Forum Média Blog Kontakt Presskit

Mapové souřadnice #2

2020-02-14

Ahoj a vítejte u druhé části našeho blogu o mapových souřadnicicích v Nebuchadnezzar. Dnes si něco povíme o rozdílu mezi prostorem obrazovky a prostorem světa a jejich vzájemných převodech.

Minule jsme probírali souřadnicový systém dílků mapy. Popisované souřadnice ale reprezentovali pouze interní uspořádání a navenek se nijak neprojevovali. Uživatel tedy nepozná jestli hra používá Staggered nebo Diamond systém. Nebo dokonce nějaký úplně jiný. Nicméně co od hry chceme je to, aby hráč všechny dílky viděl tam, kde mají být. A než si ukážeme jak na to, musíme si vysvětlit několik pojmů.

Prostor obrazovky

Prostor obrazovky je prostor toho, co vidí hráč na obrazovce. Pozice objektů v tomto prostoru jsou vztažené právě k obrazovce. Typicky má tento prostor velikost rozlišení obrazovky a jeho jednotkami jsou pixely. Počátek (nula) leží v levém horním rohu, [x] souřadnice roste směrem do prava a [y] souřadnice směrem dolů. To je rozdíl od typického prostoru v matematice, kde bývá počátek levém spodním rohu a [y] souřadnice roste směrem nahoru.

Obrazovka a její souřadnice.

Prostor světa

Prostor všech objektů ve hře popisující jejich pozici ve světě hry. Z pohledu hráče je irelevantní, kde má tento prostor počátek a jaký používá systém souřadnic. Příkladem může být třeba pozice místa kde stojí hlavní hrdina. Ovšem to, jestli hráč hrdinu uvidí, záleží na aktuální pozici a nastavení kamery snímající svět, protože právě ta rozhoduje o tom jak budou objekty světa zobrazené na obrazovce. A tomuto převodu mezi světem a obrazovkou se říká projekce.

Projekce herního světa na obrazovku.

Pokud máme izometrickou hru, kde každý objekt leží vždy na konkrétním dílku nebo skupině dílků a pokud je vždy na stejné pozici v rámci jeho aktuálního dílku nebo skupiny, stačil by souřadnicový systém dílků popsaný v předchozím blogu pro reprezentaci celé hry. To ale není příklad typické isomtrické hry a neplati to ani v Nebuchadnezzar. Příkladem můžeme být pohyb chodců, kteří přecházejí plynule z jednodo dílku na druhý a jsou tedy někdy uprostřed jednoho dílku a jindy třeba na rozhraní dvou sousedních.

Proto v Nebuchadnezzar musíme jako prostor světa uvažovat nejen jednotlivé dílky, ale i absolutní pozici ka6d0ho objektu. Přesto prostor izometrických dílků přináší mnohá usnadnění a hlavně jasnou čitelnost a přehlednost pro hráče.

Protože Nebuchadnezzar je 2D izometrická hra, je převod mezi prostorem obrazovky a prostorem světa relativně jednoduchý. Jediné dvě transformace, které naše kamera aplikuje je posun (svět na se na hráčově obrazovce posune) a přiblížení (svět se hráčově obrazovce kreslí zvětšený nebo zmenšený). O něco složetější je potom zjištení kterém dílků přísluší daná pozice v prostoru světa. Rotaci Nebuchadnezzar samozřejmě podporuje taky, ale neděje se na úrovni kamery (jak je běžné v 3D hrách), ale pomocí rotace celého prostoru světa a jeho souřadnic. Více v některém z dalších blogů.

Příklady transformací, posun a změna velikosti.

Z obrazovky do světa

Příklad situace, kdy potřebujeme převod z prostoru obrazovky na konkrétní dílek mapy. Hráč chce postavit budovu a klikne proto kurzorem myši na konkrétní místo na obrazovce. Hra musí nejdříve zjistit pozici kurzoru ve světových souřadnicích. Aplikuje proto obrácené transformace (než jaké používá při vykreslování) na pozici kurzoru. Tím získéme pozici v prostoru světa a z této pozice potom spočítáme konkrétní dílek mapy. Tady je výpočet opět složitější při použítí Staggered systému než při Diamond. Nyní máme konkrétní dílek a můžeme na něm postavit požadovanou budovu. Samozřejmě jen pokud jsou splněny všechny podmínky pro stavbu.

Tranformace z obrazovky na souřadnice dílku.

Ze světa na obrazovku

Převod z prostoru světa do prostoru obrazovky se samozřejmě nejvíce používá při vykreslování hry, protože potřebujeme hráči ukázat svět, tak jak ho "vidí" aktuální kamera.

Neváhejte se s námi podělit o jakékoliv myšlenky, nápady nebo otázky.

Níže naleznete opět několik ukázek z našeho zdrojového kódu vztahující se k popisovaným operacím. Všechny můžete libovolně použít ve svých projektech.

Souřadnice dílku ze světových souřadnic.

/**
 * @brief Get tile coordinates from world space coordinates.
 *
 * @param pos Coordinates in word space.
 */
N_Point Tile_Scene::pos2tile(const N_Point pos)
{
  const int base_x = pos.x / TILE_WIDTH;
  const int base_y = (pos.y / TILE_HEIGHT) - (pos.y < 0);
  const int off_x = pos.x - ((base_x * TILE_WIDTH) + TILE_HALF_WIDTH);
  const int off_y = pos.y - ((base_y * TILE_HEIGHT) + TILE_HALF_HEIGHT);

  const bool inside = (std::abs(off_y) != TILE_HALF_HEIGHT) && ((std::abs(off_x) / (TILE_HALF_HEIGHT - std::abs(off_y))) < 2);

  if (inside) {
    return {base_x, base_y * 2};
  }
  else {
    return {base_x - (off_x < 0), (2 * base_y) - 2 * (off_y < 0) + 1};
  }
}

Transformace mezi prostorem světa a obrazovky.

/**
 * @brief Get world space coordinates from screen space coordinates.
 *
 * @param pos Coordinates in screen space.
 */
inline N_Point screen2scene(const N_Point pos) const {
  return {
    (pos.x / scene_zoom_factor_inverted_) + scene_offset_.x, 
    (pos.y / scene_zoom_factor_inverted_) + scene_offset_.y};
}

/**
 * @brief Get screen space coordinates from world space coordinates.
 *
 * @param pos Coordinates in world space.
 */
inline N_Point scene2screen(const N_Point pos) const {
  return {
    (pos.x - scene_offset_.x) * scene_zoom_factor_inverted_, 
    (pos.y - scene_offset_.y) * scene_zoom_factor_inverted_};
}
Diskutujte o tomto příspěvku na našem fóru nebo redditu.

Add Nebuchadnezzar to wishlist

DO STEAM OBCHODU

Aktuální blog

Zůstaňte v kontaktu