I am trying to make a pac game. I am using C++ and sfml. Everything looks fine for now, but the problem is that I don't have an idea how to make the map collision detection. I am loading the map from .bmp file. Here is a picture:
Is there a way to set wall cordinates so I could detect them on a collision ?
Here is a part of my code:
sf::RenderWindow window(sf::VideoMode(451, 500), "Packman", sf::Style::Close);
sf::Image icon;
icon.loadFromFile("pac_icon.png");
window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());
sf::Texture tMap;
tMap.loadFromFile("pac_map.bmp");
sf::Sprite sprMap;
sprMap.setTexture(tMap);
Pac oPac(window);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::EventType::Closed)
{
window.close();
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)
&& !(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down)))
{
oPac.MoveRight();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)
&& !(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down)))
{
oPac.MoveLeft();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
oPac.MoveUp();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
oPac.MoveDown();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
window.close();
}
window.clear();
window.draw(sprMap);
oPac.Update();
window.display();
}
The simplest thing you can do is to divide your world into cells.
Every elements of your game can be placed into a tile (2D array of boolean for example, true is there is an element
and false is there is no element
).
Your character will be able to change its direction with your controls, and its position x and y will be modified over time depending on its direction.
You'll have to make an algorithm that checks if a tile is reachable from another tile given a direction. Thus, you'll be able to move your character in a direction and stops him when he can't reach a tile (Which is basically a collision detection + solving a collision).
If you want to learn about 2D collisions, here is a great article that treats 2D tilemap collision: https://jonathanwhiting.com/tutorial/collision/.
Example of tilemap stored into a 2D array:
bool world[5][5] =
{
{ 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1 }
};
std::pair<int> playerPosition { 1, 1 };
Of course, you can load these information from a file. You can imagine a very basic data formatting:
11111
10001
10101
10001
11111
A getline()
call + a char by char parsing for each line would do the job to parse this file
Pro tip: You can also write your level information in one line, assuming that every 5 chars you treat another line (height of your level) (Depending on your level width). It will reduce the parsing time and will also reduce your level file size (Ex: 1111110001101011000111111
)
Pro tip 2: You can encode your level data into integers or hexadecimals, thus, when you'll parse your file you'll need to convert these values into an arrays of booleans (Every boolean value will be determined by one bit of the integer/hexadecimal). 127[decimal]
can be represented as 01111111[binary]
, thus you can write more information with less characters, but you'll have to seperate your integers with some ',' (Ex: 31,17,21,17,31
to keep the same map as previous examples)