-
Notifications
You must be signed in to change notification settings - Fork 1
Player interaction Sprint3
Use if else to switch one animation to another. Check the running is on or not. In case one animation is stopped before another start.
- Animator5 is default animation - running.
- animator1-6 is Attack, touch, buff, debuff and collecting coins.
- This method runs every frame. So the first part to make sure the player is keep running.
- The second part of the if statment to test if other animation is working or not. If attack starts,then running should stop until attack finished.
- When other animation finished, restart the running animation.
public void update() {
if(animator5.getCurrentAnimation() == null) {
animator5.startAnimation("run");
}
if(animator.getCurrentAnimation() != null || animator2.getCurrentAnimation() != null|| animator3.getCurrentAnimation() != null || animator4.getCurrentAnimation() != null || animator6.getCurrentAnimation() != null){
animator5.stopAnimation();
}
if (animator2.isFinished() || animator3.isFinished() || animator4.isFinished() || animator6.isFinished()){
animator2.stopAnimation();
animator3.stopAnimation();
animator4.stopAnimation();
animator6.stopAnimation();
animator5.startAnimation("run");
}
if (moving) {
updateSpeed();
}
}
(Due to the bug given by team1, the death animation wont show correctly in the game. But the animation itself is working correctly by using other way to trigger.
if(attacker.getHealth() == 0){
AnimationRenderComponent7 animator7 =
attacker.getEntity().getComponent(AnimationRenderComponent7.class);
animator7.startAnimation("death");
}
The corresponding animation effect is triggered by determining the type of collision object
- hit buff will trigger the positive effect
- hit debuff will trigger the negative effect
- hit coins will shows the player collecting a coin
- Else show the hurt from enemy
Entity target = ((BodyUserData) other.getBody().getUserData()).entity;
CombatStatsComponent targetStats = target.getComponent(CombatStatsComponent.class);
if (targetStats != null) {
if(targetStats.getEntity().getType() == Entity.Type.BUFF){
targetStats.hitBuff(combatStats);
}
else if(targetStats.getEntity().getType() == Entity.Type.DEBUFF){
targetStats.hitDeBuff(combatStats);
}
else if(targetStats.getEntity().getType() == Entity.Type.COLLECTABLES){
targetStats.hitCoins(combatStats);
}
else{
targetStats.hit(combatStats);
}
}
public void hitCoins(CombatStatsComponent attacker) {
try {
if (ServiceLocator.getTimeSource().getTimeSince(invincibleStart) < 1000L) {
return;
}
if (attacker.getEntity().getType() == Entity.Type.PLAYER) {
logger.error("attacker--{}", attacker.getEntity().getType(),attacker.getEntity());
AnimationRenderComponent6 animator =
attacker.getEntity().getComponent(AnimationRenderComponent6.class);
animator.startAnimation("coin");
Sound coinSound = ServiceLocator.getResourceService().getAsset(
"sounds/coin.ogg", Sound.class);
coinSound.play();
logger.error("--end--attacker--{}",attacker.getEntity().getType());
}
} catch (NullPointerException e) {
int newHealth = getHealth() - attacker.getBaseAttack();
setHealth(newHealth);
}
}
The diagram shows the structure of player interaction related classes. It also shows how the playerFactory interact with different components including PlayerActions, CombatStatsComponent, TouchAttackComponent in the game. .
.
.
.
.
Test whether the judgment of attack distance is valid, and whether the enemy will be disposed.
package com.deco2800.game.components.player;
import com.badlogic.gdx.utils.Array;
import com.deco2800.game.entities.Entity;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class PlayerActionsTest {
private PlayerActions playerActions;
private static Entity entity = new Entity();
private Entity entity1 = new Entity(Entity.Type.GHOST);
private Entity entity2 = new Entity(Entity.Type.GHOSTKING);
private Entity entity3 = new Entity(Entity.Type.OBSTACLE);
private Entity entity4 = new Entity(Entity.Type.BUFF);
private Array<Entity> entities1 = new Array<>(1);
private Array<Entity> entities2 = new Array<>(1);
private Array<Entity> entities3 = new Array<>(1);
private Array<Entity> entities4 = new Array<>(1);
@Test
public void findNearestTargetsTest1() {
float minDstEnemy = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity1.setPosition(1, 0);
entities1.add(entity1);
for (Entity en : entities1) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstEnemy > dst) {
entityFind = en;
}
}
assertTrue(minDstEnemy > dst);
assertEquals("GHOST", entityFind.getType().toString());
}
@Test
public void findNearestTargetsTest2() {
float minDstEnemy = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity1.setPosition(2, 0);
entities1.add(entity1);
for (Entity en : entities1) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstEnemy > dst) {
entityFind = en;
}
}
assertFalse(minDstEnemy > dst);
assertNull(entityFind.getType());
}
@Test
public void findNearestTargetsTest3() {
float minDstEnemy = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity2.setPosition(1, 0);
entities2.add(entity2);
for (Entity en : entities2) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstEnemy > dst) {
entityFind = en;
}
}
assertTrue(minDstEnemy > dst);
assertEquals("GHOSTKING", entityFind.getType().toString());
}
@Test
public void findNearestTargetsTest4() {
float minDstEnemy = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity2.setPosition(8, 0);
entities2.add(entity2);
for (Entity en : entities2) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstEnemy > dst) {
entityFind = en;
}
}
assertFalse(minDstEnemy > dst);
assertNull(entityFind.getType());
}
@Test
public void findNearestTargetsTest5() {
float minDstObstacle = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity3.setPosition(1, 0);
entities3.add(entity3);
for (Entity en : entities3) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstObstacle > dst) {
entityFind = en;
}
}
assertTrue(minDstObstacle > dst);
assertEquals("OBSTACLE", entityFind.getType().toString());
}
@Test
public void findNearestTargetsTest6() {
float minDstObstacle = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity3.setPosition(5, 0);
entities3.add(entity3);
for (Entity en : entities3) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstObstacle > dst) {
entityFind = en;
}
}
assertFalse(minDstObstacle > dst);
assertNull(entityFind.getType());
}
@Test
public void findNearestTargetsTest7() {
float minDstObstacle = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity4.setPosition(1, 0);
entities4.add(entity4);
for (Entity en : entities4) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstObstacle > dst) {
entityFind = en;
}
}
assertTrue(minDstObstacle > dst);
assertEquals("BUFF", entityFind.getType().toString());
}
@Test
public void findNearestTargetsTest8() {
float minDstObstacle = 1.8f;
float dst = 0;
Entity entityFind = new Entity();
entity.setPosition(0, 0);
entity4.setPosition(4, 0);
entities4.add(entity4);
for (Entity en : entities4) {
dst = entity.getPosition().dst(en.getPosition());
if (minDstObstacle > dst) {
entityFind = en;
}
}
assertFalse(minDstObstacle > dst);
assertNull(entityFind.getType());
}
}
Our original plan was to merge all animation Atlas into one, which is easier to control different animations that we want to use on the player. But due to some technical problem (the software does not support more than 20 pictures in one atlas, while we have more than 40 pictures), we have to change the plan to find another way to control those animations. After many attempts, we successfully use judgment sentences to perfectly control the switching of different animation (Refer to Animation controller part in Wiki). So, the plan was changed to use animationStart and animationStop to control all player interactions.
In addition, all the animations are able to work correctly, but because of the bugs generated by team 1, when the player touches some obstacles, the game will quit automatically. Therefore, some of our animations like touch and death cannot be shown in the game because the auto quit will happen before the animation is being played. We are planning to help team1 fix this bug in the next sprint.