Postęp prac na ten moment:
Lista problemów które udało mi się rozwiązać od ostatniego postu:
- Wyświetlanie mapy większej niż 256×256
- Znalezienie jakiegoś programu do edycji map kafelkowych, kompatybilnego z gba/nds
- Zrobienie prostego generatora poziomów
- Sprawdzanie kolizji poszczególnych kafelków z punktem x,y wyznaczonym przez dotyk na ekranie
- Znalezienie w gimpie opcji konwersji kolorów do takich, które spodobają się libnds (8 bit, indeksowane bmp/png)
Wyświetlanie mapy większej niż 256×256
Przypominając, wyświetlenie mapy kafelkowej w libnds składało się do skopiowania z pamięci tablicy (w przypadku 256 px na 256 px daje to mapę wielkości 1024, bo każdy element mapy zajmuje 8×8 pikseli) do odpowiedniego rejestru w hardwarze NDS.
Z poniższego postu:
https://www.coranac.com/tonc/text/regbg.htm
…można się dowiedzieć, że rysując mapy większe niż 256×256, trzeba rozpatrzyć specjalny przypadek – weźmy na przykład mapę 512×512 z jakiej teraz korzystam w spelunky-ds.
Dzielę moją tablicę 4096 elementów na 4 sektory, jak szachownicę. Robię to tworząc zapasową tablicę, a następnie przechodzę przez nią tak, aby dojść tylko do odpowiedniej połowy na każdej z osi (wiersz ma szerokość 64 elementów, więc dochodzę do 32). Reszta chyba jest oczywista:
Da się to skrócić, ale to dobry przykład bo widać każdą oddzielną pętlę for odpowiadającą za oddzielną część szachownicy.
Nie wiem czy to część całego standardu C++, ale zauważyłem, że jeśli nie przydzielę pamięci dla tymczasowej tablicy poprzez malloc, to całość nic nie wyświetla (żadnych błędów, po prostu jakby DMA stwierdzało że nie skopiuje tej tablicy już w runtimie), więc trzeba na to zwrócić uwagę.
Znalezienie jakiegoś programu do edycji map, który generowałby tablicę C++
Tutaj padło na program mappy:
https://tilemap.co.uk/mappy.php
Strona wygląda jakby ledwo się trzymała, więc chyba na wszelki wypadek wrzucę binarkę na moje repozytorium z dopiskiem do readme o odpowiedniej licencji i autorze.
Mappy potrzebuje tilemapy – robię ją w gimpie sklejając odpowiednie pliki i koniecznie konwertując je do .bmp, indeksowanego, 256 kolorów (8bit).
Ten sam plik, ale w formacie .png przekazuję do folderu gfx w folderze od spelunky-ds.
To co wychodzi z mappy, to tablica, którą można wkleić bezpośrednio w kod:
const short mapa[1024] = {
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4…itd.
Zrobienie prostego generatora poziomów
Tutaj wytłumaczenie generowanie spelunkowych poziomów wyłożył ktoś na youtubie, zresztą bardzo dokładnie z przykładem:
Ja napisałem jedynie szybką implementację powyższego w: source/level_layout/LevelGenerator.cpp:
https://github.com/dbeef/spelunky-ds/blob/master/source/level_layout/LevelGenerator.cpp
Sprawdzanie kolizji poszczególnych kafelków
Najmniejsza jednostka podziału grafiki w libnds to kafelek 8×8 (chociaż pewnie można zmienić to w programie grit), ale moje grafiki ze Spelunky są rozmiarów 16×16, więc aby 4 kafelki trzymały jedną logiczną część (np. dla momentów w którym niszczę cały kafelek) stworzyłem klasę MapTile:
values zawiera 4 wartości dla 4 różnych kafelków 8×8, map_index zawiera ich adresy w mapie.
Sposób wybierania adresów w mapie jest dość żmudny i nie ma co go tutaj przedstawiać, kto jest zainteresowany niech zobaczy plik LevelGenerator.cpp, w szczególności funkcje:
- generateRooms()
- mapFrame()
Mamy już pozycję każdego kafelka, można więc mając pozycje dotknięcia na ekranie sprawdzić teraz, czy któryś z nich nachodzi na ten x,y.
Trzeba pamiętać jednak o szczególe, takim jak pozycja kamery. Sprawdzając kolizję, trzeba sprawdzać pozycję x i y kafelka PLUS pozycja x i y kamery, tak jak poniżej:
To wszystko na dziś.