So ive been re learning SFML and i really wanted to learn collision, and i understand it far better now, but im still having a few issues, here is my code, what am i doing wrong with my collision? its not working.
//============================================================================
// Name : SFML Game
// Author : Chay Hawk
// Version : 0.0.14
// Version Date : March 24th 2023 @ 11:27 AM
// Date Created :
// Lines of Code : 224
// Description :
//============================================================================
#include <iostream>
#include <string>
#include <sstream>
#include <SFML/Graphics.hpp>
sf::Text CreateText(const sf::Font& font, int characterSize, const sf::Color& color, float posX, float posY, const std::string& str)
{
sf::Text text;
text.setCharacterSize(characterSize);
text.setFont(font);
text.setFillColor(color);
text.setPosition(sf::Vector2f(posX, posY));
text.setString(str);
return text;
}
std::unique_ptr<sf::RectangleShape> CreateRectangle(float width, float height, const sf::Color& color, float setXPos, float setYPos)
{
std::unique_ptr<sf::RectangleShape> rectangle(new sf::RectangleShape);
rectangle->setSize(sf::Vector2f(width, height));
rectangle->setFillColor(color);
rectangle->setPosition(sf::Vector2f(setXPos, setYPos));
rectangle->setOrigin(sf::Vector2f(rectangle->getSize().x / 2, rectangle->getSize().y / 2));
return rectangle;
}
int main()
{
sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML Feature Testing");
window.setFramerateLimit(60);
sf::Font Arial;
Arial.loadFromFile("Resources/Fonts/arial.ttf");
std::ostringstream oss;
std::istringstream iss;
float windowCenterX{ window.getSize().x / 2.0f };
float windowCenterY{ window.getSize().y / 2.0f };
sf::Text MouseXText{ CreateText(Arial, 32, sf::Color::White, 0.0f, 0.0f, "Mouse X Position: ") };
sf::Text MouseXValue{ CreateText(Arial, 32, sf::Color::White, 0.0f, 0.0f, "Mouse X Value: ") };
sf::Text MouseYText{ CreateText(Arial, 32, sf::Color::White, 0.0f, 0.0f, "Mouse Y Pos: ") };
sf::Text MouseYValue{ CreateText(Arial, 32, sf::Color::White, 204, 30, "Mouse Y Value : ") };
MouseXValue.setPosition(sf::Vector2f(MouseXText.getPosition().x + MouseXText.getGlobalBounds().width, 0.0f));
MouseYText.setPosition(sf::Vector2f(0, MouseXText.getPosition().y + MouseXText.getGlobalBounds().height + 5));
//Center Square
auto square{ CreateRectangle(300, 300, sf::Color::White, windowCenterX, windowCenterY) };
float squareLeft{ };
float squareTop{ };
float squareRight{ };
float squareBottom{ };
//Squares
auto cornerSquare_1 { CreateRectangle(35, 35, sf::Color::Blue, 0, 0) };
auto cornerSquare_2 { CreateRectangle(35, 35, sf::Color::Cyan, 0, 0) };
auto cornerSquare_3 { CreateRectangle(35, 35, sf::Color::Green, 0, 0) };
auto cornerSquare_4 { CreateRectangle(35, 35, sf::Color::Red, 0, 0) };
int playerX{ 150 };
int playerY{ 150 };
//Player
auto player{ CreateRectangle(32, 32, sf::Color::Yellow, playerX, playerY) };
float playerLeft{ };
float playerTop{ };
float playerRight{ };
float playerBottom{ };
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
if (event.type == sf::Event::Resized)
{
window.setView(sf::View(sf::FloatRect(0.0f, 0.0f, static_cast<float>(event.size.width), static_cast<float>(event.size.height))));
square->setPosition(sf::Vector2f(window.getSize().x / 2, window.getSize().y / 2));
}
}
oss << sf::Mouse::getPosition(window).x;
MouseXValue.setString(oss.str());
oss.str("");
oss << sf::Mouse::getPosition(window).y;
MouseYValue.setString(oss.str());
oss.str("");
/*std::cout << "Player X Position: " << player->getPosition().x << '\n';
std::cout << "Player Y Position: " << player->getPosition().y << '\n';*/
std::cout << "Player X Left Side: " << player->getPosition().x - player->getOrigin().x << '\n';
std::cout << "Player Y Top: " << player->getPosition().y - player->getOrigin().y << '\n';
std::cout << "Player X Right Side: " << player->getPosition().x + player->getOrigin().x << '\n';
std::cout << "Player Y Bottom: " << player->getPosition().y + player->getOrigin().y << '\n';
if ( sf::Mouse::getPosition(window).x >= square->getPosition().x - square->getOrigin().x
&& sf::Mouse::getPosition(window).x <= square->getPosition().x + square->getOrigin().x
&& sf::Mouse::getPosition(window).y >= square->getPosition().y - square->getOrigin().y
&& sf::Mouse::getPosition(window).y <= square->getPosition().y + square->getOrigin().y
)
{
std::cout << "Within white square\n";
}
playerLeft = player->getPosition().x - player->getOrigin().x;
playerTop = player->getPosition().y - player->getOrigin().y;
playerRight = player->getPosition().x + player->getOrigin().x;
playerBottom = player->getPosition().y + player->getOrigin().y;
squareLeft = square->getPosition().x - square->getOrigin().x;
squareTop = square->getPosition().y - square->getOrigin().y;
squareRight = square->getPosition().x + square->getOrigin().x;
squareBottom = square->getPosition().y + square->getOrigin().y;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
if (playerTop >= squareBottom)
{
player->move(0, -5);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
if (playerLeft <= squareRight)
{
player->move(-5, 0);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
if (playerBottom <= squareTop)
{
player->move(0, 5);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
if (playerRight >= squareLeft)
{
player->move(5, 0);
}
}
//Set cornerSquare to one corner.
//Bottom Right (Blue)
cornerSquare_1->setPosition(sf::Vector2f(square->getPosition().x + square->getOrigin().x + cornerSquare_1->getOrigin().x, square->getPosition().y + square->getOrigin().y + cornerSquare_1->getOrigin().y));
//Top Left (Cyan)
cornerSquare_2->setPosition(sf::Vector2f(square->getPosition().x - square->getOrigin().x - cornerSquare_2->getOrigin().x, square->getPosition().y - square->getOrigin().y - cornerSquare_2->getOrigin().y));
//Top Right (Green)
cornerSquare_3->setPosition(sf::Vector2f(square->getPosition().x + square->getOrigin().x + cornerSquare_3->getOrigin().y, square->getPosition().y - square->getOrigin().y - cornerSquare_3->getOrigin().y));
//Bottom Left (Red)
cornerSquare_4->setPosition(sf::Vector2f(square->getPosition().x - square->getOrigin().x - cornerSquare_4->getOrigin().y, square->getPosition().y + square->getOrigin().y + cornerSquare_4->getOrigin().y));
window.clear();
window.draw(MouseXText);
window.draw(MouseXValue);
window.draw(MouseYText);
window.draw(MouseYValue);
window.draw(*player);
window.draw(*square);
window.draw(*cornerSquare_1);
window.draw(*cornerSquare_2);
window.draw(*cornerSquare_3);
window.draw(*cornerSquare_4);
window.display();
}
return 0;
}
Let's look at the D key case:
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
if (playerRight >= squareLeft)
{
player->move(5, 0);
}
}
The logic here is checking if the playerRight is to the right of the squareLeft. That could mean the player is to the left of the square but overlapping it, or the player is entirely to the right of the square and not overlapping. You don't want to move right if the player is to the left and overlapping.
Also there's no Y axis check in that one. It only considers the X positions, it doesn't check if they overlap on the Y.
To do a full overlap test you can do something like this:
bool overlap = (playerLeft <= squareRight) &&
(playerRight >= squareLeft) &&
(playerTop <= squareBottom) &&
(playerBottom >= squareTop);
That will tell if the player and square are currently definitely overlapping.
Although what you really want is to tell if they are going to overlap after a move, not if they currently overlap.
So you could find the desired movement first (don't do the move, just work out what it would be based on the keys), calculate the left, right, top, bottom if the move happened, check if that was an overlap, and don't do the move if overlap is true.
The other way would be to do the move regardless, then correct it afterwards (push the player out of the square). That will make them sit flush a bit better, but it's trickier to implement.
Generally I prefer to just use Box2D and let it deal with everything. :)