Rares - devlog
Kolejny devlog leniwego programisty
Kolejny devlog leniwego programisty
wrz 1st
Postanowiłem trochę uelastycznić kod Bad World. Zamiast tworzyć tablice sprite’ów, kątów czy pozycji różnych obiektów zaprzęgnąłem do pracy wektory.
Wektory w C++ to część biblioteki standardowej. Są to twory podobne do tablic, z tym, że są dynamiczne. W razie, gdy wymagane jest dodanie nowego elementu do wektora, ten potrafi sam się powiększyć. Posiadają bardzo dużo zalet, są łatwe w obsłudze, krótko mówiąc warto je znać.
Aby skorzystać z wektorów należy dołączyć nagłówek:
#include <vector>
Deklaracja wektora wygląda tak:
std::vector<typename> vector;
Gdzie typename należy wpisać typ. Może być nim zarówno typ prosty, taki jak int czy char, ale i typ złożony, deklarowany przez użytkownika, np. klasa. I z tej drugiej możliwości skorzystałem przy projekcie. Jednak nie przechowuję w wektorze samych klas, lecz wskaźniki na nie.
std::vector<CBullet*> Ammunition; std::vector<CBullet*>::iterator AmmunitionIterator;
Deklaracje te znajdują się w klasie broni, która przechowuje powyższy wektor, który z kolei przechowuje wskaźniki na klasy pocisków. Jest to o wiele lepsze rozwiązanie niż jedna klasa pocisków, w której znajdują się tablice sprite’ów, kątów tychże pocisków, czy inne dane.
Zdziwić może druga linijka w ostatnio cytowanym kodzie.
To iterator. Jest to specjalny obiekt, pozwalający na dostęp do każdego elementu w wektorze. Może on wskazywać na początek, koniec wektora, czy inny element w nim zawarty. Dobre może być porównanie iteratora do wskaźnika, chociaż należy pamiętać, że to nie to samo.
Dostęp do metod danej klasy przechowywanej w kontenerze uzyskuje się właśnie poprzez iterator.
Narysowanie wszystkich pocisków na ekranie, może odbywać się poprzez wywołanie co obieg pętli metody z klasy, na którą iterator aktualnie wskazuje.
for(AmmunitionIterator = Ammunition.begin(); AmmunitionIterator != Ammunition.end(); ++AmmunitionIterator)
{
(*AmmunitionIterator)->Draw(Application);
}
Na początek należy ustawić iterator na początek wektora. Warunek wskazuje, że pętla będzie wykonywać się dopóki nie będzie się znajdował na końcu pojemnika. Co obieg pętli inkrementujemy go, dzięki czemu mamy dostęp do następnego elementu.
Słówko trzeba też wspomnieć o tym, jak odwołujemy się do danej metody.
W powyższym przykładzie iterator odwołuje się podobnie jak wskaźnik na klasę, przeładowanym operatorem ->.
Wcześniej należy jeszcze dodać operator *, aby uzyskać adres do klasy i objąć go w nawiasy, dlatego, że operator -> ma większy priorytet od *.
Ok, miało być o wyciekach pamięci, a przerodziło się w krótki tutorial.
Otóż po wprowadzeniu wektorów pojawiły się wycieki.
Dodawanie klas wraz ze wskaźnikami do nich polega na utworzeniu nowego egzemplarza klasy za pomocą operatora new.
CBullet* pBullet = new CBullet; Ammunition.push_back(pBullet);
Druga linijka pokazuje jak dodaje się nowe elementy – wywołuje się funkcję push_back, a jako jej argument podajemy zmienną, której typ jest kompatybilny z typem kontenera. Funkcja ta dodaje nowy element na koniec wektora.
Usuwanie elementu z wektora to jedna funkcja, ale z powodu, że w pojemniku znajdują się nie tyle same obiekty, co wskaźniki do nich, trzeba jeszcze użyć operatora delete na danym egzemplarzu klasy. Ponieważ każdy element wektora został powołany do życia przez operator new, użycie wyżej wymienionego delete jest konieczne.
delete (*AmmunitionIterator); AmmunitionIterator = Ammunition.erase(AmmunitionIterator);
Podobnie jak przy odwoływaniu się do metod, należy objąć iterator w nawiasy, gdyż delete ma wyższy priorytet od dereferencji (*).
Funkcja erase usuwa element wskazany przez iterator, podany jako argument i co ważniejsze zwraca iterator do następnego elementu. Należy go więc przypisać do aktualnego.
Skąd w takim razie pojawiły się wycieki?
Z tego powodu, że wcześniej co prawda usuwałem klasy za pomocą delete, ale zapomniałem o priorytecie operatorów i brakowało nawiasów.
delete *AmmunitionIterator; // źle!
To by było na tyle.
Trochę się przedłużyło, ale w końcu mogłem napisać wpis, w którym podzieliłem się doświadczeniem. I przy okazji wypróbowałem wtyczkę SyntaxHighlighter.
sie 26th
Śledziłem poczynania Quavitora w pisaniu jego programu na konkurs i muszę przyznać, że jesteśmy w tym samym położeniu. Podobnie jak on uznałem, że nie warto tracić czasu na pisanie dokumentacji, tylko wziąć się za kod. Chociaż to może źle powiedziane. Nie warto tracić czasu na pisanie rozległych dokumentacji. Opisałem tylko podstawy, wypisałem klasy, które będą w grze i policzyłem różne rzeczy – m.in. wielkość świata gry. Z tych obliczeń wyszło mi, że mapa będzie miała wymiary 1500×1500 kafli, co daje 2250000 kafli. Dużo zajmie mi wypełnienie tego wszystkiego, ale nie jestem masochistą i nie będę pisał tego w notatniku (wersja na hardcore’a) i napiszę edytor map. Zakładając, że kafle będą miały wymiary 128×128 pikseli to mapa będzie miała 192000 pikseli w pionie i poziomie. Najszybszy samochód w grze będzie poruszał się z prędkością 330 pikseli na sekundę
, więc przejechanie mapy zajmie mu jakieś 582 sekundy, czyli prawie 10 minut. Nieźle, prawda?
A co już mam w grze? Mogę sobie pochodzić bohaterem po mapie, działają kolizje z budynkami, stoją przechodnie – tak stoją, ale jeszcze dziś postaram się oskryptować ich i będzie ciekawiej, zwłaszcza, że działa już strzelanie, choć nadaje się jeszcze do lekkiej poprawki. Poza tym mam już prosty system misji. W pliku z wszystkimi misjami znajduje się nazwa sprite ze zleceniodawcą, jego położenie, a po aktywacji misji, pobierane jest jeszcze położenie celu i nazwa sprite’a. Muszę dodać jeszcze różne warianty misji, bo na razie suche kill oznacza nie zabicie celu, tylko podejście do niego na odpowiednią odległość. Ale skoro to już działa, to reszta to tylko kwestia czasu. Najtrudniejszą rzeczą, za jaką się teraz biorę są skrypty przechodniów i samochodów jeżdżących po ulicy. Na razie nie mam na to pomysłu, ale w końcu trzeba to zrobić, więc coś wymyślę.
Prawdopodobieństwo planowanego skończenia gry na WSoC jest bliskie zeru, ale myślę, że jakieś demo z kilkoma misjami i działającymi fundamentami gry uda mi się ukończyć. Nic innego nie planowałem, teraz trochę żałuję. Może i został jeszcze miesiąc do końca COMPOtu, ale trzeba wracać do szkoły, nie będzie tyle czasu, co w wakacje.
Wrócę jeszcze do kwestii moich tutoriali. Mianowicie, planuję napisać trylogię kursów do bibliotek graficznych tzn. do SDL-a, SFML-a i Allegro. Jak mi wyjdzie zobaczymy, na razie nie skończyłem pisać tutka do SDL-a, ale mam do tego duży zapał.
sie 15th
Zacznijmy od projektowania.
Tyczy się oczywiście Bad World. Jak idzie? Jak zwykle. Projektuję tradycyjnie – w zeszycie. Powoli napisałem trochę o grze, bardziej ogólnikowo, nie przymierzałem się do szczegółów. Na razie utknąłem na m.in. fabule i misjach.
Co do SDL-a to zapewne domyślacie się, że chodzi o mój kurs. Dodałem do menu stronę z kursem, więc można go czytać. Muszę tylko zająć się poprawieniem linków na różnych stronach, na których ten tutorial jest. Jak już kiedyś obiecywałem poprawię go, dodam nowe lekcje i opublikuję w (nie) dalekiej przyszłości.
Teraz grafika. Mój stary (2 letni) GeForce 8600 GTS 512 spalił się. Wysokie temp. na zewnątrz i zepsute chłodzenie zmusiło mnie do odwiedzenia sklepu komputerowego w celu wymiany chłodzenia. Facet, który się tego podjął przeholował i karta poszła się „kochać”. Jako, że nie było to z mojej winy, dostanę teraz za darmo GeForce 8600 GTS, ale 256 od Gigabyte. Martwi mnie trochę te pasywne chłodzenia, ale czytałem opinie, że nie jest tak źle. No cóż, zobaczymy. Na razie jadę na Radeonie X300
. Jutro idę po nową kartę.
sie 3rd
Przed chwilą skończyłem dodawać moje projekty na stronę. Dodane zostały wszystkie 3 dema Bad World i Moron Fighters oraz Game Studio począwszy od wersji 0.1 do jak na razie finalnej 1.0. Czemu mówię jak na razie? Dlatego, że jakoś ostatnio naszła mnie chęć, żeby dopisać trochę tego i owego do gry. Myślę, że nie wszystko zostało dokończone, że jeszcze coś można zrobić, a gra będzie sprawiała lepsze wrażenie. Zresztą na stronie Game Studio zamieszczone jest źródło gry, co prawda kod jest beznadziejnie zorganizowany, wszystko jest oparte na jednym wielkim singletonie i jednej klasie, ale jest przejrzyście i da się jeszcze na nim pracować.
Projekty można ściągnąć z działu „Projekty” z głównego menu na górze strony – nikt nie będzie miał problemu z odnalezieniem.
lip 31st
Postanowiłem niedawno wypróbować nowej wersji IDE od MS – Visual Studio z tego roku. Na początku ujrzałem to, czego się spodziewałem, tzn. VS 2008 z nowym wyglądem. I nadal tak czuję. Wszystko jest na tym samym miejscu, więc łatwo się przyzwyczaić.
Do jednego mam zastrzeżenie – do szybkości. Stary Visual odpalał się o wiele szybciej, co prawda o parę sekund, ale jednak szybciej. Nie jest to aż taka duża wada, żebym zaraz wracał do wcześniejszej wersji. Jednak, jeśli ktoś się zastanawia nad zmianą, to śmiało może zainstalować 2010-tkę.
Wkrótce potem trzeba było wziąć się za projekty. Na pierwszy ogień poszedł Bad World. Standardowo, odpaliłem projekt, Visual przekonwertował solucję i prawie można było kodzić. No właśnie – prawie. A to dlatego, że musiałem przekompilować całą bibliotekę, z której gra korzysta, tzn. SFML 1.6. Pojawiły się liczne problemy, pisałem o tym na Warsztacie:
http://forum.gamedev.pl/index.php/topic,18095.0.html
Szukałem w sieci gotowej, skompilowanej biblioteki w wersji 1.6 do VC 2010, ale znalazłem tylko wersję 2.0. Wolałem zostać przy starszej, więc kombinowałem. W końcu się udało. W razie gdyby ktoś miał podobny problem to wrzuciłem na serwer paczkę z libami:
lip 30th
Postanowiłem zarejestrować nową domenę i niestety coś poszło nie tak. Nie jestem specem od sieci, zacząłem grzebać w przeróżnych ustawieniach DNS-a i blog szlag trafił. Ale to już nieważne, zainstalowałem na nowo WordPressa i mam działającą domenę. Teraz adres jest jeszcze krótszy, a to wszystko jest za darmo. Mowa o domenach ze strony dot.tk. Do niedawna służyły tylko jako aliasy, ale teraz jako domeny są świetną alternatywą dla tych płatnych.
Blog zaczynam pisać od nowa, ale to niewielka strata w porównaniu z tak krótkim adresem. Dobrze, że dysk mi nie poszedł (odpukać). Wtedy to byłaby wielka strata – nie robiłem jeszcze kopii zapasowych projektów
.
Jak już wcześniej pisałem, na starym blogu w ten weekend mam zamiar napisać design doc Bad World. Słowa dotrzymam i podzielę się z wami moimi postanowieniami.
Niebawem dodam stronę ze starymi projektami. Gry nadal są na serwerze, tylko, że nikt nie ma do nich dostępu.
To na razie tyle, od teraz na mój blog można dostać się przez adres – www.rares.tk