Hi,
I have been able to successfully generate a random maze but am having issues with the collision detection for a simple square moving around the maze.
I have been able to get it to work effectively. My issue I think is in the timestep.
My current issue is that when the square is moving along the maze and then comes across a T intersection. Refer picture for better explanation
[attachment=29136:collisionDetectionIssue.jpg]
The blue player cannot go down.
I thought of one way to do it is that when the player stops moving, check to see which direction they were moving and if it is say 3 pixels away from covering the tile completely then move the extra 3 pixels. The problem with this is that if I'm moving say left and down, it still won't go in the down direction until I stop moving.
Currently in my code I check all 4 points of the blue square to see what tile it is going to move into. so when he is in that position going down the Right bottom corner will be in a wall so it won't let him move down.
Here is all the code for main.cpp. I will eventually move it into classes etc, but just want to get it working properly first.
#include "main.h"
std::vector <int> MazeData;
int TileSizeX = 32;
int TileSizeY = 32;
int playersize = 32;
int scale = 1; // not in use currently
int MazeSizeX = 15; int MazeSizeY = 15;
struct collision
{
bool TopLeft;
bool TopRight;
bool BottomLeft;
bool BottomRight;
};
collision CheckCollision(sf::Vector2f PlayerPosition, int movex, int movey); // check to see if new position is valid
int main()
{
float TimePerFrame = 1.f / 60.f; // 60 updates a second
float timesincelastupdate = 0;
sf::Clock DeltaTime;
sf::Clock FPS;
DeltaTime.restart().asSeconds();
FPS.restart().asSeconds();
int framerate = 0;
float DT; // Delta Time
sf::RenderWindow mywindow(sf::VideoMode(912,912),"Mazes");
srand( unsigned (time(0)));
MazeData.resize(MazeSizeX*MazeSizeY);
MazeGenerator NewMaze;
NewMaze.GenerateNewMaze(MazeData, MazeSizeX, MazeSizeY);
sf::Sprite Wall;
sf::Sprite Floor;
sf::Sprite Player;
sf::Texture WallTexture;
sf::Texture FloorTexture;
sf::Texture PlayerTexture;
PlayerTexture.loadFromFile("./Res/Player.png", sf::IntRect(0, 0, playersize, playersize));
WallTexture.loadFromFile("./Res/Wall.png", sf::IntRect(0, 0, TileSizeX, TileSizeY));
FloorTexture.loadFromFile("./Res/Floor.png", sf::IntRect(0, 0, TileSizeX, TileSizeY));
Wall.setTexture(WallTexture);
Floor.setTexture(FloorTexture);
Player.setTexture(PlayerTexture);
// setup player
int x = 1; int y = 1;
Player.setPosition(x * TileSizeX, y * TileSizeX);
float PlayerSpeed = 400.0f;
int MoveX = 0;
int MoveY = 0;
while (mywindow.isOpen())
{
sf::Event event;
while (mywindow.pollEvent(event))
{
if (event.type == sf::Event::Closed)
mywindow.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
mywindow.close();
}
while (timesincelastupdate > TimePerFrame)
{
MoveY = 0;
MoveX = 0;
timesincelastupdate -= TimePerFrame;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
MoveY += -1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
MoveY += 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
MoveX += -1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
MoveX += 1;
}
float PlayerPosX = 0;
float PlayerPosY = 0;
if (MoveX != 0)
{
PlayerPosX = Player.getPosition().x;
float test = PlayerPosX;
PlayerPosY = Player.getPosition().y;
if (MoveX == 1)
{
PlayerPosX += TileSizeX; // if player moving right, check right side of player
}
PlayerPosX += MoveX * PlayerSpeed * TimePerFrame;
int tilex = PlayerPosX / TileSizeX;
int tiley = PlayerPosY / TileSizeY;
int newtile = tilex + (tiley * MazeSizeX);
if (MazeData[newtile] != 0)
{
collision collide = CheckCollision(Player.getPosition(), MoveX, 0);
if (collide.TopLeft == false && collide.TopRight == false
&& collide.BottomLeft == false && collide.BottomRight == false)
{
Player.move(TimePerFrame * PlayerSpeed * MoveX, 0); // no collision so move player
}
}
if (MoveX == -1 && MazeData[newtile] == 0) // moving left and hit wall tile so we move player up against wall
{
int xtile = newtile % MazeSizeX;
int ytile = newtile / MazeSizeX;
Player.setPosition((xtile * TileSizeX) + TileSizeX, Player.getPosition().y);
}
if (MoveX == 1 && MazeData[newtile] == 0) // moving right and hit wall tile so we move player up against wall
{
int xtile = newtile % MazeSizeX;
int ytile = newtile / MazeSizeX;
Player.setPosition((xtile * TileSizeX) - TileSizeX, Player.getPosition().y);
}
}
if (MoveY != 0)
{
PlayerPosX = Player.getPosition().x;
PlayerPosY = Player.getPosition().y;
PlayerPosY += MoveY * PlayerSpeed * TimePerFrame;
int tilex = PlayerPosX / TileSizeX;
if (MoveY == 1)
{
PlayerPosY += TileSizeY;
}
int tiley = PlayerPosY / TileSizeY;
int newtile = tilex + (tiley * MazeSizeX);
if (MazeData[newtile] != 0)
{
collision collide = CheckCollision(Player.getPosition(), 0, MoveY);
if (collide.TopLeft == false && collide.TopRight == false
&& collide.BottomLeft == false && collide.BottomRight == false)
{
Player.move(0, TimePerFrame * PlayerSpeed * MoveY);
}
}
if (MoveY == -1 && MazeData[newtile] == 0) // moving left and hit wall tile so we move player up against wall
{
int xtile = newtile % MazeSizeX;
int ytile = newtile / MazeSizeX;
Player.setPosition(Player.getPosition().x, (ytile * TileSizeY) + TileSizeY);
}
if (MoveY == 1 && MazeData[newtile] == 0) // moving right and hit wall tile so we move player up against wall
{
int xtile = newtile % MazeSizeX;
int ytile = newtile / MazeSizeX;
Player.setPosition(Player.getPosition().x, (ytile * TileSizeY) - TileSizeY);
}
}
}
mywindow.clear(sf::Color::Blue);
// DRAW TILES
for (int x = 0; x < MazeSizeX; x++)
{
for (int y = 0; y < MazeSizeY; y++)
{
int a = MazeData[x + y * MazeSizeX];
if (a == 0)//draw wall
{
Wall.setPosition(x * TileSizeX * scale, y * TileSizeY * scale);
mywindow.draw(Wall);
}
else // draw floor
{
Floor.setPosition(x * TileSizeX * scale, y * TileSizeY * scale);
mywindow.draw(Floor);
}
}
}
// draw player
mywindow.draw(Player);
mywindow.display();
framerate++;
DT = DeltaTime.getElapsedTime().asSeconds();
timesincelastupdate += DT;
PlayerMovecount -= DT;
DeltaTime.restart().asSeconds();
//
if (FPS.getElapsedTime().asSeconds() > 1.0)
{
// 1 second has passed so print FPS in title
mywindow.setTitle("Mazes V0.3 | " + std::to_string(framerate) + " FPS");
framerate = 0;
FPS.restart().asSeconds();
}
}
return 0;
}
collision CheckCollision(sf::Vector2f PlayerPosition, int movex, int movey)
{
collision testcollision{ false, false, false, false };
float PosX = PlayerPosition.x + movex;
float PosY = PlayerPosition.y + movey;
int tilex = (PosX / TileSizeX);
int tiley = (PosY / TileSizeY);
int newtileTL = tilex + (tiley * MazeSizeX);
tilex = (PosX + TileSizeX -1) / TileSizeX; // top right
tiley = (PosY / TileSizeY);
int newtileTR = tilex + (tiley * MazeSizeX);
tilex = (PosX / TileSizeX ); // Bottom Left;
tiley = (PosY + TileSizeY-1) / TileSizeY;
int newtileBL = tilex + (tiley * MazeSizeX);
tilex = (PosX + TileSizeX-1) / TileSizeX;
tiley = (PosY + TileSizeY-1) / TileSizeY;
int newtileBR = tilex + (tiley * MazeSizeX);
if (MazeData[newtileTL] == 0)
{
testcollision.TopLeft = true;
}
if (MazeData[newtileTR] == 0)
{
testcollision.TopRight = true;
}
if (MazeData[newtileBL] == 0)
{
testcollision.BottomLeft = true;
}
if (MazeData[newtileBR] == 0)
{
testcollision.BottomRight = true;
}
return testcollision;
}
Thanks
P.S. Yeah I am a beginner so be gentle!