Проблема с прохождением сквозь объект при определенных условиях на SFML C++
Я хочу сделать простейшее отталкивание объекта от другого объекта, если вектор перемещения задевает другой объект. Код частично работает, но если столкновение происходит по координате X, то если объект достаточно низко или высоко, при этом еще входя в объект, проверка на отталкивания не происходит
Реализации в классе Game пока нет, кроме конструктора, который создает окно, поэтому только заголовочный файл
game.hpp
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "window.hpp"
#include "event.hpp"
#include "view.hpp"
class Game {
public:
sf::ContextSettings settings;
sf::RenderWindow *window;
sf::Event event;
sf::View view;
sf::Clock clock;
double time;
double deltaTime;
Game(unsigned int widthWindow, unsigned int heightWindow);
void menu();
void update();
void pause();
void destroy();
};
main.cpp
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "game.hpp"
int main() {
//Переменные
Game game(1280, 720);
bool wannaToJump = 0;
double gravity = 0.0005;
double speed = 0.5;
double jumpForce = 0.2;
double bounce = 0.1;
//Создание игрока
sf::Vector2f velocity;
sf::RectangleShape player;
player.setFillColor(sf::Color::White);
player.setSize(sf::Vector2f(32, 32));
player.setOrigin(sf::Vector2f(16, 16));
player.setPosition(sf::Vector2f(640, 300));
//Хитбокс игрока
sf::RectangleShape hitbox;
hitbox.setFillColor(sf::Color::Green);
hitbox.setSize(sf::Vector2f(32, 32));
hitbox.setOrigin(sf::Vector2f(16, 16));
hitbox.setPosition(sf::Vector2f(640, 300));
//Массив объектов
int blockCount = 20;
sf::RectangleShape block[blockCount];
for (int i = 0; i < 10; ++i) {
block[i].setFillColor(sf::Color::Red);
block[i].setSize(sf::Vector2f(32, 32));
block[i].setOrigin(sf::Vector2f(16, 16));
block[i].setPosition(sf::Vector2f((i + 11) * 32, 500));
}
for (int i = 10; i < 20; ++i) {
block[i].setFillColor(sf::Color::Red);
block[i].setSize(sf::Vector2f(32, 32));
block[i].setOrigin(sf::Vector2f(16, 16));
block[i].setPosition(sf::Vector2f((i - 2) * 32, 400));
}
while (game.window->isOpen()) {
game.time = game.clock.getElapsedTime().asMicroseconds();
game.clock.restart();
game.time = game.time / 800;
while (game.window->pollEvent(game.event)) {
if (game.event.type == sf::Event::Closed) {
game.window->close();
}
}
//Перемещение хитбокса к игроку
hitbox.setPosition(player.getPosition());
//Падение вниз
velocity.y += gravity * game.time;
//Перемещение игрока
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
velocity.x = speed * game.time;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
velocity.x = -speed * game.time;
}
else {
velocity.x = 0;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
wannaToJump = 1;
}
hitbox.move(velocity);
//Если игрок касается какого либо другого объекта и значение wannaToJump истино, то
//изменить перемещение Y на силу прыжка
for (int i = 0; i < blockCount; ++i) {
if (hitbox.getGlobalBounds().intersects(block[i].getGlobalBounds())) {
if (wannaToJump) {
velocity.y = -jumpForce * game.time;
}
}
}
hitbox.move(velocity);
//Проверяет, не содержит ли хитбокс какой либо объект
for (int i = 0; i < blockCount; ++i) {
if (hitbox.getGlobalBounds().intersects(block[i].getGlobalBounds())) {
//Если хитбокс ближе к объекту по Y, то инвертировать вектор перемещения по Y
if (abs(hitbox.getPosition().y - block[i].getPosition().y) >
abs(hitbox.getPosition().x - block[i].getPosition().x)) {
velocity.y = -velocity.y * bounce;
}
//Иначе, если хитбокс ближе к объекту по X, то инвертировать вектор перемещения
//по X
//Проблема, видимо, здесь
if (abs(hitbox.getPosition().y - block[i].getPosition().y) <
abs(hitbox.getPosition().x - block[i].getPosition().x)) {
velocity.x = -velocity.x * bounce;
}
}
}
wannaToJump = 0;
player.move(velocity);
//Отрисовка
game.window->clear();
for (int i = 0; i < blockCount; ++i) {
game.window->draw(block[i]);
}
game.window->draw(hitbox);
game.window->draw(player);
game.window->display();
}
return 0;
}