How Animation Works - UQdeco2800/2022-studio-3 GitHub Wiki
Introduction
This is a guide on using the EntityDirectionComponent
and direction setting logic in PhysicsMovementComponent
to animate your character,
may that be animations for movement or attacks, the following animation directions can be achieved.
- North
- South
- East
- West
Entity Direction Component
This is a simple component attached to any entity that requires keeping track of which direction it's pointing in, it uses a simple enum
EntityDirection
to store the four compass direction; NORTH
, SOUTH
, EAST
, WEST
, DEFAULT
, where DEFAULT
is set upon initialising the component and changed to the appropriate direction in PhysicsMovementComponent
.
UML
How it works
- Add the animation when creating your entity as follows:
AnimationRenderComponent animator =
new AnimationRenderComponent(
ServiceLocator.getResourceService().getAsset("images/blue_joker.atlas", TextureAtlas.class));
animator.addAnimation(MOVE_EAST, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(MOVE_WEST, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(MOVE_SOUTH, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(MOVE_NORTH, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation("default", 1f, Animation.PlayMode.NORMAL);
animator.addAnimation(ATTACK_NORTH, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(ATTACK_SOUTH, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(ATTACK_EAST, 0.1f, Animation.PlayMode.LOOP);
animator.addAnimation(ATTACK_WEST, 0.1f, Animation.PlayMode.LOOP);
blueJoker
.addComponent(new CombatStatsComponent(config.troops, config.health, config.baseAttack,
config.baseDefence, config.landSpeed, config.range))
.addComponent(animator)
.addComponent(new EnemyAnimationController());
blueJoker .getComponent(AnimationRenderComponent.class).scaleEntity();
- The animation controller class must be written in the following manner, UML diagram of
EnemyAnimationController
is presented as an example of how an animation controller for movable units should be structured.
The create function must be populated as follows
@Override
public void create() {
super.create();
animator = this.entity.getComponent(AnimationRenderComponent.class);
entity.getEvents().addListener("goWest", this::animateWest);
entity.getEvents().addListener("goEast", this::animateEast);
entity.getEvents().addListener("goNorth", this::animateNorth);
entity.getEvents().addListener("goSouth", this::animateSouth);
entity.getEvents().addListener("default", this::defaultAnimation);
entity.getEvents().addListener("attackNorth", this::attackNorth);
entity.getEvents().addListener("attackSouth", this::attackSouth);
entity.getEvents().addListener("attackWest", this::attackWest);
entity.getEvents().addListener("attackEast", this::attackEast);
}
Example animation method
// Under EnemyAnimationController class
public void animateWest(){ animator.startAnimation("move-west"); }
The only mandatory animation events that need to be added are first five ("goWest"
- "default"
), as these are triggered in physics movement component for movement animations, the last four are specific to enemy units and can be replaced (or not) with events specific to your actions.
(Make sure that your movement events are labelled as goWest
, goEast
, goNorth
and goSouth
)
-
Once the
EntityDirectionComponent
is added to an entity and animation controller has been made, thePhysiscsMovementComponent
sets the direction if it has changed by triggering the following movement animation events upon setting a new direction:"goWest"
"goEast"
"goSouth"
"goNorth"
-
In addition we've made an attempt at implementing attack animation, this is done in
TouchAttackComponent
by checking for the direction the entity is in and triggering its respective attack animation.
// Excerpt from TouchAttackComponent
// isAtacking is a private boolean set to false by default
// Should be from line 70 onwards.
if (targetStats != null) {
targetStats.hit(combatStats);
if (targetStats.getHealth() > 0) {
if (!isAttacking) {
isAttacking = true;
switch (entityDirectionComponent.getEntityDirection()) {
case DEFAULT:
break;
case WEST:
entity.getEvents().trigger("attackWest");
break;
case EAST:
entity.getEvents().trigger("attackEast");
break;
case NORTH:
entity.getEvents().trigger("attackNorth");
break;
case SOUTH:
entity.getEvents().trigger("attackSouth");
break;
}
}
} else {
isAttacking = false;
// target.dispose();
}
}
A similar sequence can be done for worker components when they're mining or building something.
Additional Notes
- Make sure your
.atlas
files has an entry fordefault
or else this will cause runtime errors.