Folytassuk a programozást rögtön az első ígérettel. A labda pályán belül tartásával. Ehhez a CBall::Move metódust fogjuk módosítani. Azt akarjuk, hogy a labda teljes egészében a pályán belül maradjon, ugyanakkor mi a középpont koordinátáit ismerjük. A teljes labda akkor van tehát belül, ha a középpontja az ablakunk széleitől legalább sugárnyi távolságra van. Mi történik, ha a labda kívül kerülne? Akkor visszarakjuk a pályára, és módosítjuk a sebességét, méghozzá úgy, hogy a sebesség vektor megfelelő komponensét negáljuk (tehát ha például az ablak aljának ütközik neki a labdánk, akkor az y irányú sebesség komponense ami eddig lefelé mutatott, az ütközés után fölfelé fog mutatni), ez olyan ütközést eredményez, amit a fizikában tökéletesen rugalmas ütközésként szoktak leírni. A pályán belül tartást csak az ablak aljára és tetejére fogjuk megírni, mivel ha a képernyő bal vagy jobb oldalának ütközik a labdánk az gólt jelent, és ekkor szimpla ütközés helyett mást fogunk csinálni. No de nézzük, hogy hogyan fog kinézni a kódunk ezekkel a módosításokkal:
{syntaxhighlighter brush:c}
void CBall::Move()
{
float temp = Pong.GetFrameTime();
Position.x += Speed.x*temp;
Position.y += Speed.y*temp;
if ( Position.y < radius || Position.y > (600-radius) )
{
Position.y -= Speed.y*temp; // Visszalépés
Speed.y *= -1; // Sebesség y komponensének negálása
}
}
{/syntaxhighlighter}
Eztán ha elindítjuk a programunkat azt tapasztaljuk, hogy a képernyő alján vissza fog pattanni a labdánk, majd a képernyő jobb oldalán távozik. Ideje hát megírni, hogy mi történjen a labdánkkal, ha a képernyő bal vagy jobb széléhez ér. Ekkor a labdát vissza kéne raknunk a pálya közepére, hogy elindulhasson az új kör. Ugyanakkor jó lenne, ha a labdánk mindig más irányba indulna, hogy ne lehessen kiszámítani hogy első alkalommal merre fog haladni. Ehhez hozzuk létre az Init metódust a ball.h-ban, ami biztosítani fogja számunkra, hogy a labda minden középkezdésnél a megfelelő adatokkal indul útnak:
{syntaxhighlighter brush:c}void Init();{/syntaxhighlighter}
Eztán írjuk meg a függvényt a ball.cpp-ben. Ez a konstruktorhoz lesz hasonló:
{syntaxhighlighter brush:c}
void CBall::Init()
{
if (sf::Randomizer::Random(0,1)) // Irány eldöntése
Speed.x = 150;
else
Speed.x = -150;
Speed.y = sf::Randomizer::Random(-150,150); // y irányú komponens kisorsolása
Position = sf::Vector2f(400,300); // Elhelyezés középre
}
{/syntaxhighlighter}
Eztán nincs sok dolgunk mint az új metódusunkat meghívni, amikor a labdánk vízszintes irányba lép ki a pályáról:
{syntaxhighlighter brush:c}
void CBall::Move()
{
float temp = Pong.GetFrameTime();
Position.x += Speed.x*temp;
Position.y += Speed.y*temp;
if ( Position.y < radius || Position.y > (600-radius) )
{
Position.y -= Speed.y*temp; // Visszalépés
Speed.y *= -1; // Sebesség y komponensének negálása
}
if ( Position.x < radius || Position.x > (800-radius) )
Init();
}
{/syntaxhighlighter}
Ha már van egy ilyen jó metódusunk, hívjuk meg egyből a konstruktorban is, hogy már az első alkalommal is legyen némi véletlen a labda mozgásában ( emellett gyomláljuk ki a konstruktorból a fölösleges inicializációkat):
{syntaxhighlighter brush:c}
CBall::CBall()
{
Color = sf::Color(255,255,255);
radius = 5;
Init();
}
{/syntaxhighlighter}
Eztán futtassuk a programot, és teszteljük le, hogy a várt eredményt kapjuk-e. Ha minden igaz immár a labdánk majdnem teljesen készen van. Itt az ideje, hogy áttérjünk a játékosokra. Írjuk meg az osztály deklarációját a player.h-ba! A játékosainknak is lesznek koordinátái, lesz sebességük, de nekik még gyorsulást is írunk, hogy lássuk az hogyan működik. (A sebességüknek és a gyorsulásuknak is csak y iránya lesz, ezért 2 előjeles változóval jellemezhetjük a mozgásulat.) Emellett lesz hosszuk, szélességük és színük. A metódusaik a labdához hasonlóan a Show és a Move lesz. Ami viszont újdonság, a játékosoknak a billentyűzetről utasításokat adunk (mozgatjuk őket), így ők Input metódussal is fognak rendelkezni. Mindezek után, nálam ez valahogy így néz ki gyakorlatban:
{syntaxhighlighter brush:c}
class CPlayer
{
public:
CPlayer();
sf::Color Color;
sf::Vector2f Position;
float speed;
float acceleration;
float width, length;
void Input();
void Move();
void Show();
};
{/syntaxhighlighter}
Mivel a játékosok metódusainak a megírása már nem fog beleférni ebbe a részbe, térjünk át kicsit a kód csinosítgatására. Egyik probléma a jelenlegi kódunkkal, ha például a CBall:Move metódust nézzük, a képernyő méretei ott számokként vannak megadva. Ez két okból okoz problémát. Egyrészt csökkenti a kód olvashatóságát, mivel a kód olvasója nem feltétlen tudja mit jelent ott az a szám, másrészt ha változtatni akarunk a játékunk alapértelmezett ablakméretén, ezeket a számokat több helyen is át kell írnunk. Ennek a kiküszöbölésére hozzunk létre egy újabb headert a projektünkben main.h néven, amit include-oljunk be az összes eddigi forrásfájlba (main.cpp, ball.cpp, player.cpp):
{syntaxhighlighter brush:c}#include ”main.h”{/syntaxhighlighter}
Eztán töltsük azokat a számokat amiket nem változtatunk a program futása során, de többször is használunk, a következő képen adjuk hozzá a main.h-hoz:
{syntaxhighlighter brush:c}
const int screen_width = 800;
const int screen_height = 600;
const int screen_bpp = 32;
{/syntaxhighlighter}
Eztán cseréljük ki a számokat a megfelelő konstansokra (main.cpp eleje, és ball.cpp-ben Move metódus). Így CBall::Move metódus a következőképp néz ki:
{syntaxhighlighter brush:c}
void CBall::Move()
{
float temp = Pong.GetFrameTime();
Position.x += Speed.x*temp;
Position.y += Speed.y*temp;
if ( Position.y < radius || Position.y > (screen_height-radius) )
{
Position.y -= Speed.y*temp; // Visszalépés
Speed.y *= -1; // Sebesség y komponensének negálása
}
if ( Position.x < radius || Position.x > (screen_width-radius) )
Init();
}
{/syntaxhighlighter}
Egyenlőre ennyi. A következő részben megírjuk a játékosok metódusait.