Android Open Source - Infinite Player Controller






From Project

Back to project page Infinite.

License

The source code is released under:

GNU General Public License

If you think the Android project Infinite 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.detel.infinite.controllers;
/* ww  w  .  j a  v a 2  s .  co m*/
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pool;
import com.detel.infinite.models.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Derick on 2/22/14.
 */
public class PlayerController {

    //player and world that the calculations will be performed for
    private Player player;
    private World world;

    //Creation and storage of keys that the player uses to interact with the world
    public enum Keys{
        Left,Right,Jump,Attack
    }

    static Map<Keys,Boolean> keys = new HashMap<PlayerController.Keys, Boolean>();
    static{
        keys.put(Keys.Left,false);
        keys.put(Keys.Right,false);
        keys.put(Keys.Jump,false);
        keys.put(Keys.Attack,false);
    }

    //Pools for memory saving (not sure if this works?)
    private Pool<Rectangle> rectPool = new Pool<Rectangle>() {
        @Override
        protected Rectangle newObject() {
            return new Rectangle();
        }
    };

    //this array holds the blocks that the player can collide with
    private Array<Block> collidableBlocks = new Array<>();

    //These are all the values the game uses to calculate acceleration, immunity, and jump length
    //multiplying by two gives you real-world values in m/s
    private static final float ACCELERATION = 10f;
    private static float GRAVITY = -18f;
    private static float MAX_GRAVITY = -25f;
    private static final float MAX_VEL = 7f;

    private static final long MAX_JUMP_TIME = 300L;
    private static float MAX_JUMP_VEL = 5f;

    private static final long MAX_IMMUNE_TIME = 300L;
    private static float MAX_HOP_VEL = 3f;

    private static final long THROW_COOLDOWN_TIME = 300L;

    private boolean jumpingPressed = false;
    private long jumpTime;

    private boolean immunity = true;
    private long immuneTime;

    private boolean coolDown = false;
    private long coolTime;

    //simple constructor that sets the world and player to calculate for
    public PlayerController(World world){
        this.world = world;
        player = world.getPlayer();
    }

    /*update method.
    *Calls the handleInput method that will set the player's acceleration,
    *Puts acceleration in state time and adds it to velocity
    *Makes sure velocity isn't too large and sets it to its max value if so
    *Calls the blockCollision method which stops the player from going ghost
    */
    public void update(float v){
        handleInput();

        player.getAcceleration().y += GRAVITY;
        player.getAcceleration().scl(v);
        player.getVelocity().add(player.getAcceleration());

        if(player.getVelocity().x > MAX_VEL) player.getVelocity().x = MAX_VEL;
        if(player.getVelocity().x < -MAX_VEL) player.getVelocity().x = -MAX_VEL;

        checkBlockCollision(v);
        checkCollisionWithEnemies();
    }

    /*Block collision method
    *Puts velocity into state time
    *Obtains player rectangle from pool and sets it to the player's rectangle
    *Creates the startX, endX, startY, and endY variables, [[incomplete]]
    */
    private void checkBlockCollision(float v){

        player.getVelocity().scl(v);

        /*This segment grabs the block on either the left or right of the player based on their direction and the block
         *above that,if the blocks are solid, and checks them for collision
         */
        Rectangle playerRectangle = rectPool.obtain();
        playerRectangle.set(player.getBounds());

        int startX, endX;
        int startY = (int) player.getBounds().y;
        int endY = (int) (player.getBounds().y + player.getSize().y);
        if(player.getVelocity().x < 0) startX = endX = (int) StrictMath.floor(player.getBounds().x + player.getVelocity().x);
        else startX = endX = (int) StrictMath.floor(player.getBounds().x + player.getSize().x + player.getVelocity().x);

        int playerChunkIndex = (int)Math.ceil(player.getPosition().x/ Chunk.getSIZE().x) - 1;
        getCollidableBlocks(playerChunkIndex,startX,endX,startY,endY);

        playerRectangle.x += player.getVelocity().x;

        for (Block block : collidableBlocks){
            if(playerRectangle.overlaps(block.getBounds())){
                if(player.getVelocity().x < 0) player.getPosition().x = block.getBounds().x + block.getBounds().width;
                else player.getPosition().x = block.getBounds().x - player.getSize().x;
                player.getVelocity().x = 0;
                break;
            }
        }

        playerRectangle.x = player.getPosition().x;

        /*This segment grabs the block on either the top or bottom of the player based on their direction and the block
         *to the right of that,if they are solid, and checks them for collision
         */
        startX = (int) player.getBounds().x;
        endX = (int) (player.getBounds().x + player.getSize().x);
        if(player.getVelocity().y < 0) startY = endY = (int) StrictMath.floor(player.getBounds().y + player.getVelocity().y);
        else startY = endY = (int) StrictMath.floor(player.getBounds().y + player.getSize().y + player.getVelocity().y);

        getCollidableBlocks(playerChunkIndex,startX,endX,startY,endY);

        playerRectangle.y += player.getVelocity().y;

        for (Block block : collidableBlocks){
            if(playerRectangle.overlaps(block.getBounds())){
                if(player.getVelocity().y < 0){
                    player.getPosition().y = block.getBounds().y + block.getBounds().height;
                    if(GRAVITY < 0) player.setState(Player.State.Idle);
                }else{
                    player.getPosition().y = block.getBounds().y - player.getSize().y;
                    if(GRAVITY > 0) player.setState(Player.State.Idle);
                }
                player.getVelocity().y = 0;
                break;
            }
        }

        //updates the player, takes velocity out of state time, and clears the collidable array
        player.getPosition().add(player.getVelocity());
        player.getBounds().x = player.getPosition().x;
        player.getBounds().y = player.getPosition().y;
        player.getVelocity().scl(1/v);
        collidableBlocks.clear();
    }

    private void getCollidableBlocks(int i,int startX, int endX, int startY, int endY){
        for(int x = startX; x <= endX; x++){
            for(int y = startY; y <= endY; y++){
                try{
                    if(world.getChunks().get(i).getBlocks()[(int)(x - Chunk.getSIZE().x * i)][y].isSolid()){
                        collidableBlocks.add(world.getChunks().get(i).getBlocks()[(int)(x - Chunk.getSIZE().x * i)][y]);
                    }
                } catch(ArrayIndexOutOfBoundsException e){
                    //collidableBlocks.add(new Block(x,y));
                } catch(IndexOutOfBoundsException e){

                }
            }
        }
    }

    private void checkCollisionWithEnemies(){
        ArrayList<Enemy> enemies = world.getEnemies();

        for(Enemy enemy : enemies){
            if(player.getBounds().overlaps(enemy.getBounds()) && !(immunity)){
                player.setHealth(player.getHealth() - enemy.getAttackPower());
                immunity = true;
                immuneTime = System.currentTimeMillis();
                player.getVelocity().y += MAX_HOP_VEL;
                player.getVelocity().x = (player.getVelocity().x > 0) ? -5f : 5f;
            }else if(immunity && (System.currentTimeMillis() - immuneTime) >= MAX_IMMUNE_TIME){
                immunity = false;
            }
        }
    }

    private void handleInput(){

        if(keys.get(Keys.Left)){
            player.setFacingLeft(true);
            if(!(player.getState().equals(Player.State.Jumping))) player.setState(Player.State.Walking);
            player.getAcceleration().x = -ACCELERATION;
        } else if(keys.get(Keys.Right)){
            player.setFacingLeft(false);
            if(!(player.getState().equals(Player.State.Jumping))) player.setState(Player.State.Walking);
            player.getAcceleration().x = ACCELERATION;
        }else{
            if(player.getState() != Player.State.Jumping) player.setState(Player.State.Idle);
            player.getAcceleration().x = 0;
            player.getVelocity().x = 0;
        }

        if(keys.get(Keys.Jump)){
            if(!(player.getState() == Player.State.Jumping)){
                jumpingPressed = true;
                jumpTime = System.currentTimeMillis();
                player.setState(Player.State.Jumping);
                player.getVelocity().y = MAX_JUMP_VEL;
            }else{
                if(jumpingPressed && (System.currentTimeMillis() - jumpTime) >= MAX_JUMP_TIME){
                    jumpingPressed = false;
                }else if(jumpingPressed){
                    player.getVelocity().y = MAX_JUMP_VEL;
                }
            }
        }

        if(keys.get(Keys.Attack)){

            if(!coolDown){
                if(!(player.isFacingLeft())){
                    ThrowingKnife knife = new ThrowingKnife(player.getPosition().x + 0.5f, player.getPosition().y + 1/1.5f, false);
                    knife.getVelocity().x = knife.getStartingVelocity();
                    world.addThrowingKnife(knife);
                } else {
                    ThrowingKnife knife = new ThrowingKnife(player.getPosition().x + 0.5f, player.getPosition().y + 1/1.5f, true);
                    knife.getVelocity().x = -knife.getStartingVelocity();
                    world.addThrowingKnife(knife);
                }
                coolDown = true;
                coolTime = System.currentTimeMillis();
            }else if(coolDown && (System.currentTimeMillis() - coolTime) >= THROW_COOLDOWN_TIME){
                coolDown = false;
            }
        }

    }

    /*~~~~~~~~~~Key Presses~~~~~~~~~~*/

    public void leftPressed(){
        keys.put(Keys.Left, true);
    }

    public void rightPressed(){
        keys.put(Keys.Right, true);
    }

    public void jumpPressed(){
        keys.put(Keys.Jump, true);
    }

    public void attackPressed(){
        keys.put(Keys.Attack, true);
    }

    public void leftReleased(){
        keys.put(Keys.Left, false);
    }

    public void rightReleased(){
        keys.put(Keys.Right, false);
    }

    public void jumpReleased(){
        keys.put(Keys.Jump, false);
    }

    public void attackReleased(){
        keys.put(Keys.Attack, false);
    }
}




Java Source Code List

com.detel.infinite.Infinite.java
com.detel.infinite.MainActivity.java
com.detel.infinite.Main.java
com.detel.infinite.controllers.CameraController.java
com.detel.infinite.controllers.ChunkController.java
com.detel.infinite.controllers.EnemyController.java
com.detel.infinite.controllers.KnifeController.java
com.detel.infinite.controllers.PlayerController.java
com.detel.infinite.controllers.WorldController.java
com.detel.infinite.models.BlockAir.java
com.detel.infinite.models.Block.java
com.detel.infinite.models.Chunk.java
com.detel.infinite.models.Enemy.java
com.detel.infinite.models.Player.java
com.detel.infinite.models.ThrowingKnife.java
com.detel.infinite.models.World.java
com.detel.infinite.screens.ScreenBase.java
com.detel.infinite.screens.ScreenGameOver.java
com.detel.infinite.screens.ScreenGame.java
com.detel.infinite.screens.ScreenMainMenu.java
com.detel.infinite.screens.ScreenPause.java
com.detel.infinite.views.WorldRenderer.java