Hey guys, my first post on here, I need help with setting up basic collision with a program I just did up. I downloaded sfml about an hour ago, and I have a cube I can move around, and want it to stop moving, when colliding with a stationary cube. The problem most likely lies within one of the loops, or who knows where, but I've had my fill of tinkering with it.

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

using namespace std;

bool isCollision(int x, int y, int x2, int y2){        //Function I borrowed
	if (abs(x2 - x) > 20 || abs(y2 - y) > 20)
		return false;
	else
		return true;
}

int main()
{
	sf::RenderWindow App(sf::VideoMode(800, 600, 32), "My SFML Window");
	sf::RenderWindow Warning(sf::VideoMode(400, 225, 32), "WARNING!");  //Window that should open on collision
	sf::Shape Rect = sf::Shape::Rectangle(0, 0, 20,	20, sf::Color::Red);
	sf::Shape Rect2 = sf::Shape::Rectangle(50, 0, 70, 20, sf::Color::Blue);
	
	
	while (App.IsOpened())
	{
		sf::Event event;
		while (App.GetEvent(event)) // I now know an easier way to handle these events, but makes no real difference
		{
			if (event.Type == sf::Event::Closed)
				App.Close();
			if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Escape))
				App.Close();
			if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Right))
				Rect.Move(5.0, 0);
			if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Left))
				Rect.Move(-5.0, 0);
			if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Down))
				Rect.Move(0, 5.0);
			if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Up))
				Rect.Move(0, -5.0);
			
			
			int x = Rect.GetPosition().x;
			int y = Rect.GetPosition().y;
			
			int x2 = Rect2.GetPosition().x;
			int y2 = Rect2.GetPosition().y;
			
			isCollision(x, y, x2, y2);
			
			if (isCollision(x, y, x2, y2) == true)
			{
				Warning.Clear(sf::Color::White);
				Warning.Display();
			}
			
		}
		
		App.Clear();
		App.Draw(Rect);
		App.Draw(Rect2);
		App.Display();
	}
	
	return EXIT_SUCCESS;

I got the bool isCollision function from a tut I was watching, but the tut was done in allegro, so I scraped from it what I could. (My logic in using his function was that our cubes are the exact same size, and identical in their properties [one moving one stationary]. The problem must lie, I assume, in how I call the function. Any and all help is appreciated

Recommended Answers

All 2 Replies

Yeah, I had a similar problem too when I started playing with SFML.
The solution is simple, but I don't really understand how/why it works...

The main problem is this here -> sf::Shape Rect2 = sf::Shape::Rectangle(50, 0, 70, 20, sf::Color::Blue); .
It should be -> sf::Shape Rect2 = sf::Shape::Rectangle(0, 0, 20, 20, sf::Color::Blue); Rect2.Move(50, 0); .

This works fine for me:

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

using namespace std;

bool isCollision(int x, int y, int x2, int y2)
{
    if (abs(x2 - x) > 20 || abs(y2 - y) > 20)
		return false;
	else
		return true;
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "My SFML Window");
    sf::RenderWindow Warning(sf::VideoMode(400, 225, 32), "WARNING!");
    sf::Shape Rect = sf::Shape::Rectangle(0, 0, 20, 20, sf::Color::Red);
    sf::Shape Rect2 = sf::Shape::Rectangle(0, 0, 20, 20, sf::Color::Blue);

    Rect2.Move(50, 0);

    while (App.IsOpened())
    {
        sf::Event event;

        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();
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Right)) Rect.Move(5.0, 0);
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Left)) Rect.Move(-5.0, 0);
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Down)) Rect.Move(0, 5.0);
            if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Up)) Rect.Move(0, -5.0);

            int x = Rect.GetPosition().x;
            int y = Rect.GetPosition().y;
            int x2 = Rect2.GetPosition().x;
            int y2 = Rect2.GetPosition().y;

            if (isCollision(x, y, x2, y2))
                Warning.Clear(sf::Color::White);
            else
                Warning.Clear(sf::Color::Black);
        }

        App.Clear();
        App.Draw(Rect);
        App.Draw(Rect2);
        App.Display();
        Warning.Display();
    }
}

You might also want to check this out:

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

const int SCREEN_WIDTH=320;
const int SCREEN_HEIGHT=240;
const int BLOCK_SIZE=25;

struct MyRect
{
    double x, y, dx, dy;
    double size;

    sf::Shape sprite;

    MyRect()
    {
        size=BLOCK_SIZE;
        sprite=sf::Shape::Rectangle(0,0,size,size,sf::Color::White);
        x=y=dx=dy=0;
    }

    inline double Top() {return y;}
    inline double Bottom() {return y+size;}
    inline double Left() {return x;}
    inline double Right() {return x+size;}

    void Draw(sf::RenderWindow & window)
    {
        sprite.SetPosition(x,y);
        window.Draw(sprite);
    }
};

bool Collide(MyRect & p, MyRect & o)
{
    double cy=p.Top()-o.Top();
    double cx=p.Left()-o.Left();

    double acy=cy>=0?cy:-cy;
    double acx=cx>=0?cx:-cx;

    if (acy<BLOCK_SIZE && acx<BLOCK_SIZE)
    {
        if (acy>=acx)
        {
            if (cy<0) {if (p.dy>0) p.dy=0; p.y=o.Top()-BLOCK_SIZE;}
            else {p.dy=0; p.y=o.Bottom();}
        }

        if (acx>=acy)
        {
            if (cx<0) {p.dx=0; p.x=o.Left()-BLOCK_SIZE;}
            else {p.dx=0; p.x=o.Right();}
        }

        return true;
    }
    else
        return false;
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,32),"SFML");
    sf::Event event;

    window.UseVerticalSync(true);

    MyRect p;
    MyRect o;

    o.x=4*BLOCK_SIZE;
    o.y=5*BLOCK_SIZE;

    bool cur_col=false;
    bool prev_col=false;

    bool space_down=false;

    while (window.IsOpened())
    {
        window.GetEvent(event);

        if (event.Type==sf::Event::Closed) window.Close();

        const sf::Input & input=window.GetInput();

        if (input.IsKeyDown(sf::Key::Escape)) window.Close();

        //move

        if (input.IsKeyDown(sf::Key::Left) && !cur_col) p.dx-=0.1;
        if (input.IsKeyDown(sf::Key::Right) && !cur_col) p.dx+=0.1;

        p.x+=p.dx;
        p.y+=p.dy;

        //friction

        p.dx*=0.975;

        //gravity

        if (p.y<SCREEN_HEIGHT-BLOCK_SIZE && !cur_col) p.dy+=0.1;

        //screen limits

        if (p.y<0) {p.dy=0; p.y=0;}
        if (p.y>SCREEN_HEIGHT-BLOCK_SIZE) {p.dy=0; p.y=SCREEN_HEIGHT-BLOCK_SIZE;}
        if (p.x<0) {p.dx=0; p.x=0;}
        if (p.x>SCREEN_WIDTH-BLOCK_SIZE) {p.dx=0; p.x=SCREEN_WIDTH-BLOCK_SIZE;}

        //jump

        if (input.IsKeyDown(sf::Key::Space) && !space_down && !cur_col)
        {
            p.dy=-2.5;
            space_down=true;
        }

        if (!input.IsKeyDown(sf::Key::Space)) space_down=false;

        //collision

        prev_col=cur_col;
        cur_col=Collide(p,o);

        if (cur_col && !prev_col)
            std::cout << "collision!!!" << std::endl;
        if (!cur_col && prev_col)
            std::cout << "free!!!" << std::endl;

        //draw

        window.Clear(sf::Color::Black);
        p.Draw(window);
        o.Draw(window);
        window.Display();
    }
}

It's one of my first SFML experiments :P

Thanks bud, great help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.