Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Оптимизация функции отрисовки тайловой карты.

Оптимизация функции отрисовки тайловой карты.

MaedПостоялецwww5 апр. 200319:19#0
  Я тут изометрический движок почти написал и вот хочу его оптимизировать. Начать оптимизацию хотелось бы с "сердца" - функции отрисовки тайловой карты.
  Карта задается статическим масивом заданной размерности. Функция отрисовки тайловой карты (далее DrawMap() ) проверяет не вылез ли тайл (полностью) за экран и если нет, то рисует тайл соответствующий элементу масива. В этой функции мне не нравится то что DrawMap() проверяет "вылезание" каждого тайла в масиве. Поэтому хотелось бы узнать есть ли способы избежать этого? Был бы благодарен за доку посвященную подобным темам.
ArochПостоялецwww5 апр. 200320:16#1
Maed
каким образом у тебя рисуется карта (меня интересуют индексы)? достаточно знать индекс тайла центра экрана и разрешение окна, размер тайла и уже из ходя из этого легко определить видимые тайлы. Дай свою ф-цию DrawMap отбросим все лишнее :)
MaedПостоялецwww5 апр. 200321:39#2
Ой, не думаю я что из нее можно что-то отбрость. Похоже ее в корне переделывать надо :(( .

int map[][] // - статический масив.

struct TileSets    //Структура, описывающая тайлы
{
  short int TileNo; //Номер (идентификатор) тайла
  short int x;     //Координаты тайла в Tiles.bmp
  short int y;     //(все тайлы находятся в нем).
} TileSet[23]

Структуру TileSets потом предполагается расширить.

void DrawMap(MGLDC *dc ,int MaxX, int MaxY )
{
int i=0;
int j=0;
int x=0;
int y=0;

//MaxX,MaxY-Разрешение экрана, может изменятся динамически.

for(j=0;j<100;j++) //600  <- Это Y, пока зафиксировано (на 100 тайлов).
{
  for(i=0;i<100;i++) //800 <-Это X, пока зафиксировано (на 100 тайлов).
  {
  x=TileSet[map[j]].x;
  y=TileSet[map[j]
].y;

  if((DeltaX+(32*i-32*j)<MaxX) & (DeltaY+(16*j+i*16)<MaxY) & (DeltaX+(32*i-32*j)>-64) &      (DeltaY+(16*j+i*16)>-32) )
  {
    MGL_transBltCoord(dc,TileDC,64*x,32*y,64*(x+1),32*(y+1),  //Что копировать
                      DeltaX+(32*i-32*j),DeltaY+(16*j+i*16),  //Куда копировать
                      trans,true);       //Флаги
  }

  }
}

}

ArochПостоялецwww6 апр. 200314:53#3
все ниже сказанное теория :) (но проверенно на практике)
int mapx, mapy; //реальные координаты мыши с учетом скролинга карты, то бишь мировые координаты
int R; //радиус прорисовки, то есть дальше этого радиуса все тайлы отбрасываются

int mx, my; //локальные координаты мыши, то есть экранныеint

/*возвращает индекс тайла, над которым мышь первый параметр ось x, второй ось y, третий отвечает за то какой индекс возвращать 1-ый или 2-ой (масссив карты же [][] ;) )*/
int Map.GetCellIndex(int, int, bool);

/*индекс центрального тайла (тот что на экране); 400 и 340 это значения длины и ширины окна пополам*/
Xp=Map.GetCellIndex(mapx-mx+400,mapy-my+340,true);
Yp=Map.GetCellIndex(mapx-mx+400,mapy-my+340,false);

/*переменные ниже необходимы для определение области прорисовки, все типа int
Xmax, Ymax - максимальный допустимый индекс тайла на карте (минимальный 1)*/
Ys=Yp-R; if (Ys<1)Ys=1;
Yf=Yp+R; if (Yf>Ymax)Yf=Ymax;
R1=Xp-R; R2=Xp+R;
UL=R1+Yp; UR=R2-Yp;
DL:=R1-Yp; DR:=R2+Yp;

//рисуем карту
for(int Y=Ys;Y<=Yf;Y++)
{
  if(Y<=Yp)
  {
      //проверка чтоб не вышли за карту
      Xs=UL-Y; if (Xs<1)Xs=1;
      Xf=UR+Y; if (Xf>Xmax)Xf=Xmax;
  }else{
      Xs=DL+Y; if (Xs<1)Xs=1;
      Xf=DR-Y; if (Xf>Xmax)Xf=Xmax
  };
  for(int X=Xs;X<=Xf;X++)
  {
  /*рисуем таил, почему сначала Y а потом X, не знаю у меня так а как это влияет если переставить я не проверял :) (у меня изначально индексы тайлов карты представлены как Y,X) поэтому если у тебя при X,Y область будет отрезаться прямоугольником у которого высота больше чем ширина то просто поменяй имена переменных с X на Y наоборот (там где они объявляются for(int Y;Y<=Yf .....) */
      draw_tile[Y,X];

  };
};
в итоге у нас должна нарисоваться прямоугольная (почему прямоугольник а не квадрат?, да потому что у нас таил 64x32 :) ) область из тайлов радиусом R. R подстраиваем под значения размеров тайлов и окна чем больше размеры тайлы и меньше размеры окна тем меньше К и наоборот, так как у нас отношение длина/ширина размеров тайла и отношение длина/ширина размеров окна не равна то неплохо было бы ввести коэффициент а то мы будем отрисовывать несколько лишних тайлов по длине или ширине (в основном по ширине :) p.s. у меня R=17 при 800x600 тайлы 64x32

Кстати все выше сказанное относилось к способу представления карты по диагонали, то есть индексы тайлов идут вот так: www.nightgod.narod.ru/map.gif (на красные и серые лини можешь не обращать внимания)

если же у тебя все идет "полосками"
то тут вообще все просто вычисляешь Xs, Xf, Ys, Yf  путем прибавления/отнимания R от XP, YP (тока не забудь вести коэффициет, он здесь тоже нежен :) )

В итоге при таком рендеринге fps нисколько не зависит от размеров карты
если что не понятно говори, поясню

MaedПостоялецwww6 апр. 200322:54#4
Вопрос(ы):
Точка 0,0 в глобальных (мировых) координатах находится в левом верхнем углу?

int Map.GetCellIndex(int, int, bool); //<-Код функции плиз. Эта функция вызывается при перемещении мыши, скролинге карты или при другом событии (каком)?

P.s. У меня, кстати, разрешение залочено на 800x600; тайлы тоже 64x32, способ представления карты - "класический" (по диагонали). И еще один вопрос по оптимизации назревает, как только я его смогу сформулировать (так чтобы понятно было) то задам :) .

ArochПостоялецwww7 апр. 20030:04#5
1) у меня она была верхним кончиком тайла [1;1]
2) http://www.gamedev.ru/forum/?action=showtopic&group=5&topic=170 (уже обсуждалось) в данном случае её уместно вызывать при скролинге карты, так как только в этом случае могут поменяться индексы центрального тайла (тот что по центру экрана, а не глобально). то есть когда камера над картой перемещается в любом другом случае не стоит.

/ Форум / Программирование игр / 2D графика и изометрия

Тема в архиве.

2001—2018 © GameDev.ru — Разработка игр