Small Games (paczki i mały exe)

Prolog

W poniższym artykule są opisane tajniki tworzenia małych gier. Kursik składa się z 3 części.

1. Jakie unity mają wpływ na rozmiar EXE?
2. Jak dodatkowo zmniejszyć rozmiar EXE?
3. Jak stworzyć i zaimplementować wirtualny system plików (z kompresją zlib) na potrzeby minigierek?

Rozdział I – Unity

300 KB Exe? Delphi? I wszystko jasne. Duże rozmiary exe w Delphi są ściśle powiązane z modułami które zostały użyte w pisanym programie. Jakiś czas temu gdy jeszcze nie byłem nawet w połowie tak oświeconym człowiekiem jak jestem dziś 😉 zastanawiało mnie co można a czego nie należy dodawać do sekcji uses by zachować stosunkowo mały rozmiar pliku wykonywalnego (fajnie jest gdy minigierka zajmuje mało miejsca). Przez jedne moduły aplikacja tyje niczym młody Amerykanin po wyjściu z McDonald a przez inne nic jej nie będzie niczym po niskokalorycznej Coca-Coli Light.

Jakie unity można używać a które powinniśmy omijać szerokim łukiem? Otóż…

SysUtils

Niezbędny niezastąpiony unit. Rozmiar aplikacji rośnie zaledwie o jakieś 25 kilobajtów (bynajmniej w Delphi 7). Jest to niewielka cena za funkcjonalność. Pisząc odpowiedniki tych procedur straciłbyś mnóstwo czasu i nerwów w końcowym efekcie zyskując niewiele miejsca. SysUtils daje nam bardzo przydatne funkcje jak IntToStr, Format itd. Nie warto z niego rezygnować by zmniejszać rozmiar EXE.

Classes

Tym razem rozmiar EXE wzrośnie o jakieś 46 KB. Moduł Classes zawiera w sobie SysUtils. Classes udostępnia nam szereg bardzo przydatnych klas którymi możemy zdziałać wręcz cuda. Jeśli wiesz co daje ten unit i to co oferuje jest Ci przydatne możesz z czystym sumieniem dodać go do sekcji uses swojej małej aplikacji.

Windows, Messages, MMSystem etc.

Nagłówki od API wszelkiego rodzaju nie zmieniają zbytnio rozmiaru. Możesz używać ich bez stresu :). Chyba ze wredny autor nagłówka dołączył gdzieś w unicie w sekcji uses moduły fast-food (czyli takie od których tyje aplikacja) opisane poniżej… Unikaj ich jak ognia gdy piszesz w API…

Dialogs, Forms

Omijać szerokim łukiem! 300 KB w plecy.

To w sumie wszystko co powinieneś wiedzieć o unitach. Gdy piszesz w WinAPI i chcesz zachować mały rozmiar.

Rozdział II – Miażdżymy EXE.

Rozmiar pliku wykonywalnego można zmniejszyć nie tylko poprzez właściwe zarządzanie dołączanymi modułami w trakcie pisania kodu. Można go jeszcze bardziej zmniejszyć…

1. Użyj programu do edycji zasobów i pokasuj wszystkie zasoby. (Jeśli piszesz w API zasoby typy RCData nie mają znaczenia, natomiast jeśli piszesz program w VCL musisz je zostawić). Najlepiej do kasowana użyć Restoratora (trial version można zassać z http://www.bome.com/Restorator/.
2. Następnym krokiem ku małemu rozmiarowi EXE będzie użycie StripReloc. Można go zassać z http://www.jrsoftware.org/striprlc.php. Jeśli chcesz go użyć po prostu przeciągnij swój EXE na ikonkę programu StripReloc.
3. Ostatni a zarazem najbardziej skutecznym narzędziem do kompresji EXE jest UPX. Możesz go pobrać ze strony http://upx.sourceforge.net/. Aby skompresować swój EXE po prostu przeciągnij go i upuść na program UPX (alternatywą jest program do kompresji „BeRoEXEPacker” dostępny pod tym adresem, znacznie wydajniejszy od UPX – ma jednak pewną wadę polegającą na tym, że niektóre antywirusy rozpoznają pliki w nim spakowane jako virusy :/ w istocie jednak program ten nie zaraża plików – nagłówek takiego pliku exe ma pewnie strukturę podobną do jednego z nich [nagłówek PE wsunięty w MZ])

To wszystko co powinieneś wiedzieć o kurczeniu exe. Jest to bardzo przydatne gdy zapragniesz umieścić swoją minigierkę na dyskietce czy też napisać demo 64k, 128k :).

Rozdział III – Pakujemy pliki gry czyli „Wirtualny System Plików”

Gry. Coś fajnego. Zasoby do gier? Binaria! Budujące ową fajną grę. Gdy gram w gry bardziej od samej gry interesuje mnie struktura katalogów i to jak autorzy ją zaprogramowali (dziwny jestem?). Można zauważyć w katalogach gry duże pliki o nieznanym rozszerzeniu, a NIE można znaleźć żadnych znanych plików jak BMP, WAV, JPG i wiele innych na których codziennie operujemy. Tak naprawdę gdzieś tam są… A dokładniej siedzą sobie w tych tajemniczych plikach o dziwnych rozszerzeniach (które najprawdopodobniej są paczkami). Czy to nie byłoby fajnie mieć wszystkie pliki gry w jednym pliku, który ponadto kompresowałby te pliki? Profesjonalne gry tak mają. A że to magazyn o kodowaniu profesjonalnych gier napiszemy taki uproszczony profesjonalny system wirtualnych plików ;).

Zapoznamy się z klasą TPic (Package Is Cool) którą przygotowałem na potrzeby artykułu. Klasa TPic znajduje się w unicie uPic. Dodatkowo napisałem mały program do tworzenia paczek „Pic v1.0” (paczkę można tylko zapisać nie można jej wczytać z powrotem. Jak ktoś jest ambitny może wzbogacić program o taką opcję). Dostajesz drogi czytelniku w swoje łapki pełny kod źródłowy unitu uPic (dobrze okomentowany – polecam analizę) jak i programu „Pic v1.0” które możesz modyfikować jak tylko zechcesz.

Do paczki możesz wgrywać pliki jak i całe katalogi. Paczka ma bardzo prostą strukturę. To po prostu tak jakby katalog który pakuje wszystkie w nim zawarte pliki, przy czym katalog ten nie może mieć w sobie katalogów (możesz to zmienić jak chcesz).

Używając programu „Pic v1.0” nie powinieneś mieć problemów ze stworzeniem paczki (nasze paczki mają rozszerzenie *.pic). Jak ją ugryźć w swojej grze? Proste. Najpierw tworzysz paczkę, następnie gdzieś na początku ją wczytujesz:

Wczytywanie z paczki jest bardzo proste. Zamiast:

Piszesz:

Zakładam że wcześniej przygotowałeś paczkę z plikiem „plik” i zainicjowałeś zmienną Pic na wzór pokazany w procedurze InitGame. Pamiętaj że zmienna Pic powinna być zasięgu globalnego. Gdy wywołujesz metodę Pic. GetFile to wielkość liter parametru (nazwa pliku) nie ma znaczenia. W paczce nie istnieją katalogi więc nazwy plików podawane w GetFile to np. ‘skoki.jpg’, ‘level01.lv’, ‘strzał.wav’ itd. W trakcie działania paczki nie można do nie dopisywać ani modyfikować istniejących plików. To wszystko. Od teraz twoje gry a raczej ich zasoby mogą mieć małe rozmiary.

Jak można zauważyć paczki są uproszczonymi paczkami *.zip (a nawet mają podobną kompresję). Nie posiadają katalogów więc nadają się raczej do gier z „umiarkowaną” liczbą plików. Do większych projektów należałoby dość znacznie przebudować przedstawiony system paczek.

Przeczytawszy ten artykuł możesz pisać naprawdę małe gry 🙂 (uPic używa unitów SysUtils Classes i zlib który też ich używa). Powodzenia.

Autor: HNB

Załączniki