CPU3D.comКомпьютерная графикаДвухмерная графика → Создание кланов или расс юнитов в стратегиях

Создание кланов или расс юнитов в стратегиях

битые пиксели

Стандартный Windows интерфейс - GDI

Наверное, любой геймер играл в такие хиты, как WarCraft и StarCraft. Известно, что население той или иной миссии не ограничивается количеством рас в игре. Так, например, в WarCraft'e существуют всего две расы: Люди и Орки, в StarCraft'e таких рас три: Люди, Зерги, Протосы. Однако, помимо рас существуют еще и кланы, которые принадлежат одной и той же расе, но различаются между собой цветом. Вот о том, как клонировать спрайты, но сделать их различными по цвету и пойдет разговор.

Можно сделать все очень просто - наделать столько спрайтов, сколько кланов полагается в игре и вся проблема решена, но представьте себе, что в игре, которую Вы пишите, полагается сделать три расы в каждой спрайтов по 400. Если к каждой расе сделать 6 кланов, то итоговое количество спрайтов в игре станет равным: 3*400*6 = 7200. Не правда ли многовато? И хотя этот способ самый простой и, скорее всего, самый быстродейственный по результатам работы получившейся потом игры, но слишком большой расход оперативной памяти не даст Вам покоя, он будет мучить Вас и днем и ночью.

Когда у меня возникла данная проблема, я озадачился всерьез и надолго. Дело в том, что, как оказалось, у этой задачи есть великое множество решений, и выбирать один из них дело не простое, все зависит от Вашей конкретной программы, а на этапе разработки игры, трудно сказать, какой из этих способов станет Вашим лучшим и возможно вообще придется изобретать свой. Вот, что я наизобретал:
Способ 1

После создания спрайтов, те части спрайта, которые должны менять цвет, делаются серым, так чтобы составляющие цвета (R, G, B) в каждом сером пикселе были равны между собой. Вывод спрайта на экран осуществить попиксельно, проверяя в цикле каждый пиксель на принадлежность серому цвету. Если цвет не является серым вывести его на экран без изменений, если является - изменить и вывести. Например, мы хотим вывести на экран спрайт, принадлежащий красному клану:For i := 0 to Sprite.Width-1 do
For j := 0 to Sprite.Height-1 do
Begin
If Sprite.Pixels[i, j]=GrayColor then
Canvas.Pixels[i, j]:=RedColor
Else
Canvas.Pixels[i, j]:=Sprite.Pixels[i, j];
End;

При этом интенсивность красного цвета должна быть пропорциональна интенсивности серого в каждом конкретном пикселе. Вы можете написать несколько строчек кода для расчета интенсивности красного на основе серого цвета, но можете и не писать, т. к. этот способ далеко не лучший. Он накладывает ряд ограничений. Во-первых ни один находящийся в здравом рассудке человек не будет совершать попиксельный вывод на экран, т. к. быстродействие такого приложения сможет вывести из себя даже слона, во-вторых мы не сможем использовать оттенки серого цвета для изображения частей спрайта не участвующих в смене цветов( А, простите, каким цветом мы будем рисовать рыцарские доспехи и амуницию?) и в-третьих процедура расчета интенсивности нового цвета на основе интенсивности серого тоже займет порядочно времени и вызовет торможение программы.
Способ 2

Второй способ основан на цветовой ротации.
О цветовой ротации рассказано много. В основном, когда используют этот термин, имеют в виду изменение палитры в восьмибитном режиме. Иногда этот способ называют Pallete Animation. Но как бы красиво это не называлось, нам это не походит. Во-первых, я надеюсь, мы не собираемся делать игру в восьмибитном режиме, во-вторых, мы работать будем не с палитрой, а с отдельными битами цвета.

На рисунке изображено представление цвета в 24 - битном режиме. Палитра, как таковая, отсутствует, так как она не нужна. Каждый оттенок представлен одним байтом ( восемь бит). Общее количество цветов зашкаливает аж за 16 миллионов. Чем нам это может быть полезно? Вот если мы сделаем наши спрайты таким образом, чтобы те части спрайта, которые должны менять цвет в зависимости от клана, были нарисованы только оттенками одного цвета ( например только красным - первые восемь бит), то получим возможность получить другие цвета. Как это работает? Есть такая ассемблерная операция, называется циклический сдвиг. Это когда берется какое-нибудь число и биты в нем циклически переставляются, первый становится последним, второй становится первым и так далее. Иногда в обратную сторону. Так вот если у нас изменяющиеся цвета выполнены в одном только красном оттенке, то у этих пикселей биты с 1 по 8 (вернее с 0 по 7) могут быть как единицей, так и нулем. Все остальные биты заведомо будут нулями. Теперь, если мы выполним циклический сдвиг вправо на 8, то все биты красного цвета переместятся туда где расположен синий цвет, в результате чего цвет станет оттенком синего. Если сдвинем вправо на 16 или влево на 8, то биты красного цвета займут места битов зеленого цвета - цвет станет зеленым. Так, получается, чтобы получить новый цвет, требуется узнать какой цвет имеем на данный момент, вычислить, на сколько сдвигать, сдвинуть прямо на изображении в памяти и вывести картинку на экран. Все. Это очень хороший способ, основное преимущество которого состоит в том, что не требуется никаких дополнительных спрайтов или временных буферов и достаточно высока скорость выполнения, но основной его недостаток сводит на нет его преимущества - мы может получить только три клана ( синий, зеленый, красный ). Бывают ситуации, когда этого вполне достаточно ( игра Z ), но в заголовке статьи упоминается игра WarCraft, а там кланов намного больше. Есть способ лучше - РОНДО!, то есть я хотел сказать - МАСКИ!
Способ 3

Серые Маски. Этот способ основан на сложении цветов по логическим схемам И, ИЛИ ( AND, OR ). Давайте посмотрим, что получается, когда мы складываем по логическим схемам И, ИЛИ черный и серый цвета с цветовыми масками. Ну во-первых, что такое цветовая маска? Грубо говоря это цвет и есть, а на самом деле это некая битовая последовательность, где единичные биты указывают на биты принадлежащие конкретному цвету.
Ну например для красного цвета цветовая маска будет выглядеть следующим образом : 000000000000000011111111 это есть максимальная интенсивность чисто красного цвета, единички - это биты красного цвета, нули - биты других цветов. Соответственно существуют еще пять цветов.
000000001111111100000000 зеленый
111111110000000000000000 синий
000000001111111111111111 желтый
111111111111111100000000 морская волна
111111110000000011111111 темно-сиреневый

Вот такие цветовые маски могут быть использованы нами для создания кланов. В стандартном графическом интерфейсе Windows (GDI) им соответствуют цвета : clRed, clLime, clBlue, clYellow, clAqua, clFuchsia.

Теперь, если мы сложим черный цвет с какой-нибудь из маской, по системе ИЛИ, то получим ту же самую маску в качестве результата:

000000000000000000000000 OR 000000000000000011111111 = 000000000000000011111111, это неинтересно.

Гораздо интереснее если мы сложим таким же образом маску с серым цветом, в этом случае мы получим оттенок цвета маски, но немного светлее, и чем светлее серый цвет, тем светлее будет результирующий цвет вплоть до белого. Стало быть, если у нас к примеру картинка выполнена в оттенках серого цвета, то сложив каждый пиксель с маской красного цвета по системе OR, мы сделаем картинку розового цвета не исказив ее содержания. Сложим с маской синего цвета - получим голубоватую и так далее. Есть одна неприятность - черный цвет становится цветом маски, а это не всегда приемлемо. Однако в этом случае можно складывать по схеме И, при этом черный цвет как был черным так им и останется, с чем бы его ни складывали, а вот серый приобретет оттенок маски.

Эти рисунки иллюстрируют изменеие серого цвета после сложения его с маской красного цвета по системе ИЛИ и И. При этом заметно что, при сложении по системе OR результирующий цвет светлее по тону, чем исходный, а при сложении по системе AND наоборот - темнее. Как с этим справлятся я поясню дальше, а сейчас расскажу о том, каким образом данный материал может нам помочь.

Итак, предполжим у нас есть спрайт ( Рисунок слева )

Некоторые части этого спрайта должны изменять свой цвет так, чтобы определять его принадлежность к некоторому клану. Делаем серую маску тех частей, которые подвержены изменению ( Рисунок справа )

Вот так она должна выглядеть. Подобную операцию можно осуществить, практически, в любом графическом редакторе. Например: Photoshop'e. Теперь, если мы сложим данную маску по системе И (AND) с маской нужного нам цвета, маска станет не серой, а именно того цвета, который нам нужен. После этого мы можем вывести маску на спрайт, а спрайт в свою очередь вывести на экран.



Источник: http://www.delphigfx.narod.ru