blob: f1fa36928cf54986a1329a7428e93b72bd6388ec [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.replica.replicaisland;
import com.replica.replicaisland.ChannelSystem.Channel;
import com.replica.replicaisland.GameObject.ActionType;
public class NPCAnimationComponent extends GameComponent {
// Animations
public static final int IDLE = 0;
public static final int WALK = 1;
public static final int RUN_START = 2;
public static final int RUN = 3;
public static final int SHOOT = 4;
public static final int JUMP_START = 5;
public static final int JUMP_AIR = 6;
public static final int TAKE_HIT = 7;
public static final int SURPRISED = 8;
public static final int DEATH = 9;
protected static final float RUN_SPEED_THRESHOLD = 100.0f;
protected static final float JUMP_SPEED_THRESHOLD = 25.0f;
protected static final float FALL_SPEED_THRESHOLD = -25.0f;
protected static final float FALL_TIME_THRESHOLD = 0.2f;
private int mCurrentAnimation;
private SpriteComponent mSprite;
private ChannelSystem.Channel mChannel;
private int mChannelTrigger;
private boolean mFlying;
private boolean mStopAtWalls; // Controls whether or not the character will go back
// to idle when running into a wall
public NPCAnimationComponent() {
super();
reset();
setPhase(GameComponent.ComponentPhases.ANIMATION.ordinal());
}
@Override
public void reset() {
mCurrentAnimation = IDLE;
mChannel = null;
mSprite = null;
mFlying = false;
mStopAtWalls = true;
}
@Override
public void update(float timeDelta, BaseObject parent) {
if (mSprite != null) {
GameObject parentObject = (GameObject)parent;
final int oldAnimation = mCurrentAnimation;
switch(mCurrentAnimation) {
case IDLE:
idle(parentObject);
break;
case WALK:
walk(parentObject);
break;
case RUN_START:
runStart(parentObject);
break;
case RUN:
run(parentObject);
break;
case SHOOT:
shoot(parentObject);
break;
case JUMP_START:
jumpStart(parentObject);
break;
case JUMP_AIR:
jumpAir(parentObject);
break;
case TAKE_HIT:
takeHit(parentObject);
break;
case SURPRISED:
surprised(parentObject);
break;
case DEATH:
death(parentObject);
break;
default:
assert(false);
}
if (mChannel != null) {
if (mChannel.value != null
&& ((ChannelSystem.ChannelBooleanValue)mChannel.value).value) {
mCurrentAnimation = mChannelTrigger;
}
}
if (oldAnimation != mCurrentAnimation) {
mSprite.playAnimation(mCurrentAnimation);
}
}
}
protected boolean shouldFall(GameObject parentObject) {
boolean result = false;
TimeSystem time = sSystemRegistry.timeSystem;
final float airTime = time.getGameTime() - parentObject.getLastTouchedFloorTime();
if (!mFlying && !parentObject.touchingGround() && airTime > FALL_TIME_THRESHOLD) {
final Vector2 velocity = parentObject.getVelocity();
if (velocity.y < FALL_SPEED_THRESHOLD) {
result = true;
}
}
return result;
}
protected boolean shouldJump(GameObject parentObject) {
boolean result = false;
if (!mFlying) {
final Vector2 velocity = parentObject.getVelocity();
if (velocity.y > JUMP_SPEED_THRESHOLD) {
result = true;
}
}
return result;
}
protected boolean shouldRun(GameObject parentObject) {
boolean result = false;
if (!mFlying && parentObject.touchingGround()) {
final Vector2 velocity = parentObject.getVelocity();
if (Math.abs(velocity.x) >= RUN_SPEED_THRESHOLD) {
result = true;
}
}
return result;
}
protected boolean shouldMove(GameObject parentObject) {
boolean result = true;
final Vector2 velocity = parentObject.getVelocity();
if (mStopAtWalls) {
if ((velocity.x < 0.0f && parentObject.touchingLeftWall())
|| (velocity.x > 0.0f && parentObject.touchingRightWall())) {
result = false;
}
}
return result;
}
protected boolean shouldTakeHit(GameObject parentObject) {
boolean result = false;
if (parentObject.getCurrentAction() == ActionType.HIT_REACT
&& mSprite.findAnimation(TAKE_HIT) != null) {
result = true;
}
return result;
}
protected void gotoRunStart() {
if (mSprite.findAnimation(RUN_START) != null) {
mCurrentAnimation = RUN_START;
} else {
mCurrentAnimation = RUN;
}
}
protected void gotoRun() {
mCurrentAnimation = RUN;
}
protected void idle(GameObject parentObject) {
final GameObject.ActionType currentAction = parentObject.getCurrentAction();
if (currentAction == ActionType.MOVE) {
final Vector2 velocity = parentObject.getVelocity();
if (shouldFall(parentObject)) {
mCurrentAnimation = JUMP_AIR;
} else if (shouldJump(parentObject)) {
mCurrentAnimation = JUMP_START;
parentObject.positionLocked = true;
} else if (Math.abs(velocity.x) > 0.0f && shouldMove(parentObject)) {
if (shouldRun(parentObject)) {
gotoRunStart();
parentObject.positionLocked = true;
} else {
mCurrentAnimation = WALK;
}
}
} else if (currentAction == ActionType.ATTACK) {
mCurrentAnimation = SHOOT;
} else if (shouldTakeHit(parentObject)) {
mCurrentAnimation = TAKE_HIT;
} else if (parentObject.getCurrentAction() == ActionType.DEATH) {
mCurrentAnimation = DEATH;
}
}
protected void walk(GameObject parentObject) {
final GameObject.ActionType currentAction = parentObject.getCurrentAction();
if (currentAction == ActionType.MOVE) {
final Vector2 velocity = parentObject.getVelocity();
if (shouldFall(parentObject)) {
mCurrentAnimation = JUMP_AIR;
} else if (shouldJump(parentObject)) {
mCurrentAnimation = JUMP_START;
parentObject.positionLocked = true;
} else if (Math.abs(velocity.x) > 0.0f) {
if (shouldRun(parentObject)) {
gotoRun();
}
if (velocity.x > 0.0f) {
parentObject.facingDirection.x = 1;
} else {
parentObject.facingDirection.x = -1;
}
} else {
mCurrentAnimation = IDLE;
}
} else if (currentAction == ActionType.ATTACK) {
mCurrentAnimation = SHOOT;
} else if (shouldTakeHit(parentObject)) {
mCurrentAnimation = TAKE_HIT;
} else if (parentObject.getCurrentAction() == ActionType.DEATH) {
mCurrentAnimation = DEATH;
}
}
protected void runStart(GameObject parentObject) {
parentObject.positionLocked = true;
if (mSprite.animationFinished()) {
mCurrentAnimation = RUN;
parentObject.positionLocked = false;
}
}
protected void run(GameObject parentObject) {
final GameObject.ActionType currentAction = parentObject.getCurrentAction();
if (currentAction == ActionType.MOVE) {
final Vector2 velocity = parentObject.getVelocity();
if (shouldFall(parentObject)) {
mCurrentAnimation = JUMP_AIR;
} else if (shouldJump(parentObject)) {
parentObject.positionLocked = true;
mCurrentAnimation = JUMP_START;
} else if (Math.abs(velocity.x) > 0.0f) {
if (!shouldRun(parentObject)) {
mCurrentAnimation = WALK;
}
if (velocity.x > 0.0f) {
parentObject.facingDirection.x = 1;
} else {
parentObject.facingDirection.x = -1;
}
} else {
mCurrentAnimation = IDLE;
}
} else if (currentAction == ActionType.ATTACK) {
mCurrentAnimation = SHOOT;
} else if (shouldTakeHit(parentObject)) {
mCurrentAnimation = TAKE_HIT;
} else if (parentObject.getCurrentAction() == ActionType.DEATH) {
mCurrentAnimation = DEATH;
}
}
protected void shoot(GameObject parentObject) {
if (mSprite.animationFinished() || parentObject.getCurrentAction() != ActionType.ATTACK) {
mCurrentAnimation = IDLE;
} else if (shouldTakeHit(parentObject)) {
mCurrentAnimation = TAKE_HIT;
} else if (parentObject.getCurrentAction() == ActionType.DEATH) {
mCurrentAnimation = DEATH;
} else {
final Vector2 velocity = parentObject.getVelocity();
if (velocity.x > 0.0f) {
parentObject.facingDirection.x = 1;
} else if (velocity.x < 0.0f) {
parentObject.facingDirection.x = -1;
}
}
}
protected void jumpStart(GameObject parentObject) {
final Vector2 velocity = parentObject.getVelocity();
if (velocity.x > 0.0f) {
parentObject.facingDirection.x = 1;
} else if (velocity.x < 0.0f) {
parentObject.facingDirection.x = -1;
}
parentObject.positionLocked = true;
if (mSprite.animationFinished()) {
mCurrentAnimation = JUMP_AIR;
parentObject.positionLocked = false;
}
}
protected void jumpAir(GameObject parentObject) {
final GameObject.ActionType currentAction = parentObject.getCurrentAction();
if (currentAction == ActionType.MOVE) {
final Vector2 velocity = parentObject.getVelocity();
if (parentObject.touchingGround()) {
if (Math.abs(velocity.x) > 0.0f) {
if (shouldRun(parentObject)) {
mCurrentAnimation = RUN;
} else {
mCurrentAnimation = WALK;
}
} else {
mCurrentAnimation = IDLE;
}
} else {
if (velocity.x > 0.0f) {
parentObject.facingDirection.x = 1;
} else if (velocity.x < 0.0f) {
parentObject.facingDirection.x = -1;
}
}
} else {
mCurrentAnimation = IDLE;
}
}
protected void takeHit(GameObject parentObject) {
if (mSprite.animationFinished()) {
if (parentObject.life > 0 && parentObject.getCurrentAction() != ActionType.DEATH) {
if (parentObject.getCurrentAction() != ActionType.HIT_REACT) {
mCurrentAnimation = IDLE;
}
} else {
mCurrentAnimation = DEATH;
}
}
}
protected void surprised(GameObject parentObject) {
if (mSprite.animationFinished()) {
mCurrentAnimation = IDLE;
}
}
protected void death(GameObject parentObject) {
}
public void setSprite(SpriteComponent sprite) {
mSprite = sprite;
}
public void setChannel(Channel channel) {
mChannel = channel;
}
public void setChannelTrigger(int animation) {
mChannelTrigger = animation;
}
public void setFlying(boolean flying) {
mFlying = flying;
}
public void setStopAtWalls(boolean stop) {
mStopAtWalls = stop;
}
}