Hi, I am having problems with my collisions. I know how 2 check if a collision has happened but having trouble with the sprite repositioning. I some minimal code to show what I have. Right now the code is working for side collisions but for the top it is not. I know why the commented code isn't working, one the first 2 conditions will be true. Is there something simple that I am not seeing or do I need a lot more code to get this done. I have searched for answers but what I found is way different than what I have.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "SFML");
window.setFramerateLimit(60);
sf::Clock frameTime;
sf::RectangleShape square(sf::Vector2f(40.f,40.f));
square.setFillColor(sf::Color::Red);
square.setPosition(200.f,500.f);
sf::RectangleShape square2(sf::Vector2f(40.f,100.f));
square2.setFillColor(sf::Color::Green);;
square2.setPosition(275.f,275.f);
sf::Vector2f speed(150.f,150.f);
while(window.isOpen())
{
float dt = frameTime.restart().asSeconds();
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
square.move(speed.x * dt,0.f);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
square.move(-speed.x * dt,0.f);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
square.move(0.f,speed.y * dt);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
square.move(0.f,-speed.y * dt);
if(square.getPosition().x + square.getSize().x > square2.getPosition().x &&
square.getPosition().x < square2.getPosition().x + square2.getSize().x &&
square.getPosition().y + square.getSize().y > square2.getPosition().y &&
square.getPosition().y < square2.getPosition().y + square2.getSize().y)
{
//left side of square 2 collision
if(square.getPosition().x < square2.getPosition().x )
square.setPosition(square2.getPosition().x - square2.getSize().x,square.getPosition().y);
//right side of square2 collision
if(square.getPosition().x > square2.getPosition().x)
square.setPosition(square2.getPosition().x + square2.getSize().x,square.getPosition().y);
//top of square2 collision
//if(square.getPosition().y + square.getSize().y > square2.getPosition().y)
//square.setPosition(square.getPosition().x,square2.getPosition().y - square.getSize().y);
}
window.clear();
window.draw(square);
window.draw(square2);
window.display();
}
return 0;
}
Well, after some testing, I still think that third case is testing for a collision from the bottom, not from the top, and that's why it's "not working" when you try a collision from the top. You do need that fourth/top case.
But there's a more general problem. Because no collision detection happens during the initial movement, your collision logic doesn't know what the square's previous position was, which means any way you tweak this you're likely to have it guessing wrong and making the square warp around the object it collides with. Movement and collision should be dealt with at the same time, after input is handled.
I commented out the first and second case and top collision works and if I add
if(square.getPosition().y < square2.getPosition().y + square2.getSize().y)
square.setPosition(square.getPosition().x,square2.getPosition().y + square2.getSize().y);
the bottom works.
Thanks for all the replies. Finally figured it out,here is the updated code.
#include <SFML/Graphics.hpp>
#include <iostream>
bool Collision(sf::RectangleShape square,sf::RectangleShape square2)
{
if(square.getPosition().x + square.getSize().x > square2.getPosition().x &&
square.getPosition().x < square2.getPosition().x + square2.getSize().x &&
square.getPosition().y + square.getSize().y > square2.getPosition().y &&
square.getPosition().y < square2.getPosition().y + square2.getSize().y)
{
std::cout << "collide" << std::endl;
return true;
}
else
return false;
}
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "SFML");
window.setFramerateLimit(60);
sf::Clock frameTime;
sf::RectangleShape square(sf::Vector2f(40.f,40.f));
square.setFillColor(sf::Color::Red);
square.setPosition(200.f,500.f);
sf::RectangleShape square2(sf::Vector2f(40.f,100.f));
square2.setFillColor(sf::Color::Green);;
square2.setPosition(275.f,275.f);
sf::Vector2f speed(150.f,150.f);
while(window.isOpen())
{
float dt = frameTime.restart().asSeconds();
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
square.move(speed.x * dt,0.f);
if(Collision(square,square2))
{
square.setPosition(square2.getPosition().x - square.getSize().x,square.getPosition().y);
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
square.move(-speed.x * dt,0.f);
if(Collision(square,square2))
{
square.setPosition(square2.getPosition().x + square2.getSize().x,square.getPosition().y);
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
square.move(0.f,speed.y * dt);
if(Collision(square,square2))
{
square.setPosition(square.getPosition().x,square2.getPosition().y - square.getSize().y);
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
square.move(0.f,-speed.y * dt);
if(Collision(square,square2))
{
square.setPosition(square.getPosition().x,square2.getPosition().y + square2.getSize().y);
}
}
window.clear();
window.draw(square);
window.draw(square2);
window.display();
}
return 0;
}