|
| 1 | +#include <iostream> |
| 2 | + |
1 | 3 | #include "Player.hpp" |
2 | 4 | #include <SFML/Window/Keyboard.hpp> |
| 5 | +#include <SFML/Graphics.hpp> |
3 | 6 |
|
4 | 7 | Player::Player() |
5 | 8 | : texture{}, |
@@ -78,34 +81,41 @@ Player::Player() |
78 | 81 | sprintingWestXStart = 240; sprintingWestYStart = 3120; sprintingWestXEnd = 1440; sprintingWestYEnd = 3120; |
79 | 82 | } |
80 | 83 |
|
81 | | -void Player::handleInput() { |
| 84 | +void Player::handleInput(std::vector<sf::FloatRect> wallBounds) { |
| 85 | + // Predict future collision |
| 86 | + sf::FloatRect nextBounds = sprite.getGlobalBounds(); |
| 87 | + |
82 | 88 | // If both right and up key pressed then move character right and up at same time |
83 | 89 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Right) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::D) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::W)) { |
84 | 90 | moving = true; northEast = true; |
85 | 91 | north = false; east = false; southEast = false; south = false; southWest = false; west = false; northWest = false; |
86 | | - sprite.move({horizontalSpeed / 1.5f, -verticalSpeed / 1.5f}); |
87 | | - // Waits for set amount of time then plays Jog north east animation |
88 | | - timer += 0.08f; |
89 | | - // Sprinting animation |
90 | | - if (timer >= timerMax && sprinting) {sprite.move({horizontalSpeed / 1.5f, -verticalSpeed / 1.5f}); textureX += 240; animate(sprintingNorthEastXStart, sprintingNorthEastXEnd, |
91 | | - sprintingNorthEastYStart, sprintingNorthEastYEnd); timer = 0.0f;} |
92 | | - // Jog animation |
93 | | - else if (timer >= timerMax) {textureX += 240; animate(JogNorthEastXStart, JogNorthEastXEnd, |
94 | | - JogNorthEastYStart, JogNorthEastYEnd); timer = 0.0f;} |
| 92 | + sf::Vector2f movement{horizontalSpeed / 1.5f, -verticalSpeed / 1.5f}; |
| 93 | + if (!handleCollision(movement, nextBounds, wallBounds)) { |
| 94 | + // Waits for set amount of time then plays Jog north east animation |
| 95 | + timer += 0.08f; |
| 96 | + // Sprinting animation |
| 97 | + if (timer >= timerMax && sprinting) {sprite.move({horizontalSpeed / 1.5f, -verticalSpeed / 1.5f}); textureX += 240; animate(sprintingNorthEastXStart, sprintingNorthEastXEnd, |
| 98 | + sprintingNorthEastYStart, sprintingNorthEastYEnd); timer = 0.0f;} |
| 99 | + // Jog animation |
| 100 | + else if (timer >= timerMax) {textureX += 240; animate(JogNorthEastXStart, JogNorthEastXEnd, |
| 101 | + JogNorthEastYStart, JogNorthEastYEnd); timer = 0.0f;} |
| 102 | + } |
95 | 103 | } |
96 | 104 | // If both right and down key pressed then move character right and down at same time |
97 | 105 | else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Right) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::D) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::S)) { |
98 | 106 | moving = true; southEast = true; |
99 | 107 | north = false; northEast = false; east = false; south = false; southWest = false; west = false; northWest = false; |
100 | | - sprite.move({horizontalSpeed / 1.5f, verticalSpeed / 1.5f}); |
101 | | - // Waits for set amount of time then plays Jog south east animation |
102 | | - timer += 0.08f; |
103 | | - // Sprinting animation |
104 | | - if (timer >= timerMax && sprinting) {sprite.move({(horizontalSpeed / 1.5f) * 3, (verticalSpeed / 1.5f) * 3}); textureX += 240; animate(sprintingSouthEastXStart, sprintingSouthEastXEnd, |
105 | | - sprintingSouthEastYStart, sprintingSouthEastYEnd); timer = 0.0f;} |
106 | | - // Jog animation |
107 | | - else if (timer >= timerMax) {textureX += 240; animate(JogSouthEastXStart, JogSouthEastXEnd, |
108 | | - JogSouthEastYStart, JogSouthEastYEnd); timer = 0.0f;} |
| 108 | + sf::Vector2f movement{horizontalSpeed / 1.5f, verticalSpeed / 1.5f}; |
| 109 | + if (!handleCollision(movement, nextBounds, wallBounds)) { |
| 110 | + // Waits for set amount of time then plays Jog south east animation |
| 111 | + timer += 0.08f; |
| 112 | + // Sprinting animation |
| 113 | + if (timer >= timerMax && sprinting) {sprite.move({(horizontalSpeed / 1.5f) * 3, (verticalSpeed / 1.5f) * 3}); textureX += 240; animate(sprintingSouthEastXStart, sprintingSouthEastXEnd, |
| 114 | + sprintingSouthEastYStart, sprintingSouthEastYEnd); timer = 0.0f;} |
| 115 | + // Jog animation |
| 116 | + else if (timer >= timerMax) {textureX += 240; animate(JogSouthEastXStart, JogSouthEastXEnd, |
| 117 | + JogSouthEastYStart, JogSouthEastYEnd); timer = 0.0f;} |
| 118 | + } |
109 | 119 | } |
110 | 120 | // If both left and up key pressed then move character left and up at same time |
111 | 121 | else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Left) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::A) && sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::W)) { |
@@ -236,6 +246,39 @@ void Player::handleInput() { |
236 | 246 | } |
237 | 247 | } |
238 | 248 |
|
| 249 | +bool Player::handleCollision(sf::Vector2f movement, sf::FloatRect nextBounds, std::vector<sf::FloatRect> wallBounds) { |
| 250 | +// Full movement prediction |
| 251 | + nextBounds.position += movement; |
| 252 | + |
| 253 | + for (const auto& wall : wallBounds) { |
| 254 | + if (nextBounds.findIntersection(wall).has_value()) { |
| 255 | + // Try horizontal-only movement |
| 256 | + sf::Rect<float> horizontalBounds = nextBounds; |
| 257 | + horizontalBounds.position.x -= movement.x; // Undo x movement |
| 258 | + |
| 259 | + if (!horizontalBounds.findIntersection(wall).has_value()) { |
| 260 | + sprite.move({0.f, movement.y}); // Slide vertically |
| 261 | + return true; |
| 262 | + } |
| 263 | + |
| 264 | + // Try vertical-only movement |
| 265 | + sf::Rect<float> verticalBounds = nextBounds; |
| 266 | + verticalBounds.position.y -= movement.y; // Undo y movement |
| 267 | + |
| 268 | + if (!verticalBounds.findIntersection(wall).has_value()) { |
| 269 | + sprite.move({movement.x, 0.f}); // Slide horizontally |
| 270 | + return true; |
| 271 | + } |
| 272 | + |
| 273 | + std::cout << "Blocked from all sides\n"; |
| 274 | + return true; // Fully blocked |
| 275 | + } |
| 276 | + } |
| 277 | + // No collision — move freely |
| 278 | + sprite.move(movement); |
| 279 | + return false; |
| 280 | +} |
| 281 | + |
239 | 282 | // Reusable function for animating player |
240 | 283 | void Player::animate(int xStart, int xEnd, int yStart, int yEnd) { |
241 | 284 | // If current texture coordinates outside of expected values then use start coordinates |
|
0 commit comments