This game is the first more or less complete game I’ve done. It’s produced to show two different ways of collision detect: bounding box and radius calculation. You just change one row of code by un-comment it to see how it works. As it is now, it checks the coordinates for the mouse; originally the functions checked two sprites and some remnants from that remain in the radius computing. Bear with that.
The game was created as a demonstration game in the Swedish high school, so I hope you’ll understand the names of the variables even though they aren’t English. I’ve commented as much as possible of the code, just to clarify how it works.
How do you make a game out of it?
*I used SFML 1.6, I assume you can use the same code for 2.0 without problem.
*Copy the code and paste it into an SFML project.
*Get the picture of the flags (just one) and save it in the project folder
*Compile and run
*When the name of the Nordic country or area appears, you click on the corresponding flag. If you choose wrong, or click on the background, you’ll get error points.
*A red and a green staple show how many correct, and how many erroneous clicks you’ve made. At 27 of either the game is over.
The debug version is considerable slower than the release version, so use the release version if you want to use it as a game, or change the velocity value at the move command (one place in the code) to make all move faster.
//Ingemar
//Get the picture of the flags here:
// http://www.biblioteken.fi/File/d8811b0a-b714-4911-a69f-d634b8b952a8/width/397/height/119/nordiskt_flaggor.jpg
// You’ll get different flags from the Nordic countries
// moving on the screen, click on the corresponding country - flag ,
// hit SPACE for a new country.
#include <iostream>
#include <vector>
#include <string>
#include <SFML\System.hpp>
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>
#define SFML_STATIC //No extra DLL-files
using namespace std;
class flagga //The flag class
{
public:
//Arraynumber = unique, hastighet = speed, flagga_x and y = coordinates
flagga (int arraynummer, float hastighet, float flagga_x, float flagga_y);
~flagga(){};
int arraynummer; //Which country corresponds
float hastighet; //How fast is the flag moving
float flagga_x; // Where is it in X
float flagga_y; // Where is it in Y
sf::Sprite flaggsprite; //The sprite used
};
//Pre-generated values at contruction time.
flagga::flagga (int ut_arraynummer, float ut_hastighet, float ut_flagga_x, float ut_flagga_y)
{
arraynummer=ut_arraynummer;
hastighet=ut_hastighet;
flagga_x=ut_flagga_x;
flagga_y=ut_flagga_y;
}
//Check bounding box hit
bool Box_check_hit(float musx, float musy, sf::Sprite &maolsprite);
//Check radius hit
bool Cirkular_check_hit (float musx, float musy, sf::Sprite &maolsprite);
int main(int argc, char **argv)
{ //Main starts
/* Fill in variables within main */
double muskoordinat_x = 0.0f; //mouse x
double muskoordinat_y = 0.0f; //mouse y
unsigned int flagg_i = 0; //list item counter
int landsnummer = 5; //What country will we get
std::string landsnamn = "Hit the swedish flag - \n[SPACE] for new flag"; //Name of the country
sf::String uttext; //Text to be printed on screen
int flaggans_hastighet = 0.0f;
int Raett = 0; //How many correct hits?
int Fel = 0; // How many incorrect hits?
/* Load the picture of all the flags */
sf::Image flaggbild; //Create an empty image holder named flaggbild
if (!flaggbild.LoadFromFile("nordiskt_flaggor.jpg")) return EXIT_FAILURE;
//Fill it with the picture: nordiskt_flaggor.jpg
std::vector<flagga> Flagglista; //Create a vector with class instances
//Add the flags with custom velocity
int r1, r2 =0;
r1 = 1.0f;
r2 = 10.0f;
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (0, flaggans_hastighet, 400.0f, 100.0f) ); // (0=Denmark)
//0=Denmark, velocity, 400= xposition 100 = yposition
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (1, flaggans_hastighet, 400.0f, 150.0f) ); //Place a new flag in the vector (1=Faroe Islands)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (2, flaggans_hastighet, 400.0f, 200.0f) ); //Place a new flag in the vector (2=Iceland)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (3, flaggans_hastighet, 400.0f, 250.0f) ); //Place a new flag in the vector (3=Finland)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (4, flaggans_hastighet, 400.0f, 300.0f) ); //Place a new flag in the vector (4=Norway)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (5, flaggans_hastighet, 400.0f, 350.0f) ); //Place a new flag in the vector (5=Sweden)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (6, flaggans_hastighet, 400.0f, 400.0f) ); //Place a new flag in the vector (6=Sapmi)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (7, flaggans_hastighet, 400.0f, 450.0f) ); //Place a new flag in the vector (7=Aaland)
flaggans_hastighet = sf::Randomizer::Random(r1, r2);
Flagglista.push_back( flagga (8, flaggans_hastighet, 400.0f, 500.0f) ); //Place a new flag in the vector (8=Greenland)
/* Create render window that can’t be resized */
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Guess the flags of the Nordic countries", sf::Style::Close);
for (flagg_i=0; flagg_i < Flagglista.size(); flagg_i++)
{ //Walk through the list
//Give the image to the sprite and put it on the game board
Flagglista.at(flagg_i).flaggsprite.SetImage(flaggbild); //give the picture to the sprite
//Choose correct part of the sheet to show.
// Since all flags have different size and uneven positions
// all flag coordinates must be handmade,
// size is 70x50 for all
if ( Flagglista.at(flagg_i).arraynummer == 0)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(4,2,74,52));
if ( Flagglista.at(flagg_i).arraynummer == 1)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(82,2,152,52));
if ( Flagglista.at(flagg_i).arraynummer == 2)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(155,2,225,52));
if ( Flagglista.at(flagg_i).arraynummer == 3)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(233,2,303,52));
if ( Flagglista.at(flagg_i).arraynummer == 4)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(322,2,392,52));
if ( Flagglista.at(flagg_i).arraynummer == 5) //Nästa rad
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(36,66,106,116));
if ( Flagglista.at(flagg_i).arraynummer == 6)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(124,66,194,116));
if ( Flagglista.at(flagg_i).arraynummer == 7)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(200,66,270,116));
if ( Flagglista.at(flagg_i).arraynummer == 8)
Flagglista.at(flagg_i).flaggsprite.SetSubRect(sf::IntRect(285,66,355,116));
Flagglista.at(flagg_i).flaggsprite.SetPosition(Flagglista.at(flagg_i).flagga_x, Flagglista.at(flagg_i).flagga_y);
} //End of walking through the flag list
while (App.IsOpened())
{ //while 1 start, game loop in action
sf::Event Event; //Check if mouse or keyboard is used
while (App.GetEvent(Event))
{ //while 2, check events
if (Event.Type == sf::Event::Closed) //Hit [x] symbole?
App.Close(); // close the program
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) //ESC key pressed
App.Close(); // close the program
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Space)) //SPACE tangent
{
if (landsnamn == "CORRECT!" || landsnamn == "ERROR!")
{ //string doesn’t contain a name of a country
landsnummer = sf::Randomizer::Random(0, 8); //Välj ett land
if (Flagglista[landsnummer].arraynummer == 0)
landsnamn = "Denmark";
if (Flagglista[landsnummer].arraynummer == 1)
landsnamn = " Faroe Islands ";
if (Flagglista[landsnummer].arraynummer == 2)
landsnamn = "Iceland";
if (Flagglista[landsnummer].arraynummer == 3)
landsnamn = "Finland";
if (Flagglista[landsnummer].arraynummer == 4)
landsnamn = "Norway";
if (Flagglista[landsnummer].arraynummer == 5)
landsnamn = "Sweden";
if (Flagglista[landsnummer].arraynummer == 6)
landsnamn = "Sapmi";
if (Flagglista[landsnummer].arraynummer == 7)
landsnamn = "Aaland";
if (Flagglista[landsnummer].arraynummer == 8)
landsnamn = "Greenland";
} //string doesn’t contain a name of a country
}
//Where did you click the mouse?
if (Event.MouseButton.Button == sf::Mouse::Left)
{ //left mouse button
muskoordinat_x = App.GetInput().GetMouseX();
//What x-coordinate did we clik on?
muskoordinat_y = App.GetInput().GetMouseY();
//What x-coordinate did we clik on?
for (flagg_i=0; flagg_i < Flagglista.size(); flagg_i++)
{ //Walk through the flag list and check for hits
//Bounding box
if (Box_check_hit(muskoordinat_x, muskoordinat_y, Flagglista.at(flagg_i).flaggsprite) == true)
//Radius
//if (Cirkular_check_hit(muskoordinat_x, muskoordinat_y, Flagglista.at(flagg_i).flaggsprite) == true)
{//if we got a hit
if (Flagglista.at(flagg_i).arraynummer == landsnummer)
{ //Correct guess
landsnamn = "CORRECT!”;
Raett = Raett + 1;
} //end of correct guess
else
if (Flagglista.at(flagg_i).arraynummer != landsnummer)
{ //Incorrect guess
landsnamn = "ERROR!";
Fel = Fel + 1;
} // end of incorrect guess
}//end of hit
} //End of walking through the list
if (landsnamn != "CORRECT!" && landsnamn != "ERROR!")
Fel = Fel + 1; // Hit beside all flags
} //end left mouse button
} //End of while 2, check events
if (Raett > 26) //Winner
landsnamn="YOU WON!";
if (Fel > 26) //You loose
landsnamn="LOOSER!";
uttext.SetText(landsnamn);//String with country
uttext.SetFont(sf::Font::GetDefaultFont());
uttext.SetSize(50);
uttext.SetPosition(20.f, 20.f); //place the string on the game board
/* Show the game for the player */
for (flagg_i=0; flagg_i < Flagglista.size(); flagg_i++)
{ //Walk through the list
if(Flagglista.at(flagg_i).flaggsprite.GetPosition().x < 0 || Flagglista.at(flagg_i).flaggsprite.GetPosition().x > 800 - 70)
//Flag is outside the edge
{
Flagglista.at(flagg_i).hastighet = Flagglista.at(flagg_i).hastighet * -1; //Change direction
}
Flagglista.at(flagg_i).flaggsprite.Move(Flagglista.at(flagg_i).hastighet * 0.033,0); //Move the flag
0.33 to change the velocity to a lower, float, value
} //End of walking through the list
App.Clear(sf::Color(100, 100, 100)); //Dark grey background
/*Show the sprites */
App.Draw(sf::Shape::Rectangle(0,570,10 + (Raett * 30), 580, sf::Color(0, 255, 0) )); //Green, grows with correct answers
App.Draw(sf::Shape::Rectangle(0,585,10 + (Fel * 30), 595, sf::Color(255, 0, 0) )); //Red, grows with wrong answers or miss clicks
//Win/loose at 27 correct/errors
App.Draw(uttext); //Show the country name
for (flagg_i=0; flagg_i < Flagglista.size(); flagg_i++)
{ //Walk through the list
//Draw the flags
App.Draw(Flagglista.at(flagg_i).flaggsprite);
} //End of walk through the list
App.Display(); //Show the game board or the player
} //while 1 ends, end of game loop
Flagglista.clear(); //avoid memory leaks
return 0; //last row
} //End of main
/* Function descriptions */
//BOX******************************************************************
bool Box_check_hit(float musx, float musy, sf::Sprite &maolsprite)
//mouse x and y, sprite is flag sprite.
// check if we clicked inside a flag
{
bool klickat_inuti = false; //return value
double maolx = maolsprite.GetPosition().x;
double maoly = maolsprite.GetPosition().y;
//Flags are 50 x 70 in size
// inside left edge/inside right edge/inside top/inside bottom
if ((musx > (maolx)) && (musx < maolx + 70) && musy > maoly && musy < maoly + 50 )
klickat_inuti = true; //return value
return klickat_inuti;
}
//RADIus***************************************************
bool Cirkular_check_hit (float musx, float musy, sf::Sprite &maolsprite)
//mouse x and y, sprite is flag sprite.
//Check if we clicked inside radius (50 * 1.4……)
{
bool har_traeffat = false; //return value
double avstaond = 0.0; //distance to middle point
double traeffavstaond = 0.0; //At what distance will you hit?
double tempx; //distance in x-value
double tempy; //distance in y-value
//get the mouse coordinates
//musx and musy are the mouse coordinates
//maolx och maoly are the flags coordinates at the center
//Re-calculate it from top left corner to center.
double maolx = maolsprite.GetPosition().x + 35;
double maoly = maolsprite.GetPosition().y + 25;
double maol_radie = (1.4142135623730950488016887242097 * 50) / 2;
//When do we hit?
traeffavstaond = maol_radie;
if (musx == maolx && musy != maoly ) //both on same line in x
{
avstaond = musy - maoly;
if (avstaond <= traeffavstaond) //within hit distance
har_traeffat = true;
}
else if (musy == maoly && musx != maolx ) // both on same line in y
{
avstaond = musx - maolx;
if (avstaond <= traeffavstaond) // within hit distance
har_traeffat = true;
}
else if(musx != maolx && musy != maoly) // different places
{ //Use pythagoras theorem
tempx = musx-maolx;
tempy = musy-maoly;
// Calculate hypotenusan/distance by calculating
// square from x-distance ^2 + y-distance ^2
avstaond = sqrt ( tempx * tempx + tempy * tempy);
if (avstaond <= traeffavstaond) //within hit distance
har_traeffat = true;
} // End, using pythagoras theorem
else if (musx == maolx && musy == maoly) //The very same spot
har_traeffat = true;
return har_traeffat;
}