Handling the collisions
Currently, collisions are not tested. The player can walk over the trees and stones. Let us resolve that.Testing the collision between two sprites
The class sf::FloatRect is almost the same as sf::IntRect. The only difference is that its members (Representing its position and size) are of type 'float' rather than 'int'.The method 'getGlobalBounds' of the class sf::Sprite returns an object of type sf::FloatRect representing its boundaries.
The class sf::FloatRect has a method called 'intersects' that returns 'true' if it is in collision with the sf::FloatRect object it received in argument and 'false' otherwise.
Let us define two sprites:
C++:
sf::Sprite s1, s2;
C++:
if(s1.getGlobalBounds().intersects(s2.getGlobalBounds()))
{
// The instructions here are executed if the two sprites are in collision.
}
The strategy
There are many ways to handle collisions. Here, we will employ a simple technique. It comes as follow: After each translation of the character, we test if it is in collision with any of the objects inside the game (Trees, stones...). If it is, we cancel the previous movement (We subtract the translation vector that we added to the position of the character). Otherwise, we do nothing. Basically, if a translation causes the player 'merge' with an object, we cancel it. Because the movement of the player is updated very frequently (Many very small movements), the character will stop right before he comes to collision with an object.The code
Here is the code handling the collisions between the player and the trees:
C++:
// For each tree.
for(int c=0; c < 8; c++)
{
// If the player is in collision with the tree.
if(player.getGlobalBounds().intersects(trees[c].getGlobalBounds()))
{
// We cancel the movement.
player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
}
}
C++:
for(int c=0; c < 3; c++)
{
if(player.getGlobalBounds().intersects(stones[c].getGlobalBounds()))
player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
}
The code of the game so far
C++:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow win(sf::VideoMode(800, 600), "Introduction to coding", sf::Style::Close);
// Grass
sf::Texture grassTex;
grassTex.loadFromFile("resources/grass.png");
grassTex.setRepeated(true);
sf::Sprite grass;
grass.setTexture(grassTex);
grass.setScale(5, 5);
grass.setTextureRect(sf::IntRect(0,0,160,120));
// Dirt tiles
sf::Texture dirtTex;
dirtTex.loadFromFile("resources/dirt.png");
sf::Sprite dirtTiles[10];
dirtTiles[0].setPosition(300, 60);
dirtTiles[1].setPosition(660, 300);
dirtTiles[2].setPosition(390, 480);
dirtTiles[3].setPosition(660, 60);
dirtTiles[4].setPosition(720, 420);
dirtTiles[5].setPosition(180, 300);
dirtTiles[6].setPosition(60, 180);
dirtTiles[7].setPosition(60, 420);
dirtTiles[8].setPosition(240, 420);
dirtTiles[9].setPosition(480, 120);
for(int c = 0; c < 10; c++)
{
dirtTiles[c].setTexture(dirtTex);
dirtTiles[c].setScale(5, 5);
}
// Trees
sf::Texture treeTex;
treeTex.loadFromFile("resources/tree.png");
sf::Sprite trees[8];
trees[0].setPosition(50, 60);
trees[1].setPosition(600, 150);
trees[2].setPosition(630, 456);
trees[3].setPosition(300, 600);
trees[4].setPosition(720, 40);
trees[5].setPosition(460, 500);
trees[6].setPosition(20, 370);
trees[7].setPosition(340, 240);
for(int c = 0; c < 8; c++)
{
trees[c].setTexture(treeTex);
trees[c].setScale(3, 3);
}
// Stones
sf::Texture stoneTex;
stoneTex.loadFromFile("resources/stone.png");
sf::Sprite stones[3];
stones[0].setPosition(304, 64);
stones[1].setPosition(664, 304);
stones[2].setPosition(180, 300);
for(int c = 0; c < 3; c++)
{
stones[c].setTexture(stoneTex);
stones[c].setScale(3, 3);
}
// Player
sf::Texture playerTex;
playerTex.loadFromFile("resources/player.png");
sf::Sprite player;
player.setTexture(playerTex);
player.setPosition(400, 300);
player.setScale(3, 3);
float playerMovementSpeed = 200.0;
sf::Clock playerMovementClock;
// Game loop
sf::Event event;
while(win.isOpen())
{
while(win.pollEvent(event))
{
if(event.type == sf::Event::Closed)
win.close();
}
// Player movements
sf::Vector2f trans;
float mouv =
playerMovementClock.getElapsedTime().asSeconds() *
playerMovementSpeed;
if(sf:⌨️:isKeyPressed(sf:⌨️:W))
trans.y -= mouv;
if(sf:⌨️:isKeyPressed(sf:⌨️:S))
trans.y += mouv;
if(sf:⌨️:isKeyPressed(sf:⌨️:A))
trans.x -= mouv;
if(sf:⌨️:isKeyPressed(sf:⌨️:D))
trans.x += mouv;
player.setPosition(player.getPosition().x+trans.x, player.getPosition().y+trans.y);
playerMovementClock.restart();
// Collision testing
for(int c=0; c < 8; c++)
{
if(player.getGlobalBounds().intersects(trees[c].getGlobalBounds()))
player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
}
for(int c=0; c < 3; c++)
{
if(player.getGlobalBounds().intersects(stones[c].getGlobalBounds()))
player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
}
// Rendering
win.clear();
win.draw(grass);
for(int c = 0; c < 10; c++)
win.draw(dirtTiles[c]);
for(int c = 0; c < 8; c++)
win.draw(trees[c]);
for(int c = 0; c < 3; c++)
win.draw(stones[c]);
win.draw(player);
win.display();
}
return 0;
}
Last edited by a moderator: