Kompresja i dekompresja plików gry
Serdecznie witam wszystkich czytających ten artykuł w którym chcę opisać metodę pakowania i rozpakowywania plików gry. Metoda będzie bardzo prosta, oparta na nieskomplikowanej klasie, którą Ty czytelniku możesz sobie rozbudować… Oczywiście rozwiązanie będzie opisane w Object Pascalu i z użyciem Omegi.
Ukryte właściwości OMEGI
Przeglądając pakiet Omegi można natrafić na taki unit: LZRW1.PAS. Zawiera on bardzo ciekawe metody związane z kompresją i dekompresją danych. Zainteresowanych odsyłam do przeglądnięcia wspomnianego unit-u.
Pisząc własny edytor światów oraz oprogramowując pliki zapisu stanu gry musimy się zdecydować na sposób przechowywania danych. Najłatwiej jest to zapisać w zwykłym pliku tekstowym. Ale powstaje banalny problem: do takiego pliku każdy będzie mieć dostęp pomimo zmianie jego rozszerzenie. Aby zabezpieczyć przed manipulacjami w sercach poziomów gry pasuj zastosować kodowanie…Omega daje inne rozwiązanie. Można takie pliki spakować, a to w zupełności wystarczy. Ba dodatkowo mamy upakowanie danych.
Tyle słowa wstępnego
Prosta klasa pakera
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
TPaker=class(TLzrw1) private FSciezka:string;//sciezka i nazwa pliku kompresji lub dekompresji FStrumienWejscia, FStrumienWyjscia:TMemoryStream; public property StrumienWejscia:TMemoryStream read FStrumienWejscia write FStrumienWejscia; property StrumienWyjscia:TMemoryStream read FStrumienWyjscia write FStrumienWyjscia; constructor Create(AOwner: TComponent;ASciezka:string);virtual; destructor Destroy;override; procedure Kompresja; procedure Dekompresja(var AListaDanych:TStringList); end; |
Najważniejsze procedury tej klasy to
a) procedure Kompresja
b) procedure Dekompresja
Procedura Kompresja
Opiera się na odwołaniu do wbudowanej metody kompresji danych klasy bazowej TLzrw1 odczytany plik pakowany jest do wskazanego pliku FSciezkapo wykonaniu kilku linii kodu:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
FStrumienWejscia.Position:=0; UseStream:=true; InputStream:=FStrumienWejscia; OutputStream:=FStrumienWyjscia; Compress; FStrumienWyjscia.Position:=0; FStrumienWyjscia.SaveToFile(FSciezka); |
Tu uwaga kod przykładowego programu otwiera pliki z rozszerzeniem *.txt i pakuje je do pliku o takiej samej nazwie ale zmienionym rozszerzeniu na *.OmegaPak
Procedura Dekompresja
Ta procedura rozpakowuje pobrane dane do zmiennej typu TStringList W kodzie programu jest to zmienna o nazwie ListaDanych Jest to wygodny sposób przechowywania rozpakowanego pliku. Ponieważ mamy dostęp do pojedynczej linii pliku ListaDanych.Strings Wystarczy teraz zastosować funkcję opracowaną przez Tostera (jest gdzieś w zasobach www.unit1.pl) odczytu danych oddzielonych ustalonym separatorem i możemy tak sobie zorganizować zapis danych naszego świata, że w jednej linii będziemy mieć szereg informacji (oddzielonych np. spacją) o pojedynczej kości mapy świata gry…
Poniżej kod procedury rozpakowującej dane
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
FStrumienWejscia.LoadFromFile(FSciezka); FStrumienWejscia.Position:=0; UseStream:=true; InputStream :=FStrumienWejscia; OutputStream:=FStrumienWyjscia; Decompress; FStrumienWyjscia.Position:=0; AListaDanych.LoadFromStream(FStrumienWyjscia); |
I to wszystko. Resztę czytelniku znajdziesz w załączonym kodzie. Jeszcze jedno do projekty należy dołączyć w sekcji uses
1 2 3 |
uses ...,LZRW1, ... |
Pozdrawiam oksal Zbylitowska Góra 18. 02. 2007
PS
Jak tu nie kochać Delphi:)