tld;dr: Character movement glitches easily, doesn't always seem to register key releases, and is overall poor; any suggestions for improvements (or bug fixes)?
Hello,
I'm (still) working on making a relatively simple platformer game in SFML with C++, and I'm struggling with making smooth movement. My 'map' is composed of a grid of (x,y) pairs, which define the tile that is to be displayed at that point (the x and y represent the co-ordinates of the tile sprite in my level spritesheet).
The problem that I'm having is that even though the movement seems to work, it sometimes behaves in an unintended way, and I don't know how to fix it, or even why it might be happening.
For example, spamming (rapidly pressing) the arrow keys, you can sometimes get the character to slide across the map (and lose control of him) until he hits something. Other times, (usually while coming in at an angle) you can get stuck in the floor, and be unable to move unless you first jump to get unstuck.
As of right now, I'm doing collision detection through the use of 4 points which represent the rectangle that is the character's hitbox, so that might be part of the issue.
(Side note: my key presses also only detect the arrow keys and not WASD ... even though they are in the same if statement)
(main.cpp)(relevant code)
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right)
thePlayer.goingRight = true;
if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)
thePlayer.goingLeft = true;
if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)
{
thePlayer.isJumping = true;
thePlayer.goingUp = true;
}
if (event.key.code == sf::Keyboard::S || event.key.code == sf::Keyboard::Down)
thePlayer.goingDown = true;
}
if (event.type == sf::Event::KeyReleased)
{
if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right)
thePlayer.goingRight = false;
if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)
thePlayer.goingLeft = false;
if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)
thePlayer.goingUp = false;
if (event.key.code == sf::Keyboard::Space)
{
if (bulletsfired != true)
{
bulletsfired = true;
if (thePlayer.directionFacing == 0)
{
bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
}
else
{
bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x + 25.f, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
}
bulletCount++;
}
}
}
thePlayer.updatePlayer();
for (int i = 0; i < bulletsList.size(); i++)
{
bulletsList[i].update();
}
(player.cpp)(relevant code)
void player::updatePlayer()
{
if (player::isJumping == true)
player::goingDown = true;
playerPosX = player::mSprite.getPosition().x;
playerPosY = player::mSprite.getPosition().y;
//Gravity
if (((map[(playerPosY+48)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+48)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+28)/32].y) != 0 ))
{
player::isJumping = false;
player::goingDown = false;
}
else
{
player::isJumping = true;
player::goingDown = true;
}
//Collision top
if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
{
player::goingUp = false;
}
//Collision right
if (((map[(playerPosY+46)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+28)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
{
if (((map[(playerPosY+46)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+46)/32][(playerPosX+28)/32].y) == 5 ) && ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+28)/32].y) == 5 ))
{
std::cout << "Ladder right!";
player::goingDown = false;
player::isJumping = false;
}
else
{
player::goingRight = false;
}
}
//Collision left
if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+46)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+5)/32].y) != 0 ))
{
if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+5)/32].y) == 5 ) && ((map[(playerPosY+46)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+46)/32][(playerPosX+5)/32].y) == 5 ))
{
std::cout << "Ladder left!";
player::goingDown = false;
player::isJumping = false;
}
else
{
player::goingLeft = false;
}
}
if (player::goingRight == true)
{
player::moveRight(player::playerSpeed);
}
if (player::goingLeft == true)
{
player::moveLeft(player::playerSpeed);
}
if (player::goingDown == true)
{
player::moveDown(player::playerFallSpeed);
}
if (player::goingUp == true)
{
player::moveUp(player::playerJumpSpeed);
}
if (player::goingRight == true && player::goingUp == true)
{
player::mSprite.move(player::playerSpeed * 0.5 , -player::playerJumpSpeed * 0.5);
}
if (player::goingLeft == true && player::goingUp == true)
{
player::mSprite.move(-player::playerSpeed * 0.5 , -player::playerJumpSpeed * 0.5);
}
if (player::goingRight == true && player::goingDown == true)
{
player::mSprite.move(player::playerSpeed * 0.5 , player::playerFallSpeed * 0.5);
}
if (player::goingLeft == true && player::goingDown == true)
{
player::mSprite.move(-player::playerSpeed * 0.5 , player::playerFallSpeed * 0.5);
}
}
The tile defined by map[i][j].x = 4, map[i][j].y = 5 is a 'ladder' tile, so I want the player to be able to move through it (and also why it outputs "Ladder /direction/!" to the console).
If it is at all relevant; playerSpeed = 4.f; playerFallSpeed = 5.f; playerJumpSpeed = 10.f;
Finally, thanks for reading through this wall of text! I really appreciate any and all help, since I've been struggling with this for about a week now.
goingRight
,goingLeft
,goingDown
...) and what the hell is the difference betweenisJumping
andgoingUp
? You will never have the situation when both,goingLeft
andgoingRight
will be used, will you? Why don't you have one vector representing movement? It could perfectly (and clearly) handle the situations when player is jumping and going left at the same time! Have a look here – sjaustirni