I'd just like to say thanks again for all the swift and very helpful replies. I certainly have a lot to work with here!
In regards to everything that's been said, I've already implemented a few of these concepts. I like to keep my sections
separate depending on what they do. For example, I handle all the input, whether that's from a controller, mouse, keyboard, or
AI command, then convert that into some kind of intent.
The intent can then be worked with once, so everything down the line doesn't have to keep checking for different types of input!
This intent can then drive the states of my entities, so, for example, say it has an enum for its different states (walking, still, jumping, attacking1,
attacking2, etc), the methods called after these checks don't have to check against 10-20 different variables, and instead just
check if the entity's state is a certain way.
For example, if I have 10 separate lines of code that need to know if I'm standing, it's better to have:
if (this, that, something else, another thing, some variables doing stuff, this is on, etc)
{
currentState == PhysicalStates.Standing;
}
//Then further down the code
if (currentState == PhysicalStates.Standing)
{
//Do something hilarious
}
Since every check to see if I'm standing only has to check the PhysicalStates enum. So in that respect, my code is data-driven
to some extent. I also separate the animation completely into its own method, so that the movement, collisions, etc, don't have bits
of animation code wedged in. I originally did that, and it was a nightmare to maintain the animation, especially when adding new
animations in that I hadn't previously accounted for. I'd have to change the code massively to account for a single line.
Using this approach, I then have a ChangeAnimation() method in each entity (abstractly inherited) which separately checks if
the animation should change after all the logic nitty gritty code has been executed.
I hope this helps anyone who's having trouble with animation themselves.
I have to say that Alberth's state machines write-up is immensely helpful! I think that implementing two state machines (one for logical states
and another for animation states) is the best way for me to go. As I previously said, my code worked, but it was a messy jumble of if nests.
It's a relief to know that there's no "simple" solution to this problem. But if I implement the state machine concept, I'm pretty sure there's no way
the animations could go wrong.
I'm also going to change my animation class to simply have preset animations. At the moment, it's more like:
if (currentState == PhysicalStates.Dying)
{
animation.startPosX = 2;
animation.startPosY = 3;
animation.playSpeed = 5;
animation.replay = false;
}
After looking into this, it seems a much more maintainable approach would be to link these variable changes to their own
state, so a newer version could simply be:
if (currentState == PhysicalStates.Dying)
{
animation.Play("death");
}
The "death" animation would then essentially play an animation which was already defined as:
animation.startPosX = 2;
animation.startPosY = 3;
animation.playSpeed = 5;
animation.replay = false;
That's about my take on it anyway! Does this seem like the practical way to go about it? I want to make sure
I fully understand where people are going with this :)