Tworzenie gry strategicznej typu Dune 2.


Poprzedni wpis (4) | Następny wpis (6)

Wpis 5 (26.09.2016)

Temat: Pierwsze prototypy oraz opis Modułów

Dzisiaj zajmiemy się dwoma rzeczami: pisaniem Prototypów podstawowych funkcji korzystających z opracowanych struktur danych oraz wstepnym opisaniem Modułów silnika (obok logicznego).

1. Prototypy

Postanowiłem najpierw napisać wszystkie niezbędne prototypy, a implementacją zajmę się dopiero na końcu. Implementacja powinna być prosta, kiedy wszystkie prototypy będą zadeklarowane. Uważam, że jest to właściwa kolejność.

Przyjrzyjmy się Mapie. Jakie funkcje będą tam potrzebne?

Po pierwsze tworzenie nowej mapy:

/* NAZWA:  UtworzMape
   OPIS:   Tworzy nową mapę o zadanych parametrach.
   ZWRACA: Adres struktury Mapa */

struct Mapa
*UtworzMape( struct ParametryMapy *parametry );
Po drugie zapis mapy! Tak, w grze będzie dostępny edytor bazujący na silniku, który umożliwi edycję map bezpośrednio w grze oraz ich odczyt i zapis.
/* NAZWA:  ZapiszMape
   OPIS:   Zapisuje mapę do pliku o podanej nazwie.
   ZWRACA: TRUE, gdy pomyślnie zapisano. */

BOOL
ZapiszMape( BYTE *nazwa, struct Mapa *mapa );
Analogicznie odczyt mapy z pliku na podstawie nazwy:
/* NAZWA:  WczytajMape
   OPIS:   Wczytuje mapę z pliku.
   ZWRACA: Adres struktury Mapa */

struct Mapa
*WczytajMape( BYTE *nazwa );
Co nam się jeszcze przyda? Na przykład dodawanie nowego Budynku o zadanych parametrach do Mapy. Rozdzielmy to na dwie funkcje: UtworzBudynek oraz PostawBudynek:
/* NAZWA:  UtworzBudynek
   OPIS:   Tworzy budynek o podanych parametrach.
   ZWRACA: Adres budynku */

struct Budynek
*UtworzBudynek( struct ParametryBudynku *parametry );
Funkcja ta tylko tworzy nową strukturę Budynek na podstawie parametrów, nie dodając go jeszcze do mapy (nie uwzględnia położenia). Stawianie budynku zostało wyodrębnione. Dzięki temu można dowiedzieć się, czy można postawić budynek w danym miejscu. Jeśli nie, można próbować w innym miejscu:
/* NAZWA:  PostawBudynek
   OPIS:   Stawia budynek na mapie.
   x:      Pozycja X na mapie
   y:      Pozycja Y na mapie
   ZWRACA: Kod błędu */

LONG
PostawBudynek( struct Mapa *mapa, UBYTE x, UBYTE y, struct Budynek *budynek );
Na pewno przyda się usuwanie budynku (np. po zniszczeniu).
/* NAZWA:  UsunBudynek
   OPIS:   Usuwa budynek z mapy.
   ZWRACA: TRUE, gdy pomyślnie usunięto */

BOOL
UsunBudynek( struct Mapa *mapa, struct Budynek *budynek );
Jeszcze przyda się funkcja pobierająca adres budynku po indeksie.
/* NAZWA:  PobierzBudynek
   OPIS:   Pobiera adres budynku.
   indeks: Numer budynku
   ZWRACA: Adres budynku lub NULL, gdy nie ma budynku o tym indeksie */

struct Budynek
*PobierzBudynek( UBYTE indeks );
To tyle odnośnie funkcji podstawowych. W przypadu budynków potrzebne nam będą jeszcze funkcje wykonywane cyklicznie. Możemy ująć to w jedną funkcję cyklu życia budynku:
/* NAZWA:  CyklZyciaBudynku
   OPIS:   Obsługuje cykl życia danego budynku. */

VOID
CyklZyciaBudynku( struct Budynek *budynek );
Ta funkcja wywoływanaby była cyklicznie (np. co 50 jednostek czasu) i obsługiwałaby cykl życia budynku (tj. obsługę postępu wznaszania, budowy, reperacji, badań, modernizacji itd.).

Prawdopodobnie ta jedna duża funkcja będzie podzielona na wiele funkcji pochodnych, celem szybszego ich wywoływania.

2. Moduły silnika

Teraz nota o Modułach gry. Opisywany dotąd Moduł to był moduł logiczny, odpowiedzialny za logiczną strukturę i działanie gry.

Potrzebny będzie nam jeszcze moduł interfejsu użytkownika odpowiedzialny za komunikację z graczem oraz moduł graficzny, odpowiedzialny za rysowanie i animację.

Cechą modułów będzie wzajemna niezależność.

Moduły jednakże muszą komunikować się ze sobą.

Animacja będzie realizowana w taki sposób, że najpierw statyczna postać mapy będzie konwertowana przez moduł graficzny na statyczną grafikę. Zaś informacja o obiektach animowanych będzie przesyłana na bieżąco (moduł graficzny będzie cały czas nasłuchiwać co każdą jednostkę czasu).

Jeśli zajdzie potrzeba narysowania czegoś nowego lub zanimowania obiektu, zostanie wysłany odpowiedni sygnał do modułu graficznego.

Moduł logiczny będzie wysyłać zapytania do modułu graficznego, czy dana modyfikacja obiektu musi zostać odzwierciedlona przez zmianę obrazu. Na przykład jeśli obiekt znajduje się poza ekranem to żadna modyfikacja obrazu nie jest potrzebna. Moduł graficzny będzie o tym wiedział.

Przykładowo jeśli jakiś budynek zostanie zniszczony, to odpowiednia informacja musi być przesłana z modułu logicznego do modułu graficznego. Moduł graficzny będzie czekał na informacje, które wymagają zmiany grafiki, czyli będzie nasłuchiwać zmiany położenia lub stanu budynków, jednostek i obiektów specjalnych (pocisków, wybuchów itp.).

Żeby uczynić taką komunikację możliwą, trzeba będzie wykorzystać system Wydarzeń, co uczynię w kolejności.

Robert Szacki e-mail: robert.szacki(małpa)gmail.com