Android Open Source - Stickman Character






From Project

Back to project page Stickman.

License

The source code is released under:

Apache License

If you think the Android project Stickman listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.wireframe.stickman;
/*www.j  a  va 2s  .c  o m*/
import java.util.List;
import java.util.Random;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public abstract class Character extends GameObject implements Health{
  public static final int TEAM_NEUTRAL = 0;
  public static final int TEAM_BLUE = 1;
  public static final int TEAM_RED = 2;
  
  public static final int CHARACTER_MAX_HEALTH = 100;
  public static final int CHARACTER_FADE_TIME = 2; // Time before dissappering
  public static final int CHARACTER_ATTACKDAMAGE_MAX = 15;
  public static final int CHARACTER_ATTACKDAMAGE_BASE = 1;
  public static final int CHARACTER_CRITICALCHANCE = 10; // 5/100
  public static final int CHARACTER_CRITICALINCREASE = 2; // Amount to increase by when critical hit is applied
  

  public static final int col = 3;
  public static final int row = 8;
  private boolean animating = true;
  private Animation animation;
  private Texture characterTexture;
  private TextureRegion[] frames;
  private TextureRegion currentImage;

  private float stateTime;
  private float fadeTime;
  

  
  private float gravityStrength = 0.20f;
  private float animationSpeed = 0.125f;
  private float walkSpeed = 3;
  private float climbSpeed = 3;
  private float jumpSpeed = 6;

  private Vector2 velocity = new Vector2(0,0);
  private Ladder ladder;
  
  private boolean movingUp = false;
  private boolean movingLeft = false;
  private boolean movingRight = false;
  private boolean movingDown = false;
  private boolean attacking = false;
  private boolean facingRight = true;
  
  private int teamNumber = TEAM_NEUTRAL;
  private Character targetToAttack;
  
  // Attacking
  protected Random random = new Random();
  private int criticalIncrease = CHARACTER_CRITICALINCREASE;
  private int criticalChance = CHARACTER_CRITICALCHANCE;
  private int maxAttackDamage = CHARACTER_ATTACKDAMAGE_MAX;
  private int baseAttackDamage = CHARACTER_ATTACKDAMAGE_BASE;
  private float lastAttack = 0;
  private float attackSpeed = 0.25f;
  private float attackRange = 30;
  
  // HEAlTH
  private int maxHealth = CHARACTER_MAX_HEALTH;
  private int health = maxHealth;

  public Character(String type, int x, int y, int z, int w, int h) {
    this(type, new Vector3(x,y,z), new Vector2(w,h));
  }

  public Character(String type, Vector3 position, Vector2 size) {
    super(position, size);
    initialize(type);
  }
  
  public void dispose(){
    //characterTexture.dispose();
    for(TextureRegion t : frames){
      //wWWt.getTexture().dispose();
    }
  }
  
  private void initialize(String type){    
    this.setTeamNumber(type);
    characterTexture = StickmanResources.getImage(type + "_animations.png");
    TextureRegion[][] tmp = TextureRegion.split(characterTexture, characterTexture.getWidth()/col, characterTexture.getHeight()/row);
    frames = new TextureRegion[col*row];
    
    int index = 0;
    for (int i = 0; i < row; i++) {
      for (int j = 0; j < col; j++) {
        frames[index] = tmp[i][j];  
        frames[index++].flip(false, true);
      }
    }

    stateTime = 0f;
    animation = new Animation(animationSpeed, frames);
    currentImage = animation.getKeyFrame(6);
  }

  public void update(){
    stateTime += Gdx.graphics.getDeltaTime();
    
    // Are we did?
    if( !isAlive() ){
      fadeTime += Gdx.graphics.getDeltaTime();
      if( fadeTime > CHARACTER_FADE_TIME ){
        World.removeCharacter(this);
      }
      animate();
      return;
    }
    
    
    // Check if we have a ladder
    if( ladder == null && ( movingUp || movingDown ) ){
      //if( World.getPlayer() == this )  System.out.println("==============YUP");
      
      Rectangle ladderBounds = getBounds();
      ladderBounds.setY(movingUp ? ladderBounds.y+1 : ladderBounds.y-1);
      
      List<Ladder> obs = World.getLadders();
      for(Ladder ladder : obs){
        if( ladder.getBounds().overlaps(ladderBounds) ){
          
          // Found a ladder to grab onto
          attachToLadder(ladder);
          break;
        }
      }
    }
    else if( ladder != null ){
      // Are we still on the ladder?
      if( !ladder.getBounds().overlaps(getBounds()) ){
        ladder = null;
      }
    }
    
    
    // Not on a ladder
    if( ladder == null ){
      
      // GRAVITY
      velocity.y += gravityStrength;
    }
    
    
    if( attacking ){
      if( lastAttack != 0f ){
        lastAttack += Gdx.graphics.getDeltaTime();
        if( lastAttack > attackSpeed ){
          attacking = false;  
          lastAttack = 0;
        }
      }
      else{
        // Perform attack
        performAttack();
      }
    }
    
    
    // Move up/down
    if( ladder != null ){
      if(  velocity.y == 0 ){
        if( movingUp )velocity.y -= climbSpeed;
        if( movingDown )velocity.y += climbSpeed;
      }
      else{
        if( velocity.y < 0 && !movingUp )velocity.y += climbSpeed;
        if( velocity.y > 0 && !movingDown )velocity.y -= climbSpeed;
      }
    }
    
    
    
    // Move left/right
    if( velocity.x != 0 ){
      if( velocity.x < 0 && movingLeft == false ){
        if( ladder == null ){
          velocity.x += walkSpeed;
        }
      }
      else if( velocity.x > 0 && movingRight == false ){
        if( ladder == null ){
          velocity.x -= walkSpeed;
        }
      }
    }
    else if( ladder == null ){
      if( movingLeft ){
        velocity.x -= walkSpeed;
      }
      if( movingRight ){
        velocity.x += walkSpeed;
      }
    }
    
    // Move Character
    moveCharacter();
    
    // Animate character
    animate();
  }
  
  public void attachToLadder(Ladder ladder){
    this.ladder = ladder;
    velocity.set(0,0);
    
    float x = ladder.getX() + (ladder.getWidth()/2) - (getWidth()/2);
    moveTo(x,getY());
  }
  
  public void performAttack() {
    lastAttack = Gdx.graphics.getDeltaTime();
    if( targetToAttack != null ){
      int damage = random.nextInt(maxAttackDamage - baseAttackDamage) + baseAttackDamage;
      boolean criticalHit = random.nextInt(100) < getCriticalChance(); 
      damage *= criticalHit ? getCriticalIncrease() : 1;          
      targetToAttack.takeDamage(damage, criticalHit, this);
    }
  }

  private void animate(){
    if( !animating ){ return; }
    
    if( stateTime /animationSpeed >= col ){
      stateTime = 0;
    }
    
    if( !isAlive() ){
      
      // Death
      int index = facingRight ? 18 : 21;
      currentImage = animation.getKeyFrame(index*animationSpeed + stateTime);
      if( currentImage == animation.getKeyFrames()[index+2]){
        animating = false;
      }
    }
    else if( movingUp && ladder != null ){
      currentImage = animation.getKeyFrame(6*animationSpeed + stateTime);
    }
    else if( attacking ){
      int index = facingRight ? 12 : 15;
      currentImage = animation.getKeyFrame(index*animationSpeed + stateTime);      
    }
    else if( movingLeft ){      
      currentImage = animation.getKeyFrame(3*animationSpeed + stateTime);
    }
    else if( movingDown && ladder != null  ){
      currentImage = animation.getKeyFrame(6*animationSpeed + stateTime);
    }
    else if( movingRight ){
      currentImage = animation.getKeyFrame(stateTime);
    }
    else if( velocity.y > 0 ){
      // Falling
      currentImage = animation.getKeyFrame(9*animationSpeed + stateTime);
    }
    else{
      // IDLE
      currentImage = animation.getKeyFrame(6*animationSpeed + stateTime);
    }
    
  }
  
  private void moveCharacter(){
    
    // Move by Y
    moveBy(0,velocity.y);
  
    // Check for collision
    List<Tile> overLappingObjects = World.getTilesInArea(getBounds());
    if( !overLappingObjects.isEmpty() ){
      
      // Check if the object we are colliding with is colliding with the ladder
      boolean collided = true;
      if( ladder != null ){
        collided = false;
        for(Tile tile : overLappingObjects){
          if( !tile.getBounds().overlaps(ladder.getBounds()) ){
            collided = true;
          }
        }
      }
      
      // Double check collision
      if( collided ){
        //if( World.getPlayer() == this )  System.out.println("COLLIDED");
        if( velocity.y > 0 && ladder != null ) ladder = null;
        moveBy(0,-velocity.y);
        velocity.y = 0;
        
      }
    }

    // Move BY X
    moveBy(velocity.x,0);
  
    // Check for collision
    overLappingObjects = World.getTilesInArea(getBounds());
    if( !overLappingObjects.isEmpty() ){
      moveBy(-velocity.x,0);
      velocity.x = 0;
    }
  }
  
  protected boolean canAttackTarget(GameObject target) {
    
    // See if they are alive
    if( target instanceof Health && !((Health)target).isAlive() ){
      return false;
    }
    
    // Must be on the same Y
    if( Math.abs((int)target.getY() - (int)getY()) > 10){
      return false;
    }
    
    // Must be within attacking range
    if( (int)target.getX() < (int)getX() ){
      // Enemy to the left
      
      // Not facing the enemy that is on the left
      if( facingRight() ){
        //System.out.println("NOT Facing correct direction");
        return false; 
      }
      
      // Within attacking range
      if( Vector2.len(target.getX() - getX(), 1) > getAttackRange() ){
        //System.out.println(Vector2.len(target.getX() - getX(), 1));
        return false;
      }
    }
    else{
      // Enemy to the right
      
      // Not facing the enemy that is on the right
      if( !facingRight() ){
        //System.out.println("NOT Facing correct direction");
        return false; 
      }
      
      // Within attacking range
      if( (int)target.getX() > (int)(getX()+getAttackRange()) ){
        //System.out.println(Vector2.len(target.getX() - getX(), 1));
        return false;
      }
    }
    
    return true;
  }
  
  @Override
  public void draw(SpriteBatch batch){
    batch.draw(currentImage, getX(), getY(), getWidth(), getHeight());
  }

  @Override
  public void takeDamage(int damage, boolean isACriticalHit, Character attacker) {
    int oldHealth = health;
    oldHealth = Math.max(0, Math.min(getMaxHealth(), health - damage));

    int difference = Math.abs(health - oldHealth);
    health = oldHealth;
    
    // Floating Text // TODO
    FloatingText text = new FloatingText(String.valueOf(difference), getX(), getY(), isACriticalHit ? Color.PURPLE : Color.RED);
    text.moveBy(0, -text.getHeight());
    World.addObject(text);
    
    if( !isAlive() ){
      stateTime = 0f;
    }
  }

  @Override
  public void heal(int health) {
    takeDamage(-health, false, null);
  }

  @Override
  public boolean isAlive() {
    return health > 0;
  }

  @Override
  public int getMaxHealth() {
    return maxHealth;
  }

  @Override
  public int getHealth() {
    return health;
  }
  
  @Override
  public void setMaxHealth(int max){
    maxHealth = max;
  }
  
  @Override
  public void setHealth(int health){
    this.health = health;
  }
  
  /**
   * @return the animation
   */
  public Animation getAnimation() {
    return animation;
  }

  /**
   * @param animation the animation to set
   */
  public void setAnimation(Animation animation) {
    this.animation = animation;
  }

  /**
   * @return the frames
   */
  public TextureRegion[] getFrames() {
    return frames;
  }

  /**
   * @param frames the frames to set
   */
  public void setFrames(TextureRegion[] frames) {
    this.frames = frames;
  }

  /**
   * @return the currentImage
   */
  public TextureRegion getcurrentImage() {
    return currentImage;
  }
  

  /**
   * @param currentImage the currentImage to set
   */
  public void setcurrentImage(TextureRegion currentImage) {
    this.currentImage = currentImage;
  }

  /**
   * @return the stateTime
   */
  public float getStateTime() {
    return stateTime;
  }
  
  /**
   * @param stateTime the stateTime to set
   */
  public void setStateTime(float stateTime) {
    this.stateTime = stateTime;
  }
  
  public boolean movingLeft() {
    return movingLeft;
  }

  public boolean movingRight() {
    return movingRight;
  }

  public void moveUp() {
    movingUp = true;
  }
  
  public void stopMoveingUp() {
    movingUp = false;
  }

  public void moveLeft() {
    movingLeft = true;
    
    if( movingRight ) stopMoveingRight();
    facingRight = false;    
  }
  
  public void stopMoveingLeft() {
    movingLeft = false;
  }

  public void moveRight() {
    movingRight = true;
    
    if( movingLeft ) stopMoveingLeft();
    facingRight = true;
  }
  
  public void stopMoveingRight() {
    movingRight = false;
  }

  public void moveDown() {
    movingDown = true;
  }
  
  public void stopMoveingDown() {
    movingDown = false;
  }
  
  public boolean moving() {
    return movingLeft() || movingRight();
  }
  
  public boolean movingUp() {
    return movingUp;
  }

  public boolean movingDown() {
    return movingDown;
  }
  
  public void stopMoving() {
    if( movingRight() ) stopMoveingRight();
    if( movingLeft() ) stopMoveingLeft();
  }

  public void jump() {
    if( velocity.y == 0 ){
      velocity.y -= jumpSpeed;
      if ( ladder != null  ) ladder = null;
    }
  }

  public void attack() {
    attacking = true;
    //if( World.getPlayer() == this )  System.out.println("attacking");
    
  }
  
  public void stopAttacking() {
    attacking = false;
  }
  
  public boolean facingRight() {
    return facingRight;
  }
  
  public void flipFacingDirection(){
    facingRight = !facingRight;
  }
  
  public boolean isAttacking(){
    return attacking;
  }

  public float getAttackRange() {
    return attackRange;
  }

  public void setAttackRange(float attackRange) {
    this.attackRange = attackRange;
  }

  public float getAttackSpeed() {
    return attackSpeed;
  }

  public void setAttackSpeed(float attackSpeed) {
    this.attackSpeed = attackSpeed;
  }

  public Character getTargetToAttack() {
    return targetToAttack;
  }

  public void setTargetToAttack(Character targetToAttack) {
    this.targetToAttack = targetToAttack;
  }

  public int getTeamNumber() {
    return teamNumber;
  }

  public void setTeamNumber(int teamNumber) {
    this.teamNumber = teamNumber;
  }

  private void setTeamNumber(String type) {
    if( type.equalsIgnoreCase("player") ) this.setTeamNumber(TEAM_BLUE);
    else if( type.equalsIgnoreCase("friendly") ) this.setTeamNumber(TEAM_BLUE);
    else if( type.equalsIgnoreCase("enemy") ) this.setTeamNumber(TEAM_RED);    
  }

  public float getFadeTime() {
    return fadeTime;
  }

  public void setFadeTime(float fadeTime) {
    this.fadeTime = fadeTime;
  }

  public int getMaxAttackDamage() {
    return maxAttackDamage;
  }

  public void setMaxAttackDamage(int maxAttackDamage) {
    this.maxAttackDamage = maxAttackDamage;
  }

  public int getBaseAttackDamage() {
    return baseAttackDamage;
  }

  public void setBaseAttackDamage(int baseAttackDamage) {
    this.baseAttackDamage = baseAttackDamage;
  }

  public int getCriticalChance() {
    return criticalChance;
  }

  public void setCriticalChance(int criticalChance) {
    this.criticalChance = criticalChance;
  }

  public int getCriticalIncrease() {
    return criticalIncrease;
  }

  public void setCriticalIncrease(int criticalIncrease) {
    this.criticalIncrease = criticalIncrease;
  }
}




Java Source Code List

com.wireframe.stickman.AICharacter.java
com.wireframe.stickman.AndroidGUI.java
com.wireframe.stickman.Brick.java
com.wireframe.stickman.Character.java
com.wireframe.stickman.Door.java
com.wireframe.stickman.Enemy.java
com.wireframe.stickman.FloatingText.java
com.wireframe.stickman.Friendly.java
com.wireframe.stickman.GUI.java
com.wireframe.stickman.GameObject.java
com.wireframe.stickman.GameRules.java
com.wireframe.stickman.Health.java
com.wireframe.stickman.Interactable.java
com.wireframe.stickman.Ladder.java
com.wireframe.stickman.Player.java
com.wireframe.stickman.Resources.java
com.wireframe.stickman.SmallButton.java
com.wireframe.stickman.Spawner.java
com.wireframe.stickman.Spikes.java
com.wireframe.stickman.StickmanGame.java
com.wireframe.stickman.StickmanResources.java
com.wireframe.stickman.Tile.java
com.wireframe.stickman.Toggleable.java
com.wireframe.stickman.WaterShore.java
com.wireframe.stickman.Water.java
com.wireframe.stickman.World.java
com.wireframe.stickman.android.AndroidLauncher.java
com.wireframe.stickman.desktop.DesktopLauncher.java
com.wireframe.stickman.desktop.EditorLauncher.java
com.wireframe.stickman.editor.MapMaker.java
com.wireframe.stickman.editor.MappingPanel.java
com.wireframe.stickman.editor.PlacedTile.java
com.wireframe.stickman.editor.SelectionPanel.java
com.wireframe.stickman.editor.SelectionTile.java
com.wireframe.stickman.editor.SizingPanel.java