Itt az ígért folytatás. Ha valami itt nem látszik rendesen, a leírás alján ott egy link a teljes forrásfájlról átlátható formátumban.
Elsőként nyissuk meg a Code::Blocks-t. Hozzunk létre egy új projectet: File->New->Project...
Itt válasszuk ki az Empty Project-et. Menjünk végig a varázsló lépésein. Kérdezni fogja a mentés helyét és a projekt nevét. Ezután rákérdez a fordítóra, itt mindent hagyhatunk alapértelmezetten. Ha ezzel végeztünk, készen is van az üres projektünk.
Itt az ideje, hogy hozzáadjuk az első fájlt. File->New->File... itt válasszuk ki a C++ Source File opciót. Nyelvnek válasszuk ki a legördülő menüben a C++-t. Nevezzük el a fájlt main.cpp-nek, és a Build Targets listában jelöljük ki a Debug és a Release opciókat egyaránt, majd kattintsunk a Finnish gombra.
Most, hogy már van fájl a projektünkben, itt az ideje hogy beállítsuk a fordítót. Pong projekten bal oldalon jobb kattintásra előkerülő menüben válasszuk ki a Build Options-t. Eztán előjövő ablakban bal oldalon felül válasszuk ki a Pong opciót. Kis magyarázat: amit a Pong-ban változtatunk az a Release és a Debug fordítási opcióra is érvényes lesz. Kattintsunk a Linker fülre majd az Add gomb segítségével, egyesével írjuk be és adjuk hozzá a következőeket: sfml-system, sfml-window, sfml-graphics. Eztán nyomjunk OK-ot.
A projekt készen áll, kezdjük a kódolást. Elsőként adjuk hozzá a headereket amiket biztos használni fogunk:
{syntaxhighlighter brush:c}
#include <cstdlib>
#include <SFML/Graphics.hpp>{/syntaxhighlighter}
Ha ez megvolt, akkor a standard main függvény jön, ami egyik alkalmazásból sem hiányozhat:
{syntaxhighlighter brush:c}
int main ( int argc, char** argv )
{
return EXIT_SUCCESS;
}
{/syntaxhighlighter}
Most már futásra képes programmal rendelkezünk! Egy tanács, mindig törekedjünk arra, hogy minél előbb fusson a programunk, és a legtöbb módosítás után egyből teszteljük, hogy továbbra is sikeresen le tudjuk-e fordítani!
A játék természetesen egy ablakban fog futni, így a következő feladatunk ennek az ablaknak a létrehozása. Ezt könnyen megtehetjük, hála az SFML könyvtárnak. Mivel az ablak objektumára más fájlokból is gyakran hivatkozni fogunk, ezért globálisan deklarálom meg. Az ablakhoz a RenderWindow nevű class-t fogom példányosítani ami az sf namespace-ben található. Tehát a deklaráció valahol a main függvény felett és az include-ok alatt lesz, és így fog kinézni:
{syntaxhighlighter brush:c}sf::RenderWindow Pong;{/syntaxhighlighter}
Az objektum már készen van, és globális. Itt az ideje, hogy ténylegesen elkészítsük az ablakot!
Illesszük is be gyorsan a main függvény elejére a következőt:
{syntaxhighlighter brush:c}Pong.Create(sf::VideoMode(800, 600, 32), "Pong", sf::Style::Close, sf::WindowSettings(24,8,4));{/syntaxhighlighter}
Kis magyarázat. A RenerWindow Create metódusa hozza ténylegesen létre az ablakot, ami 4 paramétert vár. Az első az egy VideoMode típusú objektum, ami meghatározza az ablak szélességét, magasságát valamint a színmélyésget. A második paraméter az ablak címsorának a felirata. A harmadik felirat az ablak címsorának a stílusa, az sf::Style::Close azt jelenti, hogy egyedül az X jelenik meg, tehát az ablak nem újraméretezhető. Az WindowSettings beállításai az OpenGL-hez kapcsolódnak. Az első 2 számunkra most nem érdekes, különböző bufferek méretét határozzák meg, a harmadik viszont az anti-aliasing mértékét határozza meg. Minél nagyobb ez a szám, annál szebb lesz a játékunk, viszont annál nagyobb lesz a gépigénye.
Most, hogy megvan az ablakunk végezzünk is el pár beállítást. Az ablak létrehozása alá szúrjuk be a következőket:
{syntaxhighlighter brush:c}
Pong.SetFramerateLimit(120);
Pong.UseVerticalSync(true);{/syntaxhighlighter}
Az első azért hasznos, mert a játékunk egyszerű, és jó eséllyel akár 2-3 ezres FPS-eket produkál, miközben 100%on prögeti a processort és a gput. Ezzel a frame limit korlátozással megszabadulunk a fölösleges framektől, cserébe a processor és a gpu pihenhet, ezáltal remélhetőleg 0% körül lesz a programunk processorhasználata. A második pedig azért fontos, hogy a frame-ek megjelenítése előtt meggyőződjön róla a program, hogy az a frame teljes, tehét ne csússzon el a kép vízszintesen.
Eztán ha futtatjuk az alkalmazásunk még mindig nem történik semmi, ugyanis amint létrejött ez az ablak, mint aki jól végezte a dolgát, a program kilép. Ennek a megoldására egy végtelen ciklust fogunk létrehozni, ami addig tart, ameddig a program nyitva van. Adjuk hozzá a következőt a main függvényünkhöz a return és az ablak létrehozása és beállítása közé:
{syntaxhighlighter brush:c}
while (Pong.IsOpened())
{
Pong.Display();
}
{/syntaxhighlighter}
Ez azt jelenti, hogy a ameddig a mi ablakunk nyitva van, addig minden iterációban megjeleníti az ablak tartalmát (amit persze mi még nem hoztunk létre). Nézzük meg mi történik ha most elindítjuk az alkalmazást! Megkapjuk a várva várt ablakot, viszont nem tudjuk bezárni! (Illetve ha debug módban indítottuk, a szintén megjelenő terminál bezárása segítségével be tudjuk.) Ez a C++ szépsége :). A program csak arra képes, amit mi beleírtunk, márpedig mi még nem írtunk bele semmit a bezárásról!
A while cikluson belül létre fogunk hozni még egy ciklust, ami a programba érkező utasításokat fogja kezelni. Ezek az utasítások, vagy inkább események az eventek. Ehhez elöször deklaráljunk meg egy ilyen eventet a main függvényen belül, mondjuk az ablak létrehozása után:
{syntaxhighlighter brush:c} sf::Event Event; {/syntaxhighlighter}
Eztán hozzuk létre a ciklust:
{syntaxhighlighter brush:c}
while (Pong.IsOpened())
{
while(Pong.GetEvent(Event))
{
if(Event.Type == sf::Event::Closed)
Pong.Close();
}
Pong.Display();
}
{/syntaxhighlighter}
Kis magyarázat mi is történik. Addig még lefut egy ciklus, számos esemény bekövetkezhet. Ezek egy sor típusú helyre gyűlnek fel. Eztán amikor a főciklusunk odaér a while(Pong.GetEvent(Event)) részhez, a Pong.GetEvent(Event) mindig a soron következő eseményt fogja nekünk visszaadni az Event objektumunkba. Ha elfogytak a feldolgozásra váró események, akkor 0-t ad visszatérési értéknek, tehát a programunk végzett az események feldolgozásával, és újra megjeleníti az egyenlőre üres képernyőt.
Indítsuk el újra az alkalmazásunk! Immár be tudjuk zárni az X segítségével. Összegezve ameddig eljutottunk: létrehoztuk a projektet, létrehoztunk egy ablakot ami frissíti önmagát és létrehoztuk az ablak bezárási eseményének a kezelését. A következő részben meg is fogjuk tölteni ezt az ablakot :).
Ha bárkinek bármi kérdése/problémája akad bátran tegye fel. A teljes forrásfájl pedig itt elérhető: http://pastebin.com/qQdHAKBi