Тайловая графическая система /0x03

В этой части мы реализуем горизонтальный и вертикальный скроллинги.

Мне кажется, что статичное тайловое изображение 256×208 — слишком маленькое, если увеличить его размеры, то придется увеличивать разрешение самого экрана.

Скроллинг(прокрутка) используется для передвижения «камеры»(видимой области) по изображению, которое превышает разрешение «камеры».

Что ж, увеличим размер всей карты тайлов в n-раз: пусть будет вместо 16×13 -> 80×26. В пикселях размер будет: 1280x416px. Правим код:

1
2
3
4
5
struct Map{
    unsigned char tile1[26][80];
    unsigned char tile2[26][80];
    unsigned char tile3[26][80];
};

Типы скроллинга

  1. Создаем огромнейшую видео-память размером с нашу карту: 1280×416. Выводим на нее всю существующую карту, затем просто выводим отдельный участок 256×208 в настоящую видео-память.(можно без двойной буферизации).

    Скроллинг будет происходить путем смещения камеры.
  2. Воспользуемся возможностями функции drawTiles() и будем смещать видимые тайлы.

Предпочтительнее будет выбрать 2-ой вариант, так как создавать огромнейшую видео-память — очень ресурсозатратно. Реализуем!

Скроллинг

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

1
2
int16_t xScroll = 0;
int16_t yScroll = 0;

А также переменные для сдвига каждого слоя тайлов.

1
2
3
4
int16_t xCam[3] = {0,0,0}; //Сдвиг камеры по икс
int16_t yCam[3] = {0,0,0}; //Сдвиг камеры по игрек
unsigned char xBl[3] = {0,0,0}; //Блочный сдвиг
unsigned char yBl[3] = {0,0,0}; //.

Теперь нужно написать функции. Их задача: при каждом вызове изменять(+-) координаты смещения; сдвиг камер, и при значении == |16| (размер 1 тайла) изменять(+-) переменные блочного сдвига. Для чего же все это? — Если мы будем просто прокручивать изображение, то это простая, смещающаяся, 2D картинка.

Мы хотим большего! Как насчет 2.5D? (Parallax Scrolling) 2.5D графику реализовать не так уж и трудно. Так как мы имеем несколько слоев изображения, мы можем прокручивать один слой медленнее другого или наоборот. Также можно добавить статичный фон. Получится что-то наподобие этого:

Итак, слой tile1 — будет фоновым слоем, т.е его прокрутка будет медленная, слой tile2 — будет основным тайловым слоем, прокрутка с нормальной скоростью, слой tile3 — будет тоже самое, что и tile2, но рисоваться он будет самым последним. Также можно добавить слой, который будет прокручиваться с большой скоростью, но для этого придется увеличивать размер карты. Собственно функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void ScrollRight() {
   if (abs(xCam[1])>=16) {xCam[1]=0; ++xBl[1];}
     else {xCam[1]-=1;}
   if (abs(xCam[2])>=16) {xCam[2]=0; ++xBl[2];}
     else {xCam[2]-=1;}
   if (abs(xCam[0])>=32) {xCam[0]=0; ++xBl[0];}
     else {xCam[0]-=1;}
 
   ++xScroll;
}
 
void ScrollLeft() {
   if (abs(xCam[1])>=16) {xCam[1]=0; —xBl[1];}
     else {xCam[1]+=1;}
   if (abs(xCam[2])>=16) {xCam[2]=0; —xBl[2];}
     else {xCam[2]+=1;}
   if (abs(xCam[0])>=32) {xCam[0]=0; —xBl[0];}
     else {xCam[0]+=1;}
 
   —xScroll;
}
 
void ScrollDown() {
   if (abs(yCam[1])>=16) {yCam[1]=0; ++yBl[1];}
     else {yCam[1]-=1;}
   if (abs(yCam[2])>=16) {yCam[2]=0; ++yBl[2];}
     else {yCam[2]-=1;}
   if (abs(yCam[0])>=32) {yCam[0]=0; ++yBl[0];}
     else {yCam[0]-=1;}
 
   ++yScroll;
}
 
void ScrollUp() {
   if (abs(yCam[1])>=16) {yCam[1]=0; —yBl[1];}
     else {yCam[1]+=1;}
   if (abs(yCam[2])>=16) {yCam[2]=0; —yBl[2];}
     else {yCam[2]+=1;}
   if (abs(yCam[0])>=32) {yCam[0]=0; —yBl[0];}
     else {yCam[0]+=1;}
 
   —yScroll;
}

Использование — элементарное. Просто вызов функции. Теперь опять добавим изменения в карту(массив тайлов).

1
2
3
4
5
6
struct Map{
    unsigned char tile1[26][80];
    unsigned char tile2[26][80];
    unsigned char tile3[26][80];
    const uint8_t *staticback; //Указатель на статичную картинку фона.
};

Разумеется, статичная картинка должна быть размером с наш экран 256x208x8bit, однако вывод этой картинки будет возможен только при прорисовки с двойной буферизации. Тип данных картинки, тот же, что и у набора текстур(texturepack):

1
const uint8_t image[];

Внесем изменения в функцию(-и) render():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void render1() {
   memset(VGA.prebuf, 0, 256*208); //Очищаем второй буфер
   memcpy(VGA.prebuf, Map.staticback, 256*208); //Рисуем статичный фон
   drawTiles(Map.tile1, TexturePack, xCam[0]/2, yCam[0]/2, xBl[0], yBl[0], 0); //Рисуем Слой1
   drawTiles(Map.tile2, TexturePack, xCam[1], yCam[1], xBl[1], yBl[1], 0); //Рисуем Слой2
   drawTiles(Map.tile3, TexturePack, xCam[2], yCam[2], xBl[2], yBl[2], 0); //Рисуем Слой3
   memcpy(VGA.buf, VGA.prebuf, 256*208); //Копируем буфер2 в буфер1(видео-память)
}
 
void render2() {
   memset(zbuffer, 0, sizeof(zbuffer)); //Очищаем Zbuffer
   //"nop" с Zbuffer-ингом невозможен задний статичный фон.
   drawTiles(Map.tile3, TexturePack, xCam[2], yCam[2], xBl[2], yBl[2], 0); //Рисуем Слой3
   drawTiles(Map.tile2, TexturePack, xCam[1], yCam[1], xBl[1], yBl[1], 0); //Рисуем Слой2
   drawTiles(Map.tile1, TexturePack, xCam[0]/2, yCam[0]/2, xBl[0], yBl[0], 0); //Рисуем Слой1
}

Теперь у нас есть все виды скроллингов и 2.5D графика. 🙂


Все части статьи.

Вы можите оставить комментарий, или поставить трэкбек со своего сайта.

Написать комментарий

XHTML: Вы можете использовать эти теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Bug Report
Локализовано: шаблоны Wordpress