Home | History | Annotate | Download | only in replicaisland
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.replica.replicaisland;
     18 
     19 import com.replica.replicaisland.ChannelSystem.Channel;
     20 import com.replica.replicaisland.GameObject.ActionType;
     21 
     22 public class NPCAnimationComponent extends GameComponent {
     23 
     24     // Animations
     25     public static final int IDLE = 0;
     26     public static final int WALK = 1;
     27     public static final int RUN_START = 2;
     28     public static final int RUN = 3;
     29     public static final int SHOOT = 4;
     30     public static final int JUMP_START = 5;
     31     public static final int JUMP_AIR = 6;
     32     public static final int TAKE_HIT = 7;
     33     public static final int SURPRISED = 8;
     34     public static final int DEATH = 9;
     35 
     36 
     37     protected static final float RUN_SPEED_THRESHOLD = 100.0f;
     38     protected static final float JUMP_SPEED_THRESHOLD = 25.0f;
     39     protected static final float FALL_SPEED_THRESHOLD = -25.0f;
     40     protected static final float FALL_TIME_THRESHOLD = 0.2f;
     41 
     42     private int mCurrentAnimation;
     43     private SpriteComponent mSprite;
     44     private ChannelSystem.Channel mChannel;
     45     private int mChannelTrigger;
     46     private boolean mFlying;
     47     private boolean mStopAtWalls;	// Controls whether or not the character will go back
     48     								// to idle when running into a wall
     49 
     50 
     51     public NPCAnimationComponent() {
     52         super();
     53         reset();
     54         setPhase(GameComponent.ComponentPhases.ANIMATION.ordinal());
     55     }
     56 
     57     @Override
     58     public void reset() {
     59         mCurrentAnimation = IDLE;
     60         mChannel = null;
     61         mSprite = null;
     62         mFlying = false;
     63         mStopAtWalls = true;
     64     }
     65 
     66     @Override
     67     public void update(float timeDelta, BaseObject parent) {
     68         if (mSprite != null) {
     69             GameObject parentObject = (GameObject)parent;
     70 
     71             final int oldAnimation = mCurrentAnimation;
     72             switch(mCurrentAnimation) {
     73                 case IDLE:
     74                     idle(parentObject);
     75                     break;
     76                 case WALK:
     77                     walk(parentObject);
     78                     break;
     79                 case RUN_START:
     80                     runStart(parentObject);
     81                     break;
     82                 case RUN:
     83                     run(parentObject);
     84                     break;
     85                 case SHOOT:
     86                     shoot(parentObject);
     87                     break;
     88                 case JUMP_START:
     89                     jumpStart(parentObject);
     90                     break;
     91                 case JUMP_AIR:
     92                     jumpAir(parentObject);
     93                     break;
     94                 case TAKE_HIT:
     95                 	takeHit(parentObject);
     96                 	break;
     97                 case SURPRISED:
     98                 	surprised(parentObject);
     99                 	break;
    100                 case DEATH:
    101                 	death(parentObject);
    102                 	break;
    103                default:
    104                     assert(false);
    105             }
    106 
    107             if (mChannel != null) {
    108             	if (mChannel.value != null
    109             			&& ((ChannelSystem.ChannelBooleanValue)mChannel.value).value) {
    110             		mCurrentAnimation = mChannelTrigger;
    111             	}
    112             }
    113 
    114             if (oldAnimation != mCurrentAnimation) {
    115                 mSprite.playAnimation(mCurrentAnimation);
    116             }
    117         }
    118     }
    119 
    120     protected boolean shouldFall(GameObject parentObject) {
    121         boolean result = false;
    122         TimeSystem time = sSystemRegistry.timeSystem;
    123         final float airTime = time.getGameTime() - parentObject.getLastTouchedFloorTime();
    124         if (!mFlying && !parentObject.touchingGround() && airTime > FALL_TIME_THRESHOLD) {
    125             final Vector2 velocity = parentObject.getVelocity();
    126             if (velocity.y < FALL_SPEED_THRESHOLD) {
    127                 result = true;
    128             }
    129         }
    130         return result;
    131     }
    132 
    133     protected boolean shouldJump(GameObject parentObject) {
    134         boolean result = false;
    135 
    136         if (!mFlying) {
    137 	        final Vector2 velocity = parentObject.getVelocity();
    138 	        if (velocity.y > JUMP_SPEED_THRESHOLD) {
    139 	            result = true;
    140 	        }
    141         }
    142         return result;
    143     }
    144 
    145     protected boolean shouldRun(GameObject parentObject) {
    146         boolean result = false;
    147         if (!mFlying && parentObject.touchingGround()) {
    148             final Vector2 velocity = parentObject.getVelocity();
    149             if (Math.abs(velocity.x) >= RUN_SPEED_THRESHOLD) {
    150                 result = true;
    151             }
    152         }
    153         return result;
    154     }
    155 
    156     protected boolean shouldMove(GameObject parentObject) {
    157         boolean result = true;
    158         final Vector2 velocity = parentObject.getVelocity();
    159 
    160         if (mStopAtWalls) {
    161 	        if ((velocity.x < 0.0f && parentObject.touchingLeftWall())
    162 	                || (velocity.x > 0.0f && parentObject.touchingRightWall())) {
    163 	            result = false;
    164 	        }
    165         }
    166         return result;
    167     }
    168 
    169     protected boolean shouldTakeHit(GameObject parentObject) {
    170     	boolean result = false;
    171     	if (parentObject.getCurrentAction() == ActionType.HIT_REACT
    172     			&& mSprite.findAnimation(TAKE_HIT) != null) {
    173     		result = true;
    174     	}
    175     	return result;
    176     }
    177 
    178     protected void gotoRunStart() {
    179         if (mSprite.findAnimation(RUN_START) != null) {
    180             mCurrentAnimation = RUN_START;
    181         } else {
    182             mCurrentAnimation = RUN;
    183         }
    184     }
    185 
    186     protected void gotoRun() {
    187         mCurrentAnimation = RUN;
    188     }
    189 
    190     protected void idle(GameObject parentObject) {
    191         final GameObject.ActionType currentAction = parentObject.getCurrentAction();
    192         if (currentAction == ActionType.MOVE) {
    193             final Vector2 velocity = parentObject.getVelocity();
    194             if (shouldFall(parentObject)) {
    195                 mCurrentAnimation = JUMP_AIR;
    196             } else if (shouldJump(parentObject)) {
    197                 mCurrentAnimation = JUMP_START;
    198                 parentObject.positionLocked = true;
    199             } else if (Math.abs(velocity.x) > 0.0f && shouldMove(parentObject)) {
    200                 if (shouldRun(parentObject)) {
    201                 	gotoRunStart();
    202                 	parentObject.positionLocked = true;
    203                 } else {
    204                     mCurrentAnimation = WALK;
    205                 }
    206             }
    207         } else if (currentAction == ActionType.ATTACK) {
    208             mCurrentAnimation = SHOOT;
    209         } else if (shouldTakeHit(parentObject)) {
    210         	mCurrentAnimation = TAKE_HIT;
    211         } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
    212         	mCurrentAnimation = DEATH;
    213         }
    214      }
    215 
    216     protected void walk(GameObject parentObject) {
    217         final GameObject.ActionType currentAction = parentObject.getCurrentAction();
    218         if (currentAction == ActionType.MOVE) {
    219             final Vector2 velocity = parentObject.getVelocity();
    220             if (shouldFall(parentObject)) {
    221                 mCurrentAnimation = JUMP_AIR;
    222             } else if (shouldJump(parentObject)) {
    223                 mCurrentAnimation = JUMP_START;
    224                 parentObject.positionLocked = true;
    225             } else if (Math.abs(velocity.x) > 0.0f) {
    226                 if (shouldRun(parentObject)) {
    227                     gotoRun();
    228                 }
    229                 if (velocity.x > 0.0f) {
    230                     parentObject.facingDirection.x = 1;
    231                 } else {
    232                     parentObject.facingDirection.x = -1;
    233                 }
    234             } else {
    235                 mCurrentAnimation = IDLE;
    236             }
    237         } else if (currentAction == ActionType.ATTACK) {
    238             mCurrentAnimation = SHOOT;
    239         } else if (shouldTakeHit(parentObject)) {
    240         	mCurrentAnimation = TAKE_HIT;
    241         } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
    242         	mCurrentAnimation = DEATH;
    243         }
    244     }
    245 
    246     protected void runStart(GameObject parentObject) {
    247     	parentObject.positionLocked = true;
    248         if (mSprite.animationFinished()) {
    249             mCurrentAnimation = RUN;
    250             parentObject.positionLocked = false;
    251         }
    252     }
    253     protected void run(GameObject parentObject) {
    254         final GameObject.ActionType currentAction = parentObject.getCurrentAction();
    255         if (currentAction == ActionType.MOVE) {
    256             final Vector2 velocity = parentObject.getVelocity();
    257             if (shouldFall(parentObject)) {
    258                 mCurrentAnimation = JUMP_AIR;
    259             } else if (shouldJump(parentObject)) {
    260                 parentObject.positionLocked = true;
    261                 mCurrentAnimation = JUMP_START;
    262             } else if (Math.abs(velocity.x) > 0.0f) {
    263                 if (!shouldRun(parentObject)) {
    264                     mCurrentAnimation = WALK;
    265                 }
    266 
    267                 if (velocity.x > 0.0f) {
    268                     parentObject.facingDirection.x = 1;
    269                 } else {
    270                     parentObject.facingDirection.x = -1;
    271                 }
    272             } else {
    273             	mCurrentAnimation = IDLE;
    274             }
    275         } else if (currentAction == ActionType.ATTACK) {
    276             mCurrentAnimation = SHOOT;
    277         } else if (shouldTakeHit(parentObject)) {
    278         	mCurrentAnimation = TAKE_HIT;
    279         } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
    280         	mCurrentAnimation = DEATH;
    281         }
    282     }
    283 
    284     protected void shoot(GameObject parentObject) {
    285         if (mSprite.animationFinished() || parentObject.getCurrentAction() != ActionType.ATTACK) {
    286             mCurrentAnimation = IDLE;
    287         } else if (shouldTakeHit(parentObject)) {
    288         	mCurrentAnimation = TAKE_HIT;
    289         } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
    290             	mCurrentAnimation = DEATH;
    291         } else {
    292             final Vector2 velocity = parentObject.getVelocity();
    293 
    294         	if (velocity.x > 0.0f) {
    295                 parentObject.facingDirection.x = 1;
    296             } else if (velocity.x < 0.0f) {
    297                 parentObject.facingDirection.x = -1;
    298             }
    299         }
    300     }
    301 
    302     protected void jumpStart(GameObject parentObject) {
    303         final Vector2 velocity = parentObject.getVelocity();
    304 
    305         if (velocity.x > 0.0f) {
    306             parentObject.facingDirection.x = 1;
    307         } else if (velocity.x < 0.0f) {
    308             parentObject.facingDirection.x = -1;
    309         }
    310         parentObject.positionLocked = true;
    311 
    312         if (mSprite.animationFinished()) {
    313             mCurrentAnimation = JUMP_AIR;
    314             parentObject.positionLocked = false;
    315         }
    316     }
    317 
    318     protected void jumpAir(GameObject parentObject) {
    319         final GameObject.ActionType currentAction = parentObject.getCurrentAction();
    320         if (currentAction == ActionType.MOVE) {
    321             final Vector2 velocity = parentObject.getVelocity();
    322 
    323             if (parentObject.touchingGround()) {
    324                 if (Math.abs(velocity.x) > 0.0f) {
    325                     if (shouldRun(parentObject)) {
    326                         mCurrentAnimation = RUN;
    327                     } else {
    328                         mCurrentAnimation = WALK;
    329                     }
    330                 } else {
    331                     mCurrentAnimation = IDLE;
    332                 }
    333             } else {
    334 
    335                 if (velocity.x > 0.0f) {
    336                     parentObject.facingDirection.x = 1;
    337                 } else if (velocity.x < 0.0f) {
    338                     parentObject.facingDirection.x = -1;
    339                 }
    340 
    341             }
    342         } else {
    343             mCurrentAnimation = IDLE;
    344         }
    345     }
    346 
    347     protected void takeHit(GameObject parentObject) {
    348     	if (mSprite.animationFinished()) {
    349     		if (parentObject.life > 0 && parentObject.getCurrentAction() != ActionType.DEATH) {
    350     			if (parentObject.getCurrentAction() != ActionType.HIT_REACT) {
    351     				mCurrentAnimation = IDLE;
    352     			}
    353 			} else {
    354     			mCurrentAnimation = DEATH;
    355     		}
    356     	}
    357     }
    358 
    359     protected void surprised(GameObject parentObject) {
    360     	if (mSprite.animationFinished()) {
    361     		mCurrentAnimation = IDLE;
    362     	}
    363     }
    364 
    365     protected void death(GameObject parentObject) {
    366     }
    367 
    368     public void setSprite(SpriteComponent sprite) {
    369         mSprite = sprite;
    370     }
    371 
    372 	public void setChannel(Channel channel) {
    373 		mChannel = channel;
    374 	}
    375 
    376 	public void setChannelTrigger(int animation) {
    377 		mChannelTrigger = animation;
    378 	}
    379 
    380 	public void setFlying(boolean flying) {
    381 		mFlying = flying;
    382 	}
    383 
    384 	public void setStopAtWalls(boolean stop) {
    385 		mStopAtWalls = stop;
    386 	}
    387 }
    388