I'm a relatively new programmer attempting to create a simple 2d fighter for fun using the SFML 2 library. As a game with interaction dependent on what the character is doing, using a state system seems to be the way to go. I've been trying to incorporate a finite state machine. My question is, what is the best way to go about this? Currently I have something like this:
switch (playerstate)
{
case idle:
if (!onGround)
{
playerstate = fall;
}
else if (sf::Keyboard::isKeyPressed(controls.Up))
{
moveUp();
playerstate = air;
}
else if (sf::Keyboard::isKeyPressed(controls.Down))
{
playerstate = crouch;
}
else if (sf::Keyboard::isKeyPressed(controls.Right))
{
moveRight();
playerstate = dash;
}
else if (sf::Keyboard::isKeyPressed(controls.Left))
{
moveLeft();
playerstate = dash;
}
else
{
decelOnGround();
}
break;
case dash:
if (!onGround)
{
playerstate = fall;
}
else if (sf::Keyboard::isKeyPressed(controls.Up))
{
moveUp();
playerstate = air;
}
else if (sf::Keyboard::isKeyPressed(controls.Down))
{
playerstate = crouch;
}
else if (sf::Keyboard::isKeyPressed(controls.Right))
{
moveRight();
}
else if (sf::Keyboard::isKeyPressed(controls.Left))
{
moveLeft();
}
else
{
decelOnGround();
playerstate = idle;
}
break;
case air:
if (onGround)
{
playerstate = idle;
}
else if (sf::Keyboard::isKeyPressed(controls.Up))
{
// if numOfJumps > 0, moveUp();
}
else if (sf::Keyboard::isKeyPressed(controls.Down))
{
fastFall();
}
else if (sf::Keyboard::isKeyPressed(controls.Right))
{
moveRight();
}
else if (sf::Keyboard::isKeyPressed(controls.Left))
{
moveLeft();
}
break;
case fall:
if (onGround)
{
playerstate = idle;
}
else if (sf::Keyboard::isKeyPressed(controls.Down))
{
fastFall();
}
break;
case crouch:
if (sf::Keyboard::isKeyPressed(controls.Up))
{
moveUp();
playerstate = air;
}
else if (sf::Keyboard::isKeyPressed(controls.Down))
{
decelOnGround();
playerstate = crouch;
}
else if (sf::Keyboard::isKeyPressed(controls.Right))
{
moveRight();
playerstate = dash;
}
else if (sf::Keyboard::isKeyPressed(controls.Left))
{
moveLeft();
playerstate = dash;
}
else
{
playerstate = idle;
}
break;
default:
std::cout << "ERROR\n";
}
Which as you can see, there is a lot of repetition and a lot of code. I haven't even incorporated using different attacks yet (I'm going to have a variety of these). Am I approaching this the wrong way? Should I instead have each control be a case instead and branch from there? Any help is appreciated!