Galaxy2D Tutorials Галактика 2D
Плавный скроллинг карты.

Никакая часть этой статьи не может быть переиздана или дублирована любым способом без предшествующего письменного разрешения Автора, Джим Адамса с одним исключением - Вы может отображать эту статью немодифицированной на вашей Странице в Сети для свободного общего просмотра. Это должно включать подпись автора, Jim Adams.

 

Автор, Джим Адамс, не несет ответственности за любой ущерб, непосредственно или косвенно, следующий из использования этого файла, или этой информации.

 

 

ВВЕДЕНИЕ

 

Отлично, еще одна попытка, дать вам немного новой информации. В этой статье будет кратко рассмотрен скроллинг (прокрутка) карты сделанной из клеток.

 

Я не буду показывать, как cделать процедуру рисования клеток на экране. Если вы читаете этот урок, я допускаю, что Вы уже умеете это делать. ТО, что я буду показывать – это очень простой способ использовать вашу процедуру отображения клетки. Карта будет состоять из одного уровня.

 

Также я не имею времени добавить графику, но если я получу отклик на свою статью, то я помещу в нее несколько картинок.

 

С этим всем сказано, давайте, двигаться дальше, не так ли?

 

СТРУКТУРА КАРТЫ

 

Я упомянул, что мы будем использовать очень простою однослойную карту. Она будет состоять из одной переменной - номер клетки, которую надо нарисовать в этом положении. Скажем, Вы имеете 256 клеток, нумерованных от 0 до 255.

 

  typedef struct {

    unsigned char tile_number;

  } MAP_INFO;

 

Теперь создадим массив структур карты, который фактически содержит карту. Также зададим размерность карты в памяти, через пару определений. В нашем примере - 128x128.

 

  #define  MAP_HEIGHT    128

  #define  MAP_WIDTH     128

 

  MAP_INFO map[MAP_HEIGHT][MAP_WIDTH];

 

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

 

Наша карта может быть сохранена внутри PCX файла, с размером изображения 128x128. Каждый цвет в цветовой палитре (0-255) определял бы номер клетки, какую надо рисовать. Если Вы имеете, загрузчик pcx-файлов, то можете написать подобный код:

 

  signed short map_load(char *pcx_filename)

  {

    char *pcxmapbuf;

    short i, j;

 

    if(pcx_loadimage(pcx_filename, pcxmapbuf) == -1)

      return -1;

 

    for(i = 0; i < 128; i++) {

      for(j = 0; j < 128; j++)

        map[i][j] = get_pixel(pcxmapbuf, j, i);

    }

 

    free(pcxmapbuf);

 

    return 1;

  }

 

ОТОБРАЖЕНИЕ КАРТЫ

 

Далее Вы должны иметь кроме карты в памяти также ваши клетки. Я буду думать, что Вы держите ваши клетки в массиве. Я буду использовать массив структур, например.

 

  #define NUM_TILES        256

 

  TILE_INFO tiles[NUM_TILES];

 

Чтобы выполнить отображение карты без прокрутки, Вы просто начинаете с верхнего левого угла экрана и ведете визуализацию поперек и вниз, и так пока экран не заполниться. Скажем, мы используем клетки размером 16x16 и экран имеет разрешение 320x240. Это означает, что мы поместим (320/16) 20 клеток по горизонтали и (240/16) 15 по вертикали. Это означает, что мы будем рисовать 300 клеток на экране.

 

  void map_draw(short mapx, short mapy)

  {

    short i, j;

 

    for(i = 0; i < 15; i++) {

      for(j = 0; j < 20; i++)

        tile_draw(map[mapy + i][mapx + j].tile_number, j * 16, i * 16);

    }

  }

 

В данном коде не реализована проверка на выход за границы экрана, я оставлю это Вам. Также, вы видите, что в процедуру передаются две переменные, которые указывают координаты начала вывода карты. Для нас, эти значения меняются от 0 до 127.

 

Если Вы увеличите X на единицу, то вы будете видеть, что скроллинг будет согласно размера клетки, или 16 пикселей одновременно. Мы нуждаемся в более плавной прокрутке.

 

ПЛАВНЫЙ СКРОЛЛИНГ

 

Фактически, чрезвычайно просто заменить - это на более плавную прокрутку. Первое, что мы должны сделать - гарантировать, что размеры наших клеток кратны степени 2 (2, 4, 8, 16, 32, 64, и т.д.). Это упрощает математические расчеты. Есть способы сделать другие размеры, но я имею дело с размерами кратными степени 2, поскольку они наиболее популярны.

 

Теперь создадим точную систему координат для карты. Точные координаты - просто размер клеток, или 16x16. Так что карта 128x128 является 2048x2048 в точных координатах.

 

При визуализации карты, мы принимаем, что рисуем в этих координатах. В функции визуализации надо решить, насколько пролистать все клетки, которые мы рисуем влево и вниз.

 

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

 

Именно поэтому мы используем размер клетки со степенью кратной 2. Прежде всего, когда мы хотим визуализировать карту, скажем с 100, 126, мы должны найти координату в массиве карты.

 

Поскольку точные координаты зависят от размера клетки, мы только делим на число 16, и получаем (100/16)=6, (126/16)=7. Эта клетка будет первой нарисованной в левом верхнем углу экрана.

 

  mapx = map_drawx / 16;

  mapy = map_drawy / 16;

 

Теперь создадим точный скроллинг. Если Вы заметили, есть остаток от деления. 00/16 = 6.25 и 126/16 = 7.88. Это части для точного скроллинга. Если мы берем координаты для рисования и делаем AND их с размером одной клетки минус 1, мы получим эти остатки. В нашем случае это - (100 & 15) = 4, (126 & 15) = 14.

 

  map_xoff = map_drawx & 15;

  map_yoff = map_drawy & 15;

 

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

 

Наша новая функция визуализации:

 

  void map_draw(short map_drawx, short map_drawy)

  {

    short i, j;

    short mapx, mapy;

    short map_xoff, map_yoff;

 

    mapx = map_drawx / 16;

    mapy = map_drawy / 16;

 

    map_xoff = map_drawx & 15;

    map_yoff = map_drawy & 15;

 

    for(i = 0; i < 16; i++) {

      for(j = 0; j < 21; i++)

        tile_draw(map[mapy + i][mapx + j].tile_number,

               j * 16 - map_xoff, i * 16 - map_yoff);

    }

  }

 

Вот и все, пользуйтесь на здоровье!

 

Copyright (c) 1998 by Jim Adams.  All Rights Reserved

 

PMG  26 февраля 2004 (c)  Сергей Анисимов