16.05.2016

Motywacja

Wiele inspiracji, przy realizowaniu tego projektu, popłynęło z atari ("Robbo", "Crystal Mines 2"), amigi ("Stone Age", "Imagems") i gp2x'a ("Sqrxz").
Czyli niemodna inspiracja najczęściej prowadzi do niemodnego projektu. Mimo to, "niemodny" nie musi oznaczać "no modding".

12.05.2016

Dlaczego użyłem SDL 1.2, a nie 2.0, w tym projekcie

Próbowałem SDL'a w wersji 2.0 jakiś czas temu, w środowisku programistycznym MinGW, na Win. XP i słyszałem, że ta wersja ma jeszcze jakieś niedociągnięcia. W przypadku zaistnienia potrzeby użycia GPU jest jeszcze biblioteka SDL_gpu, która  rekompensuje brak wspomagania grafiki w SDL'u 1.2.
Poza tym, aplikacja która kładzie nacisk na użyteczność (lub długotrwałą grywalność) i nie wymaga efekciarskich bajerów wizualnych dla poklasku, może korzystać tylko z CPU, w ten sposób staje się bardziej przenośna, bez fizycznej zależności od GPU (i standardów z nim związanych) jakiejś konkretnej korporacji lub konsorcjum. Piksele to tylko piksele, są apolityczne.

7.05.2016

Przemieszczanie obiektu wizualnego

W grze przemieścić można obiekty, które niekoniecznie muszą mieć animowane sekwencje ramek, dlatego funkcje realizujące przemieszczanie są składowymi ogólnego obiektu wizualnego (zdefiniowane w "engine2d\resources.cpp").
Funkcja visObj::startMove dodaje timer z callback'iem (visObjCallback) do rzucania zdarzenia programowego EVENT_MOVE_OBJ, które jest wykorzystywane do aktualizacji macierzy sektorów, poprzez funkcję visObj::deltaMove, oraz do renderowania tego obiektu funkcją visObj::draw.

Funkcja visObj::deltaMove, oprócz modyfikowania współrzędnych, wykonuje też następujące czynności:
* Oblicza jakie jest nowe położenie obiektu w macierzy sektorów (poprzez ustawione wcześniej zmienne: dx, dy).
* Oblicza nowy rozmiar (w sektorach) zajmowany przez obiekt w macierzy sektorów (po aktualizacji współrzędnych).
* Modyfikuje kontenery sektorów ze wskaźnikami do tego obiektu (jeżeli położenie lub rozmiar obiektu wykroczył poza sektory z wcześniejszego stanu).
* Sprawdza czy przemieszczenie nie osiągnęło ustalonego wcześniej zasięgu (poprzez zmienne: x_moveRange, y_moveRange), jeżeli tak to przemieszczenie jest zastopowane za pomocą visObj::stopMove.

6.05.2016

Modernizacja obiektu wizualnego

Postanowiłem przebudować trochę sposób dostępu do struktury okna, z każdego obiektu wizualnego (w tym animacji). Pliki źródłowe, których dotyczą te modyfikacje to: "engine2d\resources.h", "engine2d\resources.cpp", "engine2d\screen.cpp" (funkcja theWindow::putOnMatrix).
Wcześniej tylko obiekt animacji typu tileSeq zawierał wskaźnik do okna. Teraz, w taki wskaźnik jest wyposażony każdy obiekt wizualny typu visObj. Pociąga to za sobą kilka zmian w sposobie  przygotowywania obiektów przy budowie mapy.

Obecnie, zainicjowanie animacji (np. dla okna planszy) wygląda w ten sposób:
someAnimation.actualVO = Game.screens[ SCREEN_GAME ].windows[ WINDOW_LEVEL ]->putSeqOnMatrix( plane, &someAnimation, posX, posY );

Bez dodatkowej linii dowiązującej tę animację do konkretnego okna:
someAnimation.win = Game.screens[ SCREEN_GAME ].windows[ WINDOW_LEVEL ];


Funkcja składowa putSeqOnMatrix jest nadbudówką funkcji putOnMatrix. Samodzielnie sprawdza, która powierzchnia stanowi aktualną ramkę animacji, poprzez zmienną actualSeq w obiekcie tileSeq.

30.04.2016

Odświeżanie animacji

Obiekt animacji typu tileSeq zawiera wskaźnik do okna (poprzez wskaźnik do aktualnej ramki actualVO), w którym ma być wyświetlany, za pomocą funkcji theWindow::redrawField. Po upływie czasu przerwy między przejściami ramek, wyświetlana i odświeżana jest kolejna ramka, poprzez funkcję składową tileSeq::draw(). Indeks tej ramki ustalany jest za pomocą sumy wartości zmiennej actualFrame w aktualnej sekwencji i zmiennej nextFrame. Jeżeli zmienna nextFrame ma wartość ujemną wtedy taka animacja będzie odtwarzana wstecz.

Jeżeli aktualna ramka osiągnie indeks graniczny, dla jej sekwencji, wtedy aktualny indeks ustawiany jest na początek w tej sekwencji (w przypadku zapętlonej animacji), lub jest wstrzymywana cała animacja (poprzez wyłączenie timera dla tego obiektu).

29.04.2016

Funkcja do sprawdzania obszaru wspólnego dwóch przestrzeni dwuwymiarowych

Funkcja do obliczania obszaru wspólnego dwóch przestrzeni dwuwymiarowych, w tym projekcie, użyta jest do sprawdzenia czy wyświetlany obiekt wizualny nie wychodzi poza okno lub widzialny obszar do odświeżenia zmian (taki obszar nie musi mieć rozmiarów całego okna). W przyszłości będzie też potrzebna do detektora kolizji.

Definicja tej funkcji znajduje się w "engine2d\resources.cpp", a jej deklaracja wygląda następująco:

bool jointField( _POS f1x, _POS f1y, _SIZE f1w, _SIZE f1h, _POS f2x, _POS f2y, _POS f2w, _POS f2h, _POS& jf1x, _POS& jf1y, _SIZE& jfw, _SIZE& jfh );

Pierwsze osiem argumentów tej funkcji to pozycja i rozmiary obydwu obszarów. Kolejne argumenty referencyjne zawierają wynikowy obszar wspólny, czyli jego pozycję (jf1x, jf1y) względem pierwszego obszaru, oraz szerokość i wysokość (jfw, jfh).
 

23.04.2016

Inicjacja timera animacji

Rozpoczęcie animacji następuje po wywołaniu funkcji składowej tileSeq::start(). Funkcja ta dodaje timer, który po upływie czasu (podanego w zmiennej interval) generuje programowe zdarzenie wychwytywane w pętli głównej (każde zdarzenie jest przetwarzane według kolejki dodania). Obsługa zdarzenia animacji jest realizowana za pomocą funkcji attendProgEvents w "events_prog.cpp", która inicjuje renderowanie ramki w określonym oknie.
Implementacja timera zależy od użytej biblioteki. W przypadku tego projektu jest to SDL_AddTimer, który umieściłem w inline'owej, zuniwersalizowanej funkcji o nazwie _ADD_TIMER. Organizację kodu w aspekcie systemu operacyjnego omówiłem już we wcześniejszej notce.