Itt az ideje hogy nekikezdjünk a CPlayer metódusainak a megírásának. Elsőként a player.cpp tetején tudatosítsuk a fordítóval a Pong globális RenderWindow-unkat a megszokott módon:
{syntaxhighlighter brush:c}extern sf::RenderWindow Pong;{/syntaxhighlighter}
Ezután módosítsunk kicsit a CPlayer osztályon a player.h-ban. Ennek két oka van. Egyrészt mivel az összes gomb mozgásért felelős, az egyszerűség kedvéért úgy döntöttem, hogy a Move metóduson belül fogom kezelni az inputokat is, a másik, hogy az inputok kezeléséhez szükség lesz változókra, amikben eltároljuk, hogy melyik gombokkal tudjuk mozgatni az adott játékost. Összegezve, az új osztály így néz ki:
{syntaxhighlighter brush:c}
class CPlayer
{
public:
CPlayer();
sf::Color Color;
sf::Vector2f Position;
sf::Key::Code Up, Down;
float speed;
float acceleration;
float width, length;
void Move();
void Show();
};
{/syntaxhighlighter}
Visszatérve a player.cpp-be kezdjünk neki a metódusok megírásának. Elsőként a konstruktor, ahol inicializáljuk az osztályunk tagjait:
{syntaxhighlighter brush:c}
CPlayer::CPlayer()
{
Color = sf::Color(255, 255, 255);
width = 3;
length = 30;
Up = sf::Key::Up;
Down = sf::Key::Down;
Position = sf::Vector2f(30,30);
acceleration = 100;
}
{/syntaxhighlighter}
Ezután írjuk meg a megjelenítésre használt metódust. Ez nem lesz túl nehéz eddigi ismereteink alapján, csupán kirajzoljuk azt a téglalapot amit egy függvénnyel létrehozunk az adataink alapján:
{syntaxhighlighter brush:c}
void CPlayer::Show()
{
Pong.Draw(sf::Shape::Rectangle(Position.x, Position.y, Position.x+width, Position.y+length, Color));
}
{/syntaxhighlighter}
Most jön a feketeleves. Írjuk meg a játékosok mozgását. Ehhez elsőként adjuk meg a maximális elérhető sebességet a main.h-ban az előzőekhez hasonlóan:
{syntaxhighlighter brush:c}const float max_speed = 300;{/syntaxhighlighter}
Térjünk vissza player.cpp-be és gondoljuk át mire van szükségünk. Elsőként gondoljuk át a mozgást, mink van? Van helyzetünk, sebességünk, gyorsulásunk. A sebesség a helyünk változása. A gyorsulás a sebesség változása. Mit kell tehát tennünk? A helyzetünket növelni a sebességünkkel, a sebességünket meg növelni a gyorsulásunkkal. Mit kell még tudnunk? Azt hogy merre gyorsulunk, amit az határoz meg, hogy mely gombokat nyomjuk éppen. Erre a Pong.GetInput() metódust használjuk amivel a gombok jelenlegi állapotát kapjuk meg, mi van lenyomva, mi felengedve. A sebesség növelésénél vigyáznunk kell arra, hogy a maximális értéken ne lépjen túl. Tehát szükségünk lesz min/max függvényekre is. Ehhez includeoljuk be az algorithm headert player.cpp tetejére:
{syntaxhighlighter brush:c}#include <algorithm>{/syntaxhighlighter}
Az előbb elmondottak alapján a kódom a mozgásra így néz ki, ha akkor amikor nem nyomunk le gombot, akkor a gyorsulásunk mindig ellentétes irányú a mozgásunkkal (tehát lassulunk és szépen lassan megállunk) és ez a fajta passzív gyorsulás fele akkora mint az aktív:
{syntaxhighlighter brush:c}
void CPlayer::Move()
{
const sf::Input& Input = Pong.GetInput();
if (Input.IsKeyDown(Up))
speed = std::max(-max_speed, speed-acceleration*Pong.GetFrameTime());
else if (Input.IsKeyDown(Down))
speed = std::min(max_speed, speed+acceleration*Pong.GetFrameTime());
else // Nincs lenyomva megfelelő gomb
{
if (speed > 0) speed = std::max(0.f,speed-acceleration/2*Pong.GetFrameTime());
else speed = std::min(0.f,speed+acceleration/2*Pong.GetFrameTime());
}
Position.y += speed*Pong.GetFrameTime();
}
{/syntaxhighlighter}
Eztán írjuk hozzá, hogy a játékos ne mehessen ki a pályáról a labdáéhoz hasonló logika alapján, azzal a különbséggel, hogy itt ütközéskor megáll a platformunk, tehát a sebességet nullázzuk:
{syntaxhighlighter brush:c}
void CPlayer::Move()
{
const sf::Input& Input = Pong.GetInput();
if (Input.IsKeyDown(Up))
speed = std::max(-max_speed, speed-acceleration*Pong.GetFrameTime());
else if (Input.IsKeyDown(Down))
speed = std::min(max_speed, speed+acceleration*Pong.GetFrameTime());
else // Nincs lenyomva gomb
{
if (speed > 0) speed = std::max(0.f,speed-acceleration/2*Pong.GetFrameTime());
else speed = std::min(0.f,speed+acceleration/2*Pong.GetFrameTime());
}
Position.y += speed*Pong.GetFrameTime();
if( Position.y < 0 || Position.y > screen_height - length)
{
Position.y -= speed*Pong.GetFrameTime();
speed = 0;
}
}
{/syntaxhighlighter}
Ezzel a játékos osztályunk készen is van, itt az ideje, hogy a main.cpp-ben létrehozzuk belőlük az objektumainkat, és bevegyük a metódusaikat a fő ciklusba. Az eredmény:
{syntaxhighlighter brush:c}
int main ( int argc, char** argv )
{
Pong.Create(sf::VideoMode(screen_width, screen_height, screen_bpp), "Pong", sf::Style::Close, sf::WindowSettings(24,8,4));
Pong.SetFramerateLimit(120);
Pong.UseVerticalSync(true);
sf::Event Event;
CBall Ball;
CPlayer Player1, Player2;
Player2.Position.x = 770;
Player2.Up = sf::Key::W;
Player2.Down = sf::Key::S;
while (Pong.IsOpened())
{
while(Pong.GetEvent(Event))
{
if(Event.Type == sf::Event::Closed)
Pong.Close();
}
Pong.Clear();
Player1.Move();
Player1.Show();
Player2.Move();
Player2.Show();
Ball.Move();
Ball.Show();
Pong.Display();
}
return EXIT_SUCCESS;
}
{/syntaxhighlighter}
Eztán ha futtatjuk a játékunkat, azt tapasztaljuk, hogy szinte készen van. Megvannak a játékosaink és a labdánk. Problémák: nem pattan vissza a labda a játékosokról valamint nem számoljuk a gólokat. Ezek mikéntjére a következő részekben fogok kitérni.