Главная » 2D графика » Создание карты в игре методом спрайтов

RSS

Создание карты в игре методом спрайтов

Если подробно рассматривать, что происходит в процедуре Draw, то вот основные моменты.
1. Сначала происходит проверка, можно ли показать данные координаты.
2. Далее, путем округления в большую сторону, получаем координаты (X1,Y1,X2,Y2). Эти координаты в системе спрайтов (т.е. 0 соответствует 0, 32 – 1, 64 – 2 … ).
3. Получаем координаты со смещением (dx,dy)
4. Выводим спрайт в координаты (dx,dy)

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

Теперь можно задаться вопросом: а за чем все это было нужно, и чем TFlur хуже?

Все очень просто, теперь появилась возможность скроллировать карту хоть по 1 пикселю, а раньше только по 32 ( т.е. по ширине спрайта карты ). При этом будет достигаться плавность перемещения.
И вот второй момент. Если Вы захотите поместить на карту объекты ( а Вы точно захотите ! ), то они могут находится на любом месте карты ( и экрана соответственно ).

Чтобы поместить на нашу карту анимированные спрайты я написал небольшой класс TSprite. Замечу что он не универсальный и далеко не совершенный. Просто для своих целей Вы можете дописать необходимые вам пункты, но я остановлюсь на этом далее.

Вот заголовок класса TSprite:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type TSprite=Class
  // Внутренние координаты спрайта, real по тому, что
  // вычисление ведется через sin и cos - достигается
  // более плавное перемещение. Возможность поворота по
  // любому углу.
  FCoordXFl,
  FCoordYFl:Real;
  // "Экранные" координаты
  FCoordX,
  FCoordY,
  FAngle:Integer;
  // FAngle - вектор направления скорости спрайта, может
  // принимать значения от 0 до 360 ( 0,45,90,135 ... 360 для данной программы)
  FSpeed:Integer; // "скорость"
  FCount:Integer; // Счетчик движений - всего 4 изображения анимации на каждое движение
  FGo:boolean; // Стоим или идем
  Imagelist:TImagelist;
  constructor Create(AX,AY,AAngle:integer);
  Procedure DrawNext(AСanvas:TCanvas;Dest:TRect);
  Procedure Rotate(AAngle:integer);
end;

Я думаю тут должно быть все понятно, но все же остановлюсь на некоторых моментах.
Для чего вводятся 2 переменные на каждую координату?
Все очень просто : спрайт выводится на экран и с координатами FCoordX и FCoordY. А FCoordXFl и FCoordYXFl нужны вот для чего: допустим спрайт движется под углом 15 градусов и его шаг 1 пиксель. При вычислении приращения его координат получаем следующее : по оси Y приращение Cos(15)*1~0.965 а по оси X Sin(15)*1~0.25 При округлении получаем по оси Y – 1, по оси X – 0! Вот так вроде двигаемся на северо-восток, а приращение только по Y. Но в принципе можно использовать только Real и потом их просто округлять.

При выполнении процедуры DrawNext передается параметр Dest:TRect – это видимая область карты, она изображена на рисунке розовым цветом. Если координаты спрайта не попадают в нее, то он не выводится.

Теперь остановимся на возможностях модернизации данного класса и других тонкостях.

  1. Количество спрайтов на одно движение должно быть как можно больше ( в моем примере их всего 4 и видно дерганность при ходьбе героя)
  2. Угол поворота в идеале 5 градусов, только тогда можно добиться очень хорошей и плавной анимации.
  3. Если Вы собираетесь писать RTS или RPG, то все параметры героя – сила, ловкость, количество маны, жизнь и т.д. так же включают в класс.
  4. Лучше всего написать один класс ‘родительский’ и от него делать все дочерние. Например класс ‘Static Sprite’ – от него можно породить магазины, дома героев, замки – для RPG и ангары, заводы – для RTS. Это проще чем писать отдельный класс для каждого нового объекта. Ну не мне вас учить ООП.
  5. Нужно включить контроль столкновений. При этом лучше всего проверять сначала просто по габаритам спрайта, а потом по его маске – ведь спрайт занимает не все пространство внутри квадрата.
  6. Спрайты включаются в список ( если их больше 1 ). Тогда с ними легче обращаться – удалять, добавлять …Например так:
1
2
3
4
5
6
7
var
SpriteList:TList;
......
SpriteList.Add(TSprite.Create(100,100,35)); // пример добавления
......
TSprite(SpriteList.Items[23]).FCoordX:=100; // доступ к спрайту 23
......

Оптимизация – как много в этом слове ! Конечно Вас не устроила скорость работы данного примера. Но я и не старался это сделать – 320×320 при 10-15 кадрах это мало. Если Вы собираетесь делать игру с разрешением 640×480 то вот способы оптимизации. Вся загвоздка в тормознутости TCanvas – по этому обойдемся без него. Самое лучшее использовать DirectX – смотрите раздел Lib и компонент DelphiX. И еще один вариант – Dib, так же смотрите в разделе Lib есть пара компонентов для работы, получается вполне приличная скорость с поддержкой всевозможных эффектов.

Дерзайте !

Вот что получилось у меня, спасибо WarLord III и Warcraft II за предоставленные спрайты. Как переделать пример для работы со спрайтами других размеров читайте в main.pas, там есть все необходимые комментарии и спрайты из игры WarCraft II.

Качайте пример вот отсюда.

Страницы : 1 2 3 4 5