233 орешка для Золушки: отбираем цвета для «идеальной» палитры



    В процессе разработки игры в текстовом режиме, мне пришлось нарисовать больше сотни анимационных ASCII спрайтов. После релиза игра получила неожиданно хорошие отзывы и было принято решение делать продолжение. Рисуя спрайты для первой части и перепробовав с десяток вариантов выбора цвета и несколько десятков различных палитр, я понял, что нужен свой, «идеальный» набор цветов на все времена. За сотни и сотни часов рисования, сложились следующие критерии идеальности палитры:

    • Краткость: небольшое количество цветов в палитре. Весь набор цветов можно охватить одним взглядом.
    • Полнота: цвета палитры должны равномерно и достаточно плотно заполнять цветовое пространство.
    • Дискретность: цвета палитры должны отличаться друг от друга на глаз.
    • Группировка: цвета должны быть удобно сгруппированы для быстрого нахождения нужного.

    Оказалось, что можно подобрать набор из ровно 233 цветов, который удовлетворит всем этим критериям.

    Начиная отбирать цвета, взглянем на все цветовое пространство. Его можно представить в виде RGB куба, HSB цилиндра/конуса — и это только самые популярные аддитивные модели.



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



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



    Итак, нужна дискретная палитра. Различных палитр — великое множество. Это как современные палитры, так и ретро палитры, пришедшие из прошлого компьютерной техники.



    Не смотря на все многообразие, я не нашел палитру, которая бы удовлетворяла моим требованиям. Это и не удивительно. Ретро палитры определялись возможностями железа. Современные же палитры составляются, как правило, для целей реализации определенного стиля в дизайне.

    Большинство графических редакторов позволяют формировать пользовательские палитры. Но встроенных возможностей группировки цветов палитры оказалось не достаточно для моих целей. Итак, я принял решение собрать палитру сам.

    Процедурная палитра?


    Что, если равномерно распределить точки-цвета палитры внутри цветового пространства? Например, каждую компоненту цвета в модели RGB разделить на 6 частей. Получится 216 цветов.

    Проблема в том, что человек воспринимает цвета не линейно. Зеленые оттенки палитры «сольются», а синие будут слишком дискретны. Вот интересный материал, посвященный цветам:

    Poynton's Color FAQ

    Только ручной отбор!


    Разработанная в 70-ых годах модель HSB, являющаяся нелинейным преобразованием модели RGB, позволяет намного более интуитивно выбирать цвета. Первым компонентом модели является Hue – Цветовой тон. Какие бывают цветовые тона? Например, как в мнемонической фразе: «Каждый охотник желает знать, где сидит фазан».

    7 цветовых тонов: Красный, Оранжевый, Желтый, Зеленый, Голубой, Синий, Фиолетовый

    Этого явно мало! А где, например, розовый или бирюзовый? Более полный набор из 12-ти тонов дает палитра «циферблата», где каждому часу на циферблате соответствует свой цвет.

    12 цветовых тонов: Красный, Оранжевый, Желтый, Лайм, Зеленый, Аквамарин, Бирюзовый, Голубой, Синий, Фиолетовый, Розовый, Малиновый

    Полученные значения Hue все еще слишком дискретны. Я добавил несколько тонов, чтобы разница на глаз между соседними тонами была одинакова. Теперь результат меня устроил.

    15 цветовых тонов: Красный, Оранжевый, Золотой, Желтый, Лайм, Зеленый, Аквамарин, Бирюзовый, Голубой, Синий, Ультрамарин, Фиолетовый, Розовый, Малиновый, Алый



    Для каждого из 15-ти цветовых тонов можно задавать компоненты Saturation – Насыщенность и Brightness – Яркость. Вот, например, множества значений насыщенности и яркости для оранжевого, фиолетового и лайма.



    Существует известная палитра, в которой компоненты насыщенности и яркости вытянуты в одну линию.



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

    Интересно, что цвета этой палитры образуют поверхность цилиндра/конуса модели HSB. Цвета из внутренних частей цилиндра/конуса — отсутствуют.

    Вернемся к нашим 15-ти цветовым тонам. Построим для каждого дискретную раскладку по компонентам яркости и насыщенности. Значения компонент выберем равномерно следующим образом: 100%, 80%, 60%, 40%, 20%.



    Часто, пространство значений яркости и насыщенности представляют не в виде квадрата, а в виде треугольника. Дело в том, что глаз человека хуже различает изменение насыщенности при более низкой яркости.

    В нашем случае, треугольник получается так: для ряда с более низкой яркостью предоставляется меньше вариантов насыщенности.



    Неплохо! Теперь приступим к более тонкой настройке. Для каждого тона, компоненты яркости и насыщенности были распределены равномерно. Но глаз человека воспринимает яркость нелинейно. Более того, для разных цветовых тонов восприятие яркости — разное.

    Одной, наиболее часто применяемой формулой для оценки яркости цвета, является следующая:



    Надо понимать, что яркость цвета зависит как от типа монитора, так и от индивидуальных особенностей зрения человека, а эта формула была выведена еще для CRT мониторов. Тем не менее, она отражает тот факт, что вклад в общую яркость синего компонента меньше чем вклад красного, который, в свою очередь, меньше вклада зеленого. Это видно невооруженным взглядом, достаточно, например, сравнить синий цвет с яркостью 20% и зеленый с яркостью 20%. Синий гораздо темнее!

    Для того, чтобы выровнять темные цвета и сделать визуальное уменьшение яркости более линейным, я применил следующее преобразование:





    Формула выглядит слегка громоздко, но на самом деле она простая. На вход подается уровень яркости Y, цветовой тон (r, g, b), а так же количество градаций яркости n. Внутри больших скобок происходит выравнивание темных цветов в зависимости от тона. Возведение в степень 0.7 делает изменение яркости более равномерным визуально. Степени 0.15 и 0.7 я подбирал вручную, пытаясь добиться лучшего результата.

    Для выравнивания насыщенности мне было достаточно следующего простого преобразования:



    Степень 0.65 так же подбиралась вручную. На представленной ниже GIF анимации приводится вариант до преобразования и после. Фон я сделал черным, чтобы лучше были видны темные цвета. Судите сами, стали ли цвета по яркости и насыщенности более равномерно распределены. На мой взгляд — да, стало лучше.



    Осталось добавить оттенки серого и сгруппировать полученные цвета. В итоге получилась такая палитра.



    Я получил 233 орешка для золушки — 233 цвета для редактора ASCII графики, которая — прекрасна!

    RGB представление цветов палитры в виде JSON
    {
        "Алый": [
            [
                {"r": 255, "g": 0, "b": 85},
                {"r": 179, "g": 0, "b": 59},
                {"r": 131, "g": 0, "b": 43},
                {"r": 91, "g": 0, "b": 30},
                {"r": 54, "g": 0, "b": 18}
            ],
            [
                {"r": 255, "g": 79, "b": 138},
                {"r": 179, "g": 55, "b": 96},
                {"r": 131, "g": 41, "b": 71},
                {"r": 91, "g": 28, "b": 49}
            ],
            [
                {"r": 255, "g": 124, "b": 168},
                {"r": 179, "g": 87, "b": 118},
                {"r": 131, "g": 64, "b": 86}
            ],
            [
                {"r": 255, "g": 162, "b": 193},
                {"r": 179, "g": 114, "b": 135}
            ],
            [
                {"r": 255, "g": 195, "b": 215}
            ]
        ],
        "Малиновый": [
            [
                {"r": 255, "g": 0, "b": 162},
                {"r": 178, "g": 0, "b": 113},
                {"r": 130, "g": 0, "b": 82},
                {"r": 89, "g": 0, "b": 56},
                {"r": 52, "g": 0, "b": 33}
            ],
            [
                {"r": 255, "g": 79, "b": 191},
                {"r": 178, "g": 55, "b": 133},
                {"r": 130, "g": 40, "b": 97},
                {"r": 89, "g": 27, "b": 67}
            ],
            [
                {"r": 255, "g": 124, "b": 207},
                {"r": 178, "g": 87, "b": 145},
                {"r": 130, "g": 63, "b": 106}
            ],
            [
                {"r": 255, "g": 162, "b": 221},
                {"r": 178, "g": 113, "b": 154}
            ],
            [
                {"r": 255, "g": 195, "b": 233}
            ]
        ],
        "Розовый": [
            [
                {"r": 255, "g": 0, "b": 255},
                {"r": 177, "g": 0, "b": 177},
                {"r": 129, "g": 0, "b": 129},
                {"r": 87, "g": 0, "b": 87},
                {"r": 50, "g": 0, "b": 50}
            ],
            [
                {"r": 255, "g": 79, "b": 255},
                {"r": 177, "g": 55, "b": 177},
                {"r": 129, "g": 40, "b": 129},
                {"r": 87, "g": 27, "b": 87}
            ],
            [
                {"r": 255, "g": 124, "b": 255},
                {"r": 177, "g": 86, "b": 177},
                {"r": 129, "g": 63, "b": 129}
            ],
            [
                {"r": 255, "g": 162, "b": 255},
                {"r": 177, "g": 113, "b": 177}
            ],
            [
                {"r": 255, "g": 195, "b": 255}
            ]
        ],
        "Фиолетовый": [
            [
                {"r": 170, "g": 0, "b": 255},
                {"r": 119, "g": 0, "b": 179},
                {"r": 88, "g": 0, "b": 132},
                {"r": 61, "g": 0, "b": 92},
                {"r": 37, "g": 0, "b": 56}
            ],
            [
                {"r": 196, "g": 79, "b": 255},
                {"r": 138, "g": 56, "b": 179},
                {"r": 102, "g": 41, "b": 132},
                {"r": 71, "g": 28, "b": 92}
            ],
            [
                {"r": 211, "g": 124, "b": 255},
                {"r": 149, "g": 88, "b": 179},
                {"r": 110, "g": 65, "b": 132}
            ],
            [
                {"r": 224, "g": 162, "b": 255},
                {"r": 158, "g": 114, "b": 179}
            ],
            [
                {"r": 235, "g": 195, "b": 255}
            ]
        ],
        "Ультрамарин": [
            [
                {"r": 98, "g": 0, "b": 255},
                {"r": 70, "g": 0, "b": 182},
                {"r": 52, "g": 0, "b": 136},
                {"r": 37, "g": 0, "b": 98},
                {"r": 24, "g": 0, "b": 63}
            ],
            [
                {"r": 146, "g": 79, "b": 255},
                {"r": 105, "g": 56, "b": 182},
                {"r": 78, "g": 42, "b": 136},
                {"r": 56, "g": 30, "b": 98}
            ],
            [
                {"r": 174, "g": 124, "b": 255},
                {"r": 124, "g": 89, "b": 182},
                {"r": 93, "g": 67, "b": 136}
            ],
            [
                {"r": 198, "g": 162, "b": 255},
                {"r": 141, "g": 116, "b": 182}
            ],
            [
                {"r": 218, "g": 195, "b": 255}
            ]
        ],
        "Синий": [
            [
                {"r": 0, "g": 0, "b": 255},
                {"r": 0, "g": 0, "b": 187},
                {"r": 0, "g": 0, "b": 145},
                {"r": 0, "g": 0, "b": 109},
                {"r": 0, "g": 0, "b": 76}
            ],
            [
                {"r": 79, "g": 79, "b": 255},
                {"r": 58, "g": 58, "b": 187},
                {"r": 45, "g": 45, "b": 145},
                {"r": 34, "g": 34, "b": 109}
            ],
            [
                {"r": 124, "g": 124, "b": 255},
                {"r": 91, "g": 91, "b": 187},
                {"r": 71, "g": 71, "b": 145}
            ],
            [
                {"r": 162, "g": 162, "b": 255},
                {"r": 119, "g": 119, "b": 187}
            ],
            [
                {"r": 195, "g": 195, "b": 255}
            ]
        ],
        "Голубой": [
            [
                {"r": 0, "g": 145, "b": 255},
                {"r": 0, "g": 100, "b": 176},
                {"r": 0, "g": 72, "b": 128},
                {"r": 0, "g": 49, "b": 86},
                {"r": 0, "g": 27, "b": 48}
            ],
            [
                {"r": 79, "g": 179, "b": 255},
                {"r": 55, "g": 124, "b": 176},
                {"r": 39, "g": 90, "b": 128},
                {"r": 26, "g": 60, "b": 86}
            ],
            [
                {"r": 124, "g": 198, "b": 255},
                {"r": 86, "g": 137, "b": 176},
                {"r": 62, "g": 99, "b": 128}
            ],
            [
                {"r": 162, "g": 215, "b": 255},
                {"r": 112, "g": 149, "b": 176}
            ],
            [
                {"r": 195, "g": 229, "b": 255}
            ]
        ],
        "Бирюзовый": [
            [
                {"r": 0, "g": 255, "b": 255},
                {"r": 79, "g": 255, "b": 255},
                {"r": 124, "g": 255, "b": 255},
                {"r": 162, "g": 255, "b": 255},
                {"r": 195, "g": 255, "b": 255}
            ],
            [
                {"r": 0, "g": 173, "b": 173},
                {"r": 62, "g": 173, "b": 173},
                {"r": 97, "g": 173, "b": 173},
                {"r": 127, "g": 173, "b": 173}
            ],
            [
                {"r": 0, "g": 121, "b": 121},
                {"r": 53, "g": 121, "b": 121},
                {"r": 83, "g": 121, "b": 121}
            ],
            [
                {"r": 0, "g": 78, "b": 78},
                {"r": 44, "g": 78, "b": 78}
            ],
            [
                {"r": 0, "g": 38, "b": 38}
            ]
        ],
        "Аквамарин": [
            [
                {"r": 0, "g": 255, "b": 170},
                {"r": 79, "g": 255, "b": 196},
                {"r": 124, "g": 255, "b": 211},
                {"r": 162, "g": 255, "b": 224},
                {"r": 195, "g": 255, "b": 235}
            ],
            [
                {"r": 0, "g": 173, "b": 115},
                {"r": 62, "g": 173, "b": 136},
                {"r": 98, "g": 173, "b": 148},
                {"r": 127, "g": 173, "b": 158}
            ],
            [
                {"r": 0, "g": 122, "b": 81},
                {"r": 53, "g": 122, "b": 99},
                {"r": 83, "g": 122, "b": 109}
            ],
            [
                {"r": 0, "g": 79, "b": 52},
                {"r": 44, "g": 79, "b": 67}
            ],
            [
                {"r": 0, "g": 40, "b": 26}
            ]
        ],
        "Зеленый": [
            [
                {"r": 0, "g": 255, "b": 0},
                {"r": 79, "g": 255, "b": 79},
                {"r": 124, "g": 255, "b": 124},
                {"r": 162, "g": 255, "b": 162},
                {"r": 195, "g": 255, "b": 195}
            ],
            [
                {"r": 0, "g": 174, "b": 0},
                {"r": 62, "g": 174, "b": 62},
                {"r": 98, "g": 174, "b": 98},
                {"r": 128, "g": 174, "b": 128}
            ],
            [
                {"r": 0, "g": 124, "b": 0},
                {"r": 54, "g": 124, "b": 54},
                {"r": 84, "g": 124, "b": 84}
            ],
            [
                {"r": 0, "g": 81, "b": 0},
                {"r": 46, "g": 81, "b": 46}
            ],
            [
                {"r": 0, "g": 42, "b": 0}
            ]
        ],
        "Лайм": [
            [
                {"r": 196, "g": 255, "b": 0},
                {"r": 214, "g": 255, "b": 79},
                {"r": 224, "g": 255, "b": 124},
                {"r": 233, "g": 255, "b": 162},
                {"r": 241, "g": 255, "b": 195}
            ],
            [
                {"r": 131, "g": 171, "b": 0},
                {"r": 146, "g": 171, "b": 61},
                {"r": 154, "g": 171, "b": 97},
                {"r": 161, "g": 171, "b": 126}
            ],
            [
                {"r": 91, "g": 119, "b": 0},
                {"r": 104, "g": 119, "b": 52},
                {"r": 110, "g": 119, "b": 81}
            ],
            [
                {"r": 57, "g": 75, "b": 0},
                {"r": 67, "g": 75, "b": 42}
            ],
            [
                {"r": 27, "g": 35, "b": 0}
            ]
        ],
        "Желтый": [
            [
                {"r": 255, "g": 255, "b": 0},
                {"r": 255, "g": 255, "b": 79},
                {"r": 255, "g": 255, "b": 124},
                {"r": 255, "g": 255, "b": 162},
                {"r": 255, "g": 255, "b": 195}
            ],
            [
                {"r": 170, "g": 170, "b": 0},
                {"r": 170, "g": 170, "b": 61},
                {"r": 170, "g": 170, "b": 96},
                {"r": 170, "g": 170, "b": 125}
            ],
            [
                {"r": 118, "g": 118, "b": 0},
                {"r": 118, "g": 118, "b": 51},
                {"r": 118, "g": 118, "b": 80}
            ],
            [
                {"r": 73, "g": 73, "b": 0},
                {"r": 73, "g": 73, "b": 41}
            ],
            [
                {"r": 33, "g": 33, "b": 0}
            ]
        ],
        "Золотой": [
            [
                {"r": 255, "g": 170, "b": 0},
                {"r": 255, "g": 196, "b": 79},
                {"r": 255, "g": 211, "b": 124},
                {"r": 255, "g": 224, "b": 162},
                {"r": 255, "g": 235, "b": 195}
            ],
            [
                {"r": 173, "g": 115, "b": 0},
                {"r": 173, "g": 136, "b": 62},
                {"r": 173, "g": 148, "b": 98},
                {"r": 173, "g": 157, "b": 127}
            ],
            [
                {"r": 122, "g": 81, "b": 0},
                {"r": 122, "g": 99, "b": 53},
                {"r": 122, "g": 109, "b": 83}
            ],
            [
                {"r": 78, "g": 52, "b": 0},
                {"r": 78, "g": 67, "b": 44}
            ],
            [
                {"r": 39, "g": 26, "b": 0}
            ]
        ],
        "Оранжевый": [
            [
                {"r": 255, "g": 94, "b": 0},
                {"r": 255, "g": 144, "b": 79},
                {"r": 255, "g": 172, "b": 124},
                {"r": 255, "g": 196, "b": 162},
                {"r": 255, "g": 217, "b": 195}
            ],
            [
                {"r": 175, "g": 64, "b": 0},
                {"r": 175, "g": 104, "b": 63},
                {"r": 175, "g": 127, "b": 99},
                {"r": 175, "g": 146, "b": 129}
            ],
            [
                {"r": 126, "g": 46, "b": 0},
                {"r": 126, "g": 81, "b": 54},
                {"r": 126, "g": 100, "b": 86}
            ],
            [
                {"r": 83, "g": 30, "b": 0},
                {"r": 83, "g": 60, "b": 47}
            ],
            [
                {"r": 45, "g": 16, "b": 0}
            ]
        ],
        "Красный": [
            [
                {"r": 255, "g": 0, "b": 0},
                {"r": 255, "g": 79, "b": 79},
                {"r": 255, "g": 124, "b": 124},
                {"r": 255, "g": 162, "b": 162},
                {"r": 255, "g": 195, "b": 195}
            ],
            [
                {"r": 180, "g": 0, "b": 0},
                {"r": 180, "g": 64, "b": 64},
                {"r": 180, "g": 101, "b": 101},
                {"r": 180, "g": 132, "b": 132}
            ],
            [
                {"r": 133, "g": 0, "b": 0},
                {"r": 133, "g": 57, "b": 57},
                {"r": 133, "g": 90, "b": 90}
            ],
            [
                {"r": 93, "g": 0, "b": 0},
                {"r": 93, "g": 52, "b": 52}
            ],
            [
                {"r": 57, "g": 0, "b": 0}
            ]
        ]
    }
    

    Буду рад видеть вас в своей группе textpuzzlelab на Фейсбуке, где можно посмотреть как я применяю цвета этой палитры в изображениях в стиле ASCII.



    Работа над палитрой еще не закончена. Текущая версия 0.8. Одной из проблем является то, что при изменении насыщенности, критерий дискретности не совсем выполняется для желтого, лайма, зеленого, аквамарина и бирюзового. Пока не придумал как быть.

    С радостью приму замечания и предложения. Одна пара глаз хорошо, а две и больше — лучше!
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 43
    • +2
      У меня ASCII графика всегда вызывает теплые воспоминания о Turbo Pascal 6.0 =)
      • +1
        А у меня воспоминания о тёплом ламповом Бейсике с зелёной псевдографикой на чёрном экране.
        • 0
          Делаю в игре зеленый спец. режим:
    • 0
      А саму игру можно увидеть?
      • 0
        Да, вот на Стиме:
        Proto Raider
        • 0
          Вопрос немного не по теме, но почему решили работать со стимом через издателя, а не самостоятельно?
          • 0
            Первый раз тогда выходил на Стим — сам побоялся. Теперь планирую самостоятельно.
            • +1
              А издатель как-то финансировал разработку?
    • 0
      > Существует известная палитра, в которой компоненты насыщенности и яркости вытянуты в одну линию.

      А существует ли для этой палитры раскладка RGB цветов для элементов дискретного пространства? Или может быть там как-то алгебраически можно рассчитать цвет?
      • 0
        Палитра устроена так:
        • Hue меняется по горизонтали от 0 до 360 градусов
        • Saturation — уменьшение вверх до 0
        • Brightness — уменьшение вниз до 0

        Далее, HSB в RGB можно перевести так:
        Ссылка
      • +2
        Расскажите, пожалуйста, как у вас устроены сами спрайты? Это именно спрайты, то есть картинки, которые вы рисовали в фотошопе, люстре или чём там и потом вставляли в движок, или используется какой-нибудь аналог curses с честным выводом текста?
        • +1
          ASCII спрайты — это честные символы с дополнительной информацией о цвете каждого. Спрайты я делал в обычном текстовом редакторе с моноширинным шрифтом. Выводятся в игре они уже движком, посимвольно с помощью шрифта, который можно выбирать. Вот, например, как храниться спрайт:
          javascript
          var bossDoctor = {
          	frameTime: 500,       // Duration of one frame in msec.
          	sprites: [[                  // Array of frames
          		".--.",                // Each frame is array of regular strings
          		"'oO'",
          		' "| ',
          		"/[]|",
          		" TT "
          	],[
          		".--.",
          		"'Oo'",
          		' "| ',
          		"/[]|",
          		" TT "
          	]],
          	colorsPattern: [[  // Array of colors of frames
          		"wwww",      // Each frame is an array of regular strings
          		"wggw",      // Characters in the strins are indexes of colors from "colorPresets"
          		" g. ",
          		" aa ",
          		" ss "
          	],[
          		"wwww",
          		"wggw",
          		" g. ",
          		" aa ",
          		" ss "
          	]],
          	colorPresets: {			// Colors indexes
          		"a": "888888", 
          		"s": "FF4400", 
          		"g": "00CCFF", 
          		"w": "FFFFFF", 
          		".": "444444"},
          	defaultColor: "FF8800"		// Default color for spaces in "colorsPattern"
          }
          

        • +3
          Очень приличная палитра. Жаль, что не вы создавали палитру для xterm. В то время не заморачивались и тупо порезали RGB-пространство на равномерные куски. В итоге номинально там 216 цветов, но половина из них сливается между собой и практически полностью отсутствуют темные тона. В консоле цвета — это боль…
          • +1
            Я бы тоже так поступил, очень логичное для простого программиста решение, что конечно не отменяет его херовости.
            • 0
              Смахивает на знаменитое «озвучено лучшими программистами» ©
            • +1
              И я так же делал, когда с VGA игрался: 16 основных цветов для совместимости + куб 6х6х6. Многие простые игры такую палитру использовали. Ещё нравился вариант 8х8х4 (по 3 бита на красный и зелёный, 2 бита на синий). Очень удобно для приближённого представления произвольного цвета, например, для вывода фотографий на экран.

              Понимания, что для многих задач лучше и естественнее использовать HSV в качестве универсальной палитры, а не RGB, у меня тогда ещё не было. Да и негде было посмотреть: не то, что интернета — телефона не было.
          • +1
            Похожая работа для палитр в 16 и 32 цвета:
            http://pixeljoint.com/forum/forum_posts.asp?TID=12795
            http://pixeljoint.com/forum/forum_posts.asp?TID=16247
            • +1
              Спасибо вам огромное за статью! Делаю на данный момент небольшую игру в ASCII-art и проблема с созданием палитры встала уже давно.
              • +4
                Делал для своих задач палитру, подобрал на глаз, исходя из регулярных востребованных комбинаций.
                Описание и расширенная версия.

                image

                • +1
                  Очень красивая палитра! В своё время я пытался собрать палитру из предопределённых цветов PANTONE в фотошопе, но безуспешно, а готовые наборы были либо чересчур объёмные, либо просто (субъективно) некрасивые. Тут всё же нужен талант художника, чтобы комбинировать цвета исходя из их эмоционального восприятия, а не численного описания.
              • +1
                Я в Winter Novel использовал только 16 цветов, т.к. изначально движок был только консольным и изображение выводилось в системный терминал. Палитра терминала Windows, кхм, не очень подходит для вывода таких картинок. Поэтому в OpenGL каждый цвет потом уже вытягивали вручную. И если зелёный/синий смотрятся ещё нормально, то красный/оранжевый так и остались излишне попугаистыми. Наверное, стоило изначально отказаться от Windows терминала и использовать большее количество цветов…
                image


                Кстати, а почему Proto Raider распространяется только под Windows? Если движок написан на JS, то вероятно его будет не сложно портировать под другие платформы.
                • 0
                  Proto Raider еще на старом движке написан, что позволило запустить его только под Windows и iOS. Сейчас перехожу на Cocos2d-js.
                • +2
                  Ох уж эта живучая легаси формула… Прочитал вашу статью и сразу о ней вспомнил :)
                  Там очень много толковой информации, возможно будет полезно при апгрейде вашей палитры.
                  • +1
                    Да, я привел ее с оговорками, не вдаваясь в подробности т.к. конкретные числа не принципиальны ввиду последующей ручной подборки цветов «на глаз».
                    • +1
                      Да и гамма-коррекцию стоило бы упомянуть вместо магических коэффициентов 0.15 и 0.7.
                      • 0
                        В принципе, можно было бы упомянуть, согласен.
                      • 0
                        Тоже вспомнил про эту статью.
                        Действительно, старые заблуждения могут жить вечно.
                      • +1
                        Как по мне Золотой цвет однообразен, предлагаю его в ручную пересмотреть, а после пускать эту палитру в массы, ибо действительно хорошо составлена.

                        P.S. Такие игры веют гиговской ноткой, и это хорошо. Хочется добавить, что неплохо поддержку 2К — 4К дисплеев и под них режим, где большинство уровней сразу на экране. Как на обоях, что в Facebook выложили.
                        • 0
                          Спасибо! Попробую поработать над золотым.
                        • +2
                          Забацал вот такой генератор:
                          https://htmlpreview.github.io/?https://github.com/e673/vga-palette-gen/blob/master/color.html

                          Видно сильную нелинейность цветового пространства LAB, особенно в синих тонах.

                          P.S. По рукам не бейте — я на JS вообще не умею писать.
                          • +1
                            Я только хотел про LAB написать, а вы уже готовый генератор сделали! LAB довольно интересное пространство.
                          • 0
                            А почему не стали игру делать кроссплатформенной? Пользователи *nix обычно с удовольствием покупают такие игры, а так вы потеряли часть доходов, может и не так уж много, но все же. Или есть трудности в реализации кроссплатформенного решения которые не видно на первый взгляд?
                            • 0
                              Игра Proto Raider запущена на Стиме и iOS т.ч. он кросплатформенная. Другое дело, что платформ могло быть и побольше. Все дело во времени. Такие игры не приносят прибыль — это как хобби. Поэтому сложно иногда выделать время.
                              • 0
                                А на каком языке игра написана? Java же вроде дает кроссплатформенное решение сразу? Я чайник =) могу и ошибаться =)
                                • 0
                                  Это я следующую игру на Cosos2d-js пишу, а та игра была написана на самодельном движке.
                            • +1
                              По теме статьи: мне кажется, стоит использовать разные корректировки насыщенности и яркости для левой и правой частей получившейся палитры.

                              Или, возможно, просто уменьшить количество оттенков зеленого, если мы его так плохо различаем.
                              • 0
                                Да, для зеленого тона и некоторых других, плохо различается насыщенность. Как не корректируй — ничего не помогает. Действительно, единственным способом решения проблемы является уменьшение количества градаций насыщенности. Но это испортит визуальную структуру палитры — будут дырки. Вот я и на распутье. Но скорее всего я таки «продрежу» палитру.
                              • +1
                                Просто замечательная статья и очень крутая графика в играх (как бы парадоксально это не звучало для графонозависимых).

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.