by date
Blade's Edge: Character Design
Blade's Edge: Character Design
| Name: | William Clark | ![]() |
|---|---|---|
| Date Posted: | Jun 02, 2008 | |
| Rating: | Not Rated | |
| Public: | YES | |
| Comments: | YES | |
| RSS Feed: | or Subscribe with . | |
| Profile Page: | View profile page for William Clark |
Blog post
After working on some graphics effects and GUI stuff over the past few days, I decided to start working on the actual meat of the Blade's Edge project. I'm continuing to use Chrono Trigger sprites cause I don't feel like drawing crappy ones, and I worked on how to make Chrono move around, selecting from playing an idle, walk, or run animation, and whether to use up, down, or right versions of them (where the left animation is just the right one with FlipX = true).
Having worked with the Platformer Framework quite a bit, I decided that an animation manager using IFSMObject was the way to go. Basically, for those of you who haven't used it, that interface lets you design a finite state machine where each state is a little class you define, and you can override Enter, Exit, and Execute. You have to tell the FSM manager to call your Execute method from time to time (in an Update function, or when an AI finishes a task, or whatever), and within that method you check whether the state should change. If so, the FSM manager calls the current state's Exit, the next state's Enter, and then all further calls to Execute will check with the new state.
This works great for animation selection, and here's how I do it: In each of the states (Idle, Walk, Run), I use a function from the base class which checks the velocity of the Owner, and returns which of those types of motion to use. Then, if for example we're in the Idle state, we check if the function returned a type other than "Idle", and if so, tell the FSM to switch to the corresponding state. In the enter for each state, I tell the animated sprite to play that animation.
The Idle State
This all glosses over how to choose Up, Down, Left, or Right. In the Update function for the component itself, as you may have guessed from the code above, I update the _currentFacing and _facingChanged member variables. If _facingChanged is true, that means that this frame, the character went between two motion types; Up, Down or Horizontal. If this happens, the animation states tell the FSM manager that they want to change to the same state that they're already in, which causes Enter to be called again, which selects a different animation.
You might wonder why I split the facing check responsibility off the velocity checking, and it really comes down to that I didn't want to have IdleUp, IdleDown, and IdleRight as different states, and the states have no internal state (lol) so the character itself has to at least keep track of the current facing to know if we've changed.
Now I'm working on my plan for how to add modular pieces of functionality to characters, while still maintaining a hierarchy between them (i.e. a character that can die, necessitating having a DieAnim, will not perform any other actions after they do die). I've got some ideas on it, and once I've got it implemented, I'll write about the interesting parts of it.
(Edit: I've changed my plan somewhat as I tried working with this and found it to be unmanageable. My comment below explains the change.)
Having worked with the Platformer Framework quite a bit, I decided that an animation manager using IFSMObject was the way to go. Basically, for those of you who haven't used it, that interface lets you design a finite state machine where each state is a little class you define, and you can override Enter, Exit, and Execute. You have to tell the FSM manager to call your Execute method from time to time (in an Update function, or when an AI finishes a task, or whatever), and within that method you check whether the state should change. If so, the FSM manager calls the current state's Exit, the next state's Enter, and then all further calls to Execute will check with the new state.
This works great for animation selection, and here's how I do it: In each of the states (Idle, Walk, Run), I use a function from the base class which checks the velocity of the Owner, and returns which of those types of motion to use. Then, if for example we're in the Idle state, we check if the function returned a type other than "Idle", and if so, tell the FSM to switch to the corresponding state. In the enter for each state, I tell the animated sprite to play that animation.
The Idle State
public class IdleState : AnimationState
{
public override void Enter(IFSMObject obj)
{
base.Enter(obj);
CharacterMoverComponent characterComp = obj as CharacterMoverComponent;
characterComp._PlayAnimation(characterComp._idle[(int)characterComp._currentFacing]);
}
public override string Execute(IFSMObject obj)
{
string velocityAnim = base.Execute(obj);
CharacterMoverComponent characterComp = obj as CharacterMoverComponent;
if (velocityAnim != "idle" || characterComp._facingChanged)
return velocityAnim;
return null;
}
}
This all glosses over how to choose Up, Down, Left, or Right. In the Update function for the component itself, as you may have guessed from the code above, I update the _currentFacing and _facingChanged member variables. If _facingChanged is true, that means that this frame, the character went between two motion types; Up, Down or Horizontal. If this happens, the animation states tell the FSM manager that they want to change to the same state that they're already in, which causes Enter to be called again, which selects a different animation.
You might wonder why I split the facing check responsibility off the velocity checking, and it really comes down to that I didn't want to have IdleUp, IdleDown, and IdleRight as different states, and the states have no internal state (lol) so the character itself has to at least keep track of the current facing to know if we've changed.
Now I'm working on my plan for how to add modular pieces of functionality to characters, while still maintaining a hierarchy between them (i.e. a character that can die, necessitating having a DieAnim, will not perform any other actions after they do die). I've got some ideas on it, and once I've got it implemented, I'll write about the interesting parts of it.
(Edit: I've changed my plan somewhat as I tried working with this and found it to be unmanageable. My comment below explains the change.)
Recent Blog Posts
| List: | 06/02/08 - Blade's Edge: Character Design 05/29/08 - Blade's Edge -- Paletting works 05/28/08 - TorqueX Game: "Blade's Edge", Part 1 |
|---|
Submit your own resources!| Bobby Leighton (Jun 02, 2008 at 22:03 GMT) |
| William Clark (Jun 03, 2008 at 06:38 GMT) |
Regarding the .plan, I'm actually changing things to not use IFSMObject, cause there's too much interdependence between the different components, and a single FSM table is present per class (per component in this case) so instead I'm going to have a central component (CharacterComponent) that checks for other components on Register, and then is in charge of coordinating them. I think it'll be more maintainable than trying to do it with some sort of FSM interdependence.
You must be a member and be logged in to either append comments or rate this resource.



Not Rated


