Programmera spel i C++ för nybörjare/Pingis

Från Wikibooks


För att kunna spela det här spelet krävs följande

  • en bild av en boll 24x24 som heter ball.png
  • en bild av ett racket som heter racket.png och är 16 x 64 pixels stort
  • Ett typsnitt som heter ELEPHNT.TTF
  • Ett ljud som heter Wall_Hit.ogg
  • Ett ljud som heter Paddle_Hit.ogg
  • Ett ljud som heter Ball_Out.ogg
  • Ett bakgrundsljud som heter bakgrund_ping_pong.ogg

Du startar spelet genom att trycka ner space-tangenten. Du styr höger racket med pil upp/ner och vänser racket med W- och S-tangenterna. Om man tävlar två mot varandra gäller det att inte förlora 5 bollar, om man har lagtävlingar gäller det att ha bollen i spel så länge som möjligt, man har 5 bollar på sig. Tiden syns i den lilla texten i botten medan poängen 0-5 syns i överkanten.


Kod:

#include <iostream>
#include <string> //För att kunna skriva ut resultaten på skärmen
#include <SFML\System.hpp>
#include <SFML\Window.hpp>
#include <SFML\Graphics.hpp>
#include <sstream> //För att kunna konvertera siffror till text
#include <SFML\Audio.hpp>  //För att få ljud

using namespace std;    // utifall att konsollen behövs för felsökning

//Funktioner------------------
char poang2char(int poang); //för att förvandla poängen från int till char.
string Tal2String(double siffrain); //För att förvandla tiden från klockan till en text att skriva ut



int main (int argc, char *argv)
{ //Början av programkörningen

float bollX=0.0f; //x position för bollen
float bollY=0.0f; //y position för bollen
float racketY=0.0f; //y position för racketen
float racket1Y=0.0f; //y position för höger racket

float fartX = 0.0f; //rörelse i xled
float fartY = 0.0f; //rörelse i yled, liten vinkel för lämplig rörelse
double tidsomgott = 0.0f; //Om man vill tävla om hur länge man kan ha bollen i luften
bool deadball = true; //Avgör om bollen har hamnat utanför och inte skjutits iväg

int poangvanster = 0; //vem får poäng?
int poanghoger = 0; //vem får poäng?
char temptext[20]={0}; //Behövs för att skapa en string av 0-0 resultat
                       //+ texten vinnare

char vinnareleft[30] = {'V','I','N','N','A','R','E',' ','V','Ä',
                                 'N','S','T','E','R',' ','S','I','D','A',
                             '!','\n ','5',' ', '-',' '};
char vinnareright[30] = {' ',' ','-',' ', '5','\n ','V','I','N','N','A','R','E',' ','H','Ö',
                                 'G','E','R',' ','S','I','D','A',
                             '!'};

bool gameover = false; //Har någon nått 5p?

//Kolla video mode för fullskärmsläge
sf::VideoMode Mode = sf::VideoMode::GetDesktopMode();
//Variabler för skärmen i fullskärmsläge.
int fonsterbredd = Mode.Width;
int fonsterhojd = Mode.Height;
int fargdjup=Mode.BitsPerPixel;

sf::WindowSettings Settings; //skapa ett SFML fönster
//Sätt det till fullscreen
sf::RenderWindow App(sf::VideoMode(Mode.Width, Mode.Height, Mode.BitsPerPixel), "SQUASH", sf::Style::Fullscreen, Settings); // Skapa   fönstret vi skall visa ping pong i

float ElapsedTime = App.GetFrameTime(); //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer

sf::Clock Clock; //en spelklocka för att hålla reda på hur länge man spelat
tidsomgott = Clock.GetElapsedTime();

//Ladda in ljudfilerna----------------------------------------------------------------------
sf::SoundBuffer paddlehit; //skapa en ljudbuffer/hållare
if (!paddlehit.LoadFromFile("Paddle_Hit.ogg")) //ladda in en fil I hållaren
{
   // Error...
}
sf::Sound Traeff_racket; //skapa ett ljud för en racketträff
Traeff_racket.SetBuffer(paddlehit); // Ladda in ljudfilens värden i ljudet så att det  går att spela upp. 
//---

sf::SoundBuffer wallhit; //skapa en ljudbuffer/hållare
if (!wallhit.LoadFromFile("Wall_Hit.ogg")) //ladda in en fil I hållaren
{
   // Error...
}
sf::Sound Traeff_wall; //skapa ett ljud för en vägg
Traeff_wall.SetBuffer(wallhit); // Ladda in ljudfilens värden i ljudet så att det  går att spela upp. 
//---

sf::SoundBuffer ballout; //skapa en ljudbuffer/hållare
if (!ballout.LoadFromFile("Ball_Out.ogg")) //ladda in en fil I hållaren
{
   // Error...
}
sf::Sound Ball_Out; //skapa ett ljud för en vägg
Ball_Out.SetBuffer(ballout); // Ladda in ljudfilens värden i ljudet så att det  går att spela upp. 

//---
sf::Music bakgrundsmusik; //skapa filhållare
if (!bakgrundsmusik.OpenFromFile("bakgrund_ping_pong.ogg"))//fyll hållaren med din fil
{
   // Error...
}

bakgrundsmusik.SetLoop(true); //få den att gå runt runt
bakgrundsmusik.Play(); //spela, obs versal i Play.

//Lada in text och typsnitt--------------------------------------
//Ladda in ett typsnitt
sf::Font resultatfont; //ladda en tom font
if (!resultatfont.LoadFromFile("ELEPHNT.TTF", 50)) return EXIT_FAILURE; 
//Se till så att ttf-fonten finns i samma mapp som main.cpp

sf::String resultat_ut; //skapa en textremsa för resultaten
resultat_ut.SetText("0 - 0"); 
resultat_ut.SetFont(resultatfont); //Tilldelas typsnittet
resultat_ut.SetColor(sf::Color(255, 255, 255));//Vit färg
resultat_ut.SetPosition(fonsterbredd/2-35, 10.f); //placera ut texten halva x och 100 i y led

sf::String tid_ut; //skapa en textremsa för hur lång tid man spelat
tid_ut.SetText("0"); 
tid_ut.SetFont(resultatfont); //Tilldelas typsnittet
tid_ut.SetColor(sf::Color(255, 255, 255));//Vit färg
tid_ut.SetPosition(fonsterbredd/2-35, fonsterhojd-50.f); //placera ut texten halva x och långt ner i y led

//Ladda in bilderna
		
sf::Image bollbild; //skapa en tom bildhållare som heter Image
if (!bollbild.LoadFromFile("ball.png")) return EXIT_FAILURE; //fyll den tomma bildhållaren med bilden boll.png
//bilden är 24x24
sf::Sprite boll(bollbild); //Skapar den grafiska spelpjäsen boll med grafiken från bollbild
boll.SetPosition(1.0f,fonsterhojd/2-12); //Placera ut bilden mitt på kortsidan


sf::Image racketbild; //skapa en tom bildhållare som heter racket
if (!racketbild.LoadFromFile("racket.png")) return EXIT_FAILURE; //fyll den tomma bildhållaren med bilden racket.png
//bilden är 16x64
sf::Sprite racket(racketbild); //Skapar den grafiska spelpjäsen racket med grafiken från racketbild
racket.SetPosition(1.0f, (fonsterhojd/2 - 32)); //Placera ut bilden mitt på vänsterkanten

sf::Image racketbild1; //skapa en tom bildhållare som heter rackettbild1 
//om man har samma bild till bägge racketarna är det bättre att använda samma bild, dvs:
//if (!racketbild1.LoadFromFile("racket.png")) return EXIT_FAILURE;
if (!racketbild1.LoadFromFile("racket.png")) return EXIT_FAILURE; //fyll den tomma bildhållaren med bilden racket.png
//bilden är 16x64
sf::Sprite racket1(racketbild1); //Skapar den grafiska spelpjäsen racket1 med grafiken från racketbild
racket1.SetPosition(fonsterbredd-17, fonsterhojd/2 - 32); //Placera ut bilden längs höger kant


while (App.IsOpened()) // Start spel-loopen
{ //while 1
sf::Event Event; 

while (App.GetEvent(Event)) // Ta hand om händelser som tangentnedtryckning
{ //while 2



if (Event.Type == sf::Event::KeyPressed) // En tangent har tryckts ner

{ //if 1

if (Event.Key.Code == sf::Key::Escape) // ESC tangenten = stäng programmet
App.Close(); 

} //slut if 1



} //slut, while 2


ElapsedTime = App.GetFrameTime(); //för att få en konstant hastighet på olika datorer

racketY=racket.GetPosition().y; //var är racket i y-led på vänster sida
racket1Y=racket1.GetPosition().y; //var är racket1 i y-led på höger sida

if (App.GetInput().IsKeyDown(sf::Key::Space) && fartX==0.0f) 
       //starta om bollen om farten är 0
{

	    fartX = (200.0f  + sf::Randomizer::Random(0, 50))* ElapsedTime;//Rörelse i X-led
      fartY = (10.0f +  sf::Randomizer::Random(0, 5))  * ElapsedTime; //rörelse i yled, liten, liten vinkel
	   Traeff_racket.Play();
	   //Spela upp ljud

deadball = false; //Bollen är i spel igen
}

//Styr racketarna upp och ner längs spelplanens sidor
if (App.GetInput().IsKeyDown(sf::Key::W)) 
{
if (racketY > 0)
racket.Move(0, -700 * ElapsedTime); //racket upp
}

if (App.GetInput().IsKeyDown(sf::Key::S)) 
{
if (racketY < fonsterhojd - 64)
racket.Move(0, 700 * ElapsedTime); //racket ner
}

if (App.GetInput().IsKeyDown(sf::Key::Up)) 
{
if (racket1Y > 0)
racket1.Move(0, -700 * ElapsedTime); //racket 1 upp
}

if (App.GetInput().IsKeyDown(sf::Key::Down)) 
{
if (racket1Y < fonsterhojd - 64)
racket1.Move(0, 700 * ElapsedTime); //racket 1ner
}


bollX=boll.GetPosition().x; //var är bollen i x-led
bollY=boll.GetPosition().y; //var är bollen i y-led


if (bollX > fonsterbredd - 24 ) 
{ //den slår in i högerväggen 
if(racket1Y - bollY < 24 && bollY - racket1Y < 64)
  //om skillnaden mellan bollens höjd (24) och kanten på racketen 
 //är mindre än och om bollen träffar racketen (64hög) hågonstans…
    {//om racket träffar
		 

     fartX = fartX * -1; //spegelvänd riktning
    //annars försvinner bollen
    //Låt dessutom bollens hastighet öka.
    fartX = fartX - 0.1f; //rörelse i xled
	 fartY = fartY - 0.1f; //rörelse i yled
	 Traeff_racket.Play(); //Spela upp ljud
    }//slut om racket träffar
else
    {//Om racket inte träffar, bollen går ut genom höger sida
     boll.SetPosition(1.0f,racketY+20); //på vänster racket.
      fartX = 0.0f; //ingen fart
      fartY = 0.0f; //ingenfart
	   poangvanster = poangvanster +1; //ge vänster spelare ett extra poäng
	   deadball = true; //Bollen är ur spel
	   Ball_Out.Play(); //Spela ljud förlorad boll

	   if (poangvanster >=5) //Man har uppnått 5p
	   gameover = true;

     }//slut om racket inte träffar
 }//slut på att se om den träffar högervägg



if( bollX < 0 ) //den slår in i vänsterväggen 
{ //träffar den racketen?

if(racketY - bollY < 24 && bollY - racketY < 64)
//om skillnaden mellan bollens höjd (24) och kanten på racketen 
//är mindre än och om bollen träffar racketen (64hög) hågonstans…
{//om racket träffar

fartX = fartX * -1; //spegelvänd riktning
//annars försvinner bollen
//Låt dessutom bollens hastighet öka.
fartX = fartX + 0.1f; //rörelse i xled
fartY = fartY + 0.1f; //rörelse i yled

//Spela upp ljud
Traeff_racket.Play();

}//slut om racket träffar
else
{//Om racket inte träffar
boll.SetPosition(fonsterbredd - 24,racket1Y+20); //Vänster sida
fartX = 0.0f; //ingen fart
fartY = 0.0f; //ingenfart
poanghoger = poanghoger +1; //Ge högerspelaren ett poäng till
deadball = true; //Bollen är ur spel
Ball_Out.Play(); //Spela ljud förlorad boll

if (poanghoger >=5) //Man har uppnått 5p
	gameover = true; //Spelet är över

    
}//slut om racket inte träffar
}//slut på att se om den träffar racketen

else if (bollY > fonsterhojd - 24 || bollY < 0) //den slår in neder- eller överväggen
{
fartY = fartY * -1; //spegelvänd riktning
	Traeff_wall.Play();
}

//Skicka iväg bollen med sina nya koordinater
boll.Move(fartX,fartY); //bollen skickas iväg


//Lägg in resultatsiffrorna för utskrift. Max 5 i resultat
resultat_ut.SetText("");//Se till så att det inte finns text kvar
temptext[0] = poang2char(poangvanster);
temptext[1] = ' ';
temptext[2] = '-';
temptext[3] = ' ';
temptext[4] = poang2char(poanghoger);



if (gameover == false)
{
 resultat_ut.SetText(temptext);
}
else
	if (poangvanster >=5 && gameover == true)
	{
		vinnareleft[26] = poang2char(poanghoger); //Skriv ut att vänster vunnit
		resultat_ut.SetText(vinnareleft);
		deadball=true; //Bollen kan inte spelas
	}
else
	if (poanghoger >=5 && gameover == true)
	{
		vinnareright[0] = poang2char(poangvanster);//Skriv ut att höger vunnit
		resultat_ut.SetText(vinnareright);
		deadball=true; //Bollen kan inte spelas
	}

	if (deadball == false)//Om bollen är i spel
	{
	tidsomgott = (tidsomgott + Clock.GetElapsedTime()); //Hur lång tid av partiet har gått
	}
	tid_ut.SetSize(14);//Liten storlek på talen som ritas ut
	tid_ut.SetText(Tal2String(tidsomgott)); //Konvertera tiden till en textremsa som kan skrivas ut.



//Rita ut allting på spelplanen
App.Clear(sf::Color(0, 0, 0)); //rensa allt i fönstret och ersätt med svart färg
App.Draw(sf::Shape::Rectangle(fonsterbredd/2-1, 0, fonsterbredd/2+1, fonsterhojd , sf::Color(255, 0, 0) ));
App.Draw(boll); //Rita upp figuren på den yta spelaren ser
App.Draw(racket); //Rita upp figuren på den yta spelaren ser
App.Draw(racket1); //Rita upp racketen längs höger vägg
App.Draw(resultat_ut); //rita ut de valda bokstäverna
App.Draw(tid_ut); //rita ut den tid som gått
App.Display(); //visa upp ändringarna för användaren

} //slut, while 1

return 0;
} //slut på programkörningen


//Funktionsbeskrivningar---------------------------------------------------------------------
char poang2char(int poang)
{
	char  utchar ='X';

	if ( poang == 0)
	utchar = '0';

    else if ( poang == 1)
	utchar = '1';

	else if ( poang == 2)
	utchar = '2';

	else if ( poang == 3)
	utchar = '3';

	else if ( poang == 4)
	utchar = '4';

	else if ( poang == 5)
	utchar = '5';
	else
	utchar ='X';


	return utchar;
}


string Tal2String(double siffrain)
{    //Förvandlar ett tal till text
        //Detta kräver: #include <sstream>
       // och: using namespace std; 
 std::string s;
 std::stringstream out;
 out << siffrain;
 s = out.str();
 return s;
}