Blog (35)
Komentarze (574)
Recenzje (0)

Notatki programisty: integracja PhysicsFS z SFML

@biomenNotatki programisty: integracja PhysicsFS z SFML03.01.2017 11:50

W poniższym wpisie chciałbym przedstawić prosty sposób na wykorzystanie plików z rozszerzeniem *.zip do przechowywania zasobów, w aplikacji używającej SFML. Motywacją do wpisu był fakt że przeszukując internet, nie znalazłem gotowego działającego kawałka kodu który zapewniłby mi taką funkcjonalność. Przechodząc do konkretów, zapraszam do lektury.

PhysicsFS

Do odczytu plików z archiwum *.zip będziemy używać biblioteki PhysicsFS. Jest to otwarto-źródłowa bibliotek wydana na licencji zlib dzięki czemu możemy być pewni że nikt nie będzie wołać o otwarcie naszego kodu. Mimo iż ostatnia aktualizacja miała miejsce w 2012 roku, format *.zip jest na tyle powszechny i uniwersalny że nie jest to jakaś duża niedogodność. Co prawda można ubolewać nad brakiem rozwoju projektu gdyż, prawdopodobnie, nie doczekamy się w nim funkcjonalności zabezpieczenia archiwum, hasłem, ale na potrzeby prostej aplikacji sprawdzi się w sam raz.

Biblioteka jest rozpowszechniana w postaci kodu źródłowego, co oznacza że sami musimy ją zbudować. W poniżej przedstawionym przykładzie, do zbudowania kodu używam QtCreatora z MinGW ze skonfigurowanym Cmakem w IDE. Uważam to za bardzo wygodne połączenie gdyż całość odbywa się w jednym oknie. Instrukcję jak skonfigurować Cmake w QtCreatorze znajdziemy tutaj.

Mając przystosowane środowisko, otwieramy plik CmakeLists.txt, projekt zostaje otworzony. Wybieramy typ budowy na release gdyż interesuje nas wersja bez znaczników debugowania. Przechodząc do do zakładki Projekty, mamy możliwość spersonalizowania budowanej biblioteki. Możemy wybrać jakie formaty mają być wspierane itp. PhysicsFS poza *.zip’em, oferuje wsparcie dla kilku innych rozszerzeń, więcej informacji znajduje się na stronie projektu. Wracając do tematu głównego: zatwierdzamy konfigurację i budujemy projekt.

Jako że wybrałem w konfiguracji opcje OFF w polu PHYSFS_BUILD_STATIC, interesującym mnie wynikiem kompilacji będą pliki: libphysfs.dll oraz libphysfs.dll.a. Następnie dobrze jest uporządkować katalog bibliotek. Wyżej wspomniane pliki przerzucamy do katalogu o nazwie lib, nagłówki ze źródeł PhysicFS przenosimy do nowego katalogu o nazwie: include, całość zamykamy w folderze o nazwie physicfs.

Integracja z SFML.

Pozwolę sobie nie opisywać procesu budowania SFML’a pod QtCreatorem. Jest to dobrze wytłumaczone w podanym przeze mnie linku dotyczącym konfiguracji Cmake’a lub też jak kto woli: analogiczny do budowania PhysicsFS. Na potrzeby przykładowej aplikacji utworzymy archiwum o następującej strukturze.

[code=] data | | --- > textures (katalog zawierający pliki cpp.png oraz uszatek.png) | --- > audio (katalog zawierajacy neverwinter_theme.ogg ) [/code]

W archiwum będziemy przechowywać najpopularniejsze zasoby z których korzystają proste gry indie czyli tekstury i audio. Tworzymy projekt w QtCreatorze, dołączamy zależności i możemy przystąpić do tego co tygryski lubią najbardziej. Czyli kodu. ;) Poniżej przedstawione zostało jak będą wyglądać nasze funkcje ładujące pliki z archiwum.

[code=c++] /* Funkcja ladowania tekstur z objasnieniem. */ sf::Texture* getTextureFromZip(std::string name) { sf::Texture* texturePtr = nullptr;

/* Test czy plik istnieje w obszarze poszukiwan.*/ if(PHYSFS_exists(name.c_str())) { std::cout << name + " - exists. \n";

/* Otwieramy plik i przypisujemy do niego * wskaznik. Nastepnie odczytujemy dane do * buffora oraz ilosc danych (jak duzo ich jest) */ PHYSFS_File* fileFromZip = PHYSFS_openRead(name.c_str());

const int fileLenght = PHYSFS_fileLength(fileFromZip); char* buffer = new char[fileLenght]; int readLength = PHYSFS_read (fileFromZip, buffer, 1, fileLenght);

/* Tworzymy obiekt SFML w pamieci. */ texturePtr = new sf::Texture(); texturePtr->loadFromMemory(buffer, readLength);

/* Nie trzeba chyba tlumaczyc, prawda? ;) */ PHYSFS_close(fileFromZip);

} else { std::cout << name + " - doesn't exists. \n"; }

return texturePtr; }

/* Analogiczna funkcja dla plikow audio. */ sf::SoundBuffer* getSoundBufferFromZip(std::string name) { sf::SoundBuffer* soundBufferPtr = nullptr;

if(PHYSFS_exists(name.c_str())) { std::cout << name + " - exists. \n";

PHYSFS_File* fileFromZip = PHYSFS_openRead(name.c_str());

const int fileLenght = PHYSFS_fileLength(fileFromZip); char* buffer = new char[fileLenght]; int readLength = PHYSFS_read (fileFromZip, buffer, 1, fileLenght);

soundBufferPtr = new sf::SoundBuffer(); soundBufferPtr->loadFromMemory(buffer, readLength);

PHYSFS_close(fileFromZip);

} else { std::cout << name + " - doesn't exists. \n"; }

return soundBufferPtr; } [/code]

Myślę że komentarz zawarty w kodzie jest wystarczająco wyczerpujący. Poniżej kod naszej funkcji głównej:

[code=c++] int main(int argc, char *argv[]) { /* Zainicjuj PHYSFS i dodaj plik *.zip * do "obszaru poszukiwań". */ PHYSFS_init(nullptr); PHYSFS_addToSearchPath("data.zip", 1);

/* Funkcje zwracaja wskazniki wiec warto * sie zabezpieczyc przed ewentualnym * zapomnieniem o dealokacji pamieci. Stad * std::unique_ptr. Zakladamy ze funkcje * nie zwroci nam nullptr stad brak testu. * Co moze pojsc zle? ;) */ std::unique_ptr<sf::Texture> textureCpp( getTextureFromZip("texture/cpp.png"));

std::unique_ptr<sf::Texture> textureUszatek( getTextureFromZip("texture/uszatek.png"));

std::unique_ptr<sf::SoundBuffer> soundBufferNeverwinter( getSoundBufferFromZip("audio/neverwinter_theme.ogg"));

/* Po zakonczeniu pracy z PHYSFS * nalezy go zdeinicjalizowac. */ PHYSFS_deinit();

/* Standardowy kod apki SFML. */ sf::RenderWindow window(sf::VideoMode(600, 400, 32), "AppZip", sf::Style::Default);

sf::RectangleShape shapeCpp; shapeCpp.setSize(sf::Vector2f(150,150)); shapeCpp.setPosition(sf::Vector2f(50, 50)); shapeCpp.setTexture(textureCpp.get());

sf::RectangleShape shapeUszatek; shapeUszatek.setSize(sf::Vector2f(150,150)); shapeUszatek.setPosition(sf::Vector2f(300, 50)); shapeUszatek.setTexture(textureUszatek.get());

sf::Sound soundNeverwinterTheme; soundNeverwinterTheme.setBuffer(*soundBufferNeverwinter.get()); soundNeverwinterTheme.play();

while(window.isOpen()) { sf::Event myEvent; while(window.pollEvent(myEvent)){

if(myEvent.type == sf::Event::Closed){ window.close(); } }

window.clear(); window.draw(shapeCpp); window.draw(shapeUszatek); window.display(); }

return 0; } [/code]

Tu tak samo jak w przypadku kodu funkcji, myślę że komentarze wyczerpują temat. Po zbudowaniu aplikacji wszystko powinno wyglądać a nawet śpiewać. ;) Niestety na blogu nie zaprezentuje działającego dźwięku przez co zachęcam do własnoręcznego sprawdzenia kodu.

Podsumowanie.

W ten oto sposób dobrnęliśmy do końca. Na początku wpisu wspomniałem że biblioteka nie jest już rozwijana i prawdopodobnie nie zostanie w niej zaimplementowany mechanizm zabezpieczania archiwum hasłem. Na pocieszenie, wspomnę o tym że jeden z najlepszych hack’n’slashy ostatnich lat, Torchlight, przechowywał swoje zasoby w niezabezpieczonym pliku *.zip o ile dobrze pamiętam. Jak widać, można w komercyjnym produkcie zawierać tak "trywialne" rozwiązania.

Co więcej mógłbym zaproponować to jeżeli ktoś chciałby korzystać z PhysicsFS w większej aplikacji to warto jest go „ucywilizować” i opakować klasą ze spójnym interfejsem. Korzystanie z biblioteki w stylu strukturalnym na dłuższą metę wydaje się niewygodne i mało praktyczne.

Dzięki za uwagę. ;)

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.