Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Simple game showing collision detects, with source.  (Read 3268 times)

0 Members and 1 Guest are viewing this topic.

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple game showing collision detects, with source.
« on: February 08, 2012, 11:44:47 am »
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

Code: [Select]
//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;
}