Skip to content
Dec 18 15

Pixel Perfect 2D в Unity

by lakmus

Секрет идеальной pixel perfect 2д графики без всяких артефактов/дрожания/пропадания пикселей/линий и т.п.
По пунктам:
1. В настройках качества (Edit-Project Settings-Quality) отключаем Anti Aliasing и Anisotropic Textures
2. Ставим компонент Pixel Perfect (он платный, но слить бесплатно можно поискав на Github по названиям файлов из поставки компонента)
3. Кидаем PixelPerfectCamera на главную камеру. Скейл лучше не трогать.
4. Настраиваем Subpixel offest у этого компонента если нужно (обычно 1)
5. У всей графики ставим Filter Mode – Point. Format – Truecolor. Generate Mip Maps – отключено.
6. Скейл косвенно редактируется во внутреннем скрипте Pixel Perfect компонента – Internal/PixelPerfect.cs через pixelsPerUnit. По умолчанию стоит 32 пикселя.

Jul 26 13

Настройка F# в Sublime Text

by lakmus

Build system:

{
    "path": "%FSBin%",
    "encoding": "CP866",
    "cmd": ["build.bat", "$file", "$file_base_name.exe"]
}

В папку с fsc.exe кладём build.bat со следующим содержимым:

@echo off
@if %1=="" exit
@if %2=="" exit

del %2

call Fsc.exe %1

IF EXIST %2 (
    call %2
)

Батник вначале удаляет exe файл, потом пытается скомпилировать исходник, а потом уже пытается запустить exe, если он появился на выходе.

Jan 22 11

Функциональные данные

by lakmus


Делаем компьютерную игру, игрок ходит по лесу. В лесу растут деревья и трава, всё как положено.
Допустим, у нас очень-очень много травы. Трава может быть разных типов: A, B, C … n. В зависимости от типа травы движок отрисовывает определённую картинку. Тип травы генерируется случайно, а не задаётся дизайнером уровня. Можно хранить объекты примерно так:

struct Grass
{
    int x, y, z;
    int type;

    Grass()
    {
        type = generator.GetRandomNumber(MAX_GRASS_TYPES);
    }

    void Draw()
    {
        Render('grass', type, x, y, z);
    }
};

Это хороший подход и он имеет право на жизнь. Но рассмотрим ситуацию, когда нужно хранить данные как можно компактнее, хоть и жертвуя скоростью рендера.
Мы можем избавиться от type, получая случайное значение на лету, выводя его из комбинированного хэша координат:

#include <boost/functional/hash.hpp>

struct Grass
{
    int x, y, z;

    void Draw()
    {
        std::size_t combined_seed = 0;

        boost::hash_combine(combined_seed, x);
        boost::hash_combine(combined_seed, y);
        boost::hash_combine(combined_seed, z);

        generator.SetSeed(combined_seed);

        const auto type = generator.GetRandomNumber(MAX_GRASS_TYPES);

        Render('grass', type, x, y, z);
    }
};
Jan 22 11

Факториал 1000000

by lakmus

Задача: найти факториал миллиона.

Находим обычный код вычисления факториала на F#.

#light

let rec factorial n =
    match n with
    | 0 -> 1
    | _ -> n * factorial (n - 1)

printfn "%A" (factorial (17))

В примерах использования обычно берут число не больше 16. А почему? Потому что при расчёте факториала 17 произойдёт переполнение и программа выведет на экран -288522240.
Хорошо, меняем тип int на BigInteger, чтобы избежать переполнения.

#light

open System.Numerics

let rec factorial n : BigInteger =
    match n with
    | _ when n = 0I -> 1I
    | _ -> n * factorial (n - 1I)

printfn "%A" (factorial (17I))

Хорошо, факториал 17 уже считает. Но при попытке подсчитать факториал миллиона выведет на экран “Process is terminated due to StackOverflowException”. Происходит переполнение стека, потому что мы всё время тащим за собой хвост “n”. Есть решение, как избавиться от этого:

#light

open System.Numerics
open System.IO

let writer = new StreamWriter("factorial.out")

let factorial (n : BigInteger) =
    let rec fact_helper (n : BigInteger) (a : BigInteger) =
        match n with
        | _ when n = 1I -> a
        | _ -> fact_helper (n - 1I) (a * n)
    fact_helper n 1I

let value = factorial 1000000I

writer.WriteLine(value.ToString())
writer.Close()

Полученное значение слишком большое, чтобы выводить его на экран, поэтому сохраняем его в файл. В ответе больше пяти миллионов цифр, расчёты заняли около двух часов. Проверить правильность можно с помощью калькулятора.