Programmera spel i C++ för nybörjare/Exempel 2 på collision detect


Exemplet baseras på SFML 1.6 och Visual Studio 2010

Jag hade en elev i år tre, Daniel Svensson, som skapade detta enkla demonstrationsspel som visar hur två cirklar aldrig kan komma in i varandra. Ett tydligt exempel på hur radius collision detect fungerar i praktiken. Det enda som behövs är två bilder du kan skapa själv.

  • png format
  • Circle1.png föreställer en blå cirkel
  • Circle2.png föreställer en röd cirkel

Båda är 128 x 128 pixels stora med genomskinlig bakgrundsfärg.


Man kan köra runt den ena cirkeln hur som helst på spelplanen, men så fort man kommer i kontakt med varandra går det inte att köra cirkeln längre utan man måste byta riktning. Exemplet är perfekt för den som t.ex. vill skapa ett biljardspel eller annat bollsportspel, eller bara för någon som vill se hur en collision detect fungerar i praktiken med minimal kod.

Kod

// written by Daniel Svensson (Dannehood)

#include <iostream>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

using namespace std;

bool circleCollision (sf::Sprite &circle1, sf::Sprite &circle2);
void circleCollisionEffect(sf::RenderWindow &App, sf::Sprite &circle1, sf::Sprite &circle2, bool &turn_up, bool &turn_down, bool &turn_left, bool &turn_right);

int main()
{
	// Variables for the movement
	
	bool turn_up = true;
	bool turn_down = true;
	bool turn_left = true;
	bool turn_right = true;

	// The window
	
	sf::RenderWindow App(sf::VideoMode(800, 600), "circle Collision");

	// The Images
	
	sf::Image Circle1;
	Circle1.LoadFromFile("Circle1.png");

	sf::Image Circle2;
	Circle2.LoadFromFile("Circle2.png");

	// The sprites

	sf::Sprite circle1;
	circle1.SetImage(Circle1);

	sf::Sprite circle2;
	circle2.SetImage(Circle2);

	// Set the sprites starting coordinates to their center points and set their starting positions

	circle1.SetCenter(circle1.GetSize().x/2, circle1.GetSize().y/2);
	circle2.SetCenter(circle2.GetSize().x/2, circle2.GetSize().y/2);
	circle1.SetPosition(App.GetWidth()/2, App.GetHeight()/2);
	circle2.SetPosition(circle1.GetPosition().x - 0.0001, circle1.GetPosition().y - circle2.GetSize().y);
	
	while(App.IsOpened())
    {
		sf::Event Event;
		cout << circle2.GetPosition().x << " x      " << circle2.GetPosition().y << " y" << endl;

		while(App.GetEvent(Event))
		{
			if(Event.Type == sf::Event::Closed)
			App.Close();
			if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
			App.Close();
		}

		// The movement

       if (App.GetInput().IsKeyDown(sf::Key::Up) && turn_up == true)circle2.Move(0, -200 * App.GetFrameTime()); // Up
       if (App.GetInput().IsKeyDown(sf::Key::Down) && turn_down == true)circle2.Move(0, 200 * App.GetFrameTime()); // Down
       if (App.GetInput().IsKeyDown(sf::Key::Left) && turn_left == true)circle2.Move(-200 * App.GetFrameTime(), 0); // L Left
       if (App.GetInput().IsKeyDown(sf::Key::Right) && turn_right == true)circle2.Move(200 * App.GetFrameTime(),0); // Right

		// If they are colliding, call the collision effekt funktion

		if (circleCollision(circle1, circle2) == 1)
		circleCollisionEffect(App, circle1, circle2, turn_up, turn_down, turn_left, turn_right);
		
		// If not, enable movement
		
		else
		{
			turn_up = true;
			turn_down = true;
			turn_left = true;
			turn_right = true;
		}

		// Draw sprites

		App.Clear(sf::Color(0,0,0));
		App.Draw(circle1);
		App.Draw(circle2);
		App.Display();
	}
}

// circle collision DETECTION

bool circleCollision (sf::Sprite &circle1, sf::Sprite &circle2)
{
	int hit;

	float circle1_x = circle1.GetPosition().x;
	float circle1_y = circle1.GetPosition().y;
	float circle1_r = circle1.GetSize().x/2;

	float circle2_x = circle2.GetPosition().x;
	float circle2_y = circle2.GetPosition().y;
	float circle2_r = circle2.GetSize().x/2;

	float distance = sqrt(pow(circle1_x - circle2_x, 2) + pow(circle1_y - circle2_y, 2)) - (circle1_r + circle2_r);
	// (C1x - C2x)2 + (C1y - C2y)2 - (C1r - C2r) Gives the distance between the two circles
	if (distance < 0)hit = 1;
	else hit = 0;
	//cout << hit << endl;
	return hit;
} 

// circle collision EFFECT

void circleCollisionEffect(sf::RenderWindow &App, sf::Sprite &circle1, sf::Sprite &circle2, bool &turn_up, bool &turn_down, bool &turn_left, bool &turn_right)
{
	if(circle2.GetPosition().x > circle1.GetPosition().x  // Top Right
	&& circle2.GetPosition().y < circle1.GetPosition().y )
	{
		turn_left = false;
		turn_down = false;
		circle2.Move(200 * App.GetFrameTime(), -200 * App.GetFrameTime());
	}
	if(circle2.GetPosition().x < circle1.GetPosition().x  // Top left
	&& circle2.GetPosition().y < circle1.GetPosition().y )
	{
		turn_right = false;
		turn_down = false;
		circle2.Move(-200 * App.GetFrameTime(), -200 * App.GetFrameTime());
	}
	if(circle2.GetPosition().x > circle1.GetPosition().x  // Bottom right
	&& circle2.GetPosition().y > circle1.GetPosition().y )
	{
		turn_left = false;
		turn_up = false;
		circle2.Move(200 * App.GetFrameTime(), 200 * App.GetFrameTime());
	}
	if(circle2.GetPosition().x < circle1.GetPosition().x  // Bottom left
	&& circle2.GetPosition().y > circle1.GetPosition().y )
	{
		turn_right = false;
		turn_up = false;
		circle2.Move(-200 * App.GetFrameTime(), 200 * App.GetFrameTime());
	}
} 

 

//Kodslut