Subversion Repositories AndroidProjects

Rev

Rev 993 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.burutaru.game.entities;

import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteFrame;
import com.gebauz.bauzoid.graphics.sprite.AtlasSprite;
import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteInstance;
import com.gebauz.bauzoid.graphics.sprite.Sprite;
import com.gebauz.bauzoid.math.MathUtil;
import com.gebauz.bauzoid.math.Matrix4;
import com.gebauz.bauzoid.math.collision.AABoundingBox;
import com.gebauz.bauzoid.math.collision.Shape;
import com.gebauz.bauzoid.math.collision.ShapeUtil;
import com.gebauz.burutaru.GameConsts;
import com.gebauz.burutaru.game.GameLogic;

public class Ship extends Entity
{
       
        // Constants========================================================================================

        public static final int SHIP_WIDTH = 64;
        public static final int SHIP_HEIGHT = 64;
       
        // HACK: for powerup pickup
        public static final float SHIP_RADIUS_SQR = SHIP_WIDTH*SHIP_WIDTH * 0.5f;
       
        public static final int NUM_UP_FRAMES = 5;
        public static final int NUM_DOWN_FRAMES = 5;
        public static final int NUM_SHIP_FRAMES = 1 + NUM_UP_FRAMES + NUM_DOWN_FRAMES;
        public static final int SHIP_SPRITE_SIZE = 128;
        public static final int NUM_SHIP_FRAMES_X = 4;
        public static final int NUM_SHIP_FRAMES_Y = 4;
        public static final float UPDOWN_ANIM_SPEED = 4.0f;
        public static final float UPDOWN_THRESHOLD = 20.0f;
       
        public static final float MUZZLEFLASH_DURATION = 0.15f;
        public static final float MUZZLEFLASH_SIZE = 40.0f;
       
        public static final float EXHAUST_WIDTH = 28;
        public static final float EXHAUST_HEIGHT = 16;
       
        public static final float EXHAUST_BOOST_MAX = 0.3f;
        public static final float EXHAUST_BOOST_MIN = -0.1f;
        public static final float EXHAUST_BOOST_FACTOR = 11.0f;
        public static final float EXHAUST_ANIM_SPEED = 4000.0f;
       
       
        public static final float ENGINE_BOOST_DURATION = 0.5f;
       
        public static final float BEAMSHOT_COOLDOWN_TIME = 0.2f;
       
        public static final float DAMAGE_COOLDOWN_TIME = 0.2f;

        // Embedded Types===================================================================================
       
        public enum MoveDirection
        {
                NONE,
                UP,
                DOWN
        }      
       
        // Fields===========================================================================================
       
        private float mPositionX = 100;
        private float mPositionY = 100;
       
        private float mLastMoveX = 0.0f;
        private float mLastMoveY = 0.0f;
       
        private AtlasSprite mShipAtlas = null;
        private AtlasSpriteFrame mShipFrames[] = new AtlasSpriteFrame[NUM_SHIP_FRAMES];
        private AtlasSpriteInstance mSpriteInstance = null;
       
        private Shape mShipShape = null;
       
        private int mCurrentShipFrame = 0;
        private MoveDirection mMoveDirection = MoveDirection.NONE;     
       
        private Sprite mMuzzleFlash = null;
        private float mMuzzleFlashTimer = -1.0f;
       
        private float mBeamShotTimer = 0.0f;
       
        private Sprite mEngineExhaust = null;
        private float mEngineExhaustScale = 1.0f;
        private float mEngineExhaustBoost = 0.0f;
       
        private float mMoveDirectionCoeff = 0.0f;
        private float mMoveDirectionCoeffTarget = 0.0f;
       
        private float mEngineBoostTimer = 0.0f;
       
        private Sound mEngineBoostSfx = null;
       
        private float mDamageCoolDown = 0.0f;

        // Methods==========================================================================================
       
        public Ship(GameLogic gameLogic)
        {
                super(gameLogic);
                mShipAtlas = new AtlasSprite(getGraphics(), "data/textures/shipframes.png", "data/textures/ship.txt");
                mMuzzleFlash = new Sprite(getGraphics(), "data/textures/plasma_muzzleflash.png");
                mEngineExhaust = new Sprite(getGraphics(), "data/textures/engine_exhaust.png");
        }

        @Override
        public void initAsync()
        {
                mShipAtlas.initAsync();
                mMuzzleFlash.initAsync();
                mEngineExhaust.initAsync();
        }
       
        @Override
        public void init()
        {
                mEngineBoostSfx = getAudio().newManagedSound("data/sounds/speedup.wav");
               
                mShipAtlas.init();
                mShipAtlas.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
                mShipAtlas.createSpriteInstances(mShipFrames);
                mMuzzleFlash.init();
                mMuzzleFlash.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
                mEngineExhaust.init();
                mEngineExhaust.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
               
                mShipShape = ShapeUtil.createShapeFromFile("data/textures/ship.shape");
               
                mSpriteInstance = new AtlasSpriteInstance(getGraphics(), mShipAtlas, mShipFrames, mShipShape);
        }
       
        @Override
        public void exit()
        {
                mShipShape = null;
                mSpriteInstance = null;
               
                for (int i = 0; i < NUM_SHIP_FRAMES; i++)
                {
                        mShipFrames[i] = null;
                }
               
                if (mShipAtlas != null)
                {
                        mShipAtlas.dispose();
                        mShipAtlas = null;
                }
               
                if (mMuzzleFlash != null)
                {
                        mMuzzleFlash.dispose();
                        mMuzzleFlash = null;
                }
               
                if (mEngineExhaust != null)
                {
                        mEngineExhaust.dispose();
                        mEngineExhaust = null;
                }
               
                if (mEngineBoostSfx != null)
                {
                        getAudio().removeManagedSound(mEngineBoostSfx);
                        mEngineBoostSfx = null;
                }
        }
       
        @Override
        public void update(float deltaTime)
        {
                if (mMoveDirection == MoveDirection.UP)
                {
                        // move towards -1
                        mMoveDirectionCoeff -= deltaTime * UPDOWN_ANIM_SPEED;
                        if (mMoveDirectionCoeff < mMoveDirectionCoeffTarget)
                                mMoveDirectionCoeff = mMoveDirectionCoeffTarget;
                }
                else if (mMoveDirection == MoveDirection.DOWN)
                {
                        // move towards +1
                        mMoveDirectionCoeff += deltaTime * UPDOWN_ANIM_SPEED;
                        if (mMoveDirectionCoeff > mMoveDirectionCoeffTarget)
                                mMoveDirectionCoeff = mMoveDirectionCoeffTarget;
                }
                else if (mMoveDirection == MoveDirection.NONE)
                {
                        // move towards 0
                        if (mMoveDirectionCoeff > 0)
                                mMoveDirectionCoeff = MathUtil.clamp(mMoveDirectionCoeff - deltaTime * UPDOWN_ANIM_SPEED, 0, 1);                               
                        else if (mMoveDirectionCoeff < 0)
                                mMoveDirectionCoeff = MathUtil.clamp(mMoveDirectionCoeff + deltaTime * UPDOWN_ANIM_SPEED, -1, 0);
                }
               
                mMoveDirectionCoeff = MathUtil.clamp(mMoveDirectionCoeff, -1, 1);
               
                if (mMoveDirectionCoeff > 0)
                {
                        mCurrentShipFrame = (int)(1 + (NUM_DOWN_FRAMES-1) * (mMoveDirectionCoeff));
                }
                else if (mMoveDirectionCoeff < 0)
                {
                        mCurrentShipFrame = (int)(1 + NUM_DOWN_FRAMES  + (NUM_UP_FRAMES-1) * (-mMoveDirectionCoeff));                  
                }
                else
                {
                        mCurrentShipFrame = 0;
                }
               
                //Gdx.app.log(GameConsts.LOG_TAG, "coeff = " + mMoveDirectionCoeff + ", frame = " + mCurrentShipFrame + ", dir = " + mMoveDirection);
               
                mCurrentShipFrame = MathUtil.clamp(mCurrentShipFrame, 0, NUM_SHIP_FRAMES-1);
               
                if (mLastMoveX > 0.0f)
                {
                        // grow
                        float diff = EXHAUST_BOOST_MAX - mEngineExhaustBoost;
                        mEngineExhaustBoost += diff * deltaTime * EXHAUST_BOOST_FACTOR;
                }
                else if (mLastMoveX < 0.0f)
                {
                        float diff = EXHAUST_BOOST_MIN - mEngineExhaustBoost;
                        mEngineExhaustBoost += diff * deltaTime * EXHAUST_BOOST_FACTOR;
                }
                else
                {
                        float diff = 0.0f - mEngineExhaustBoost;
                        mEngineExhaustBoost += diff * deltaTime * EXHAUST_BOOST_FACTOR;
                }
                mEngineExhaustScale = 0.9f + MathUtil.sin(getGame().getTime() * EXHAUST_ANIM_SPEED) * 0.05f + mEngineExhaustBoost;
               
                if (mEngineBoostTimer > 0.0f)
                {
                        mEngineBoostTimer -= deltaTime;
                        if (mEngineBoostTimer < 0.0f)
                                mEngineBoostTimer = 0.0f;
                }
               
                mEngineExhaustScale += ((mEngineBoostTimer / ENGINE_BOOST_DURATION) * 1.8f);
               

                if (mMuzzleFlashTimer > 0.0f)
                        mMuzzleFlashTimer -= deltaTime;
               
                if (mBeamShotTimer > 0.0f)
                        mBeamShotTimer -= deltaTime;
               
                if (mDamageCoolDown > 0.0f)
                        mDamageCoolDown -= deltaTime;
        }
       
        @Override
        public void render()
        {
               
                if (mEngineBoostTimer > 0.0f)
                {
                        mMuzzleFlash.param.x = mPositionX;
                        mMuzzleFlash.param.y = mPositionY - 1;
                        mMuzzleFlash.param.w = MUZZLEFLASH_SIZE * (1 + mEngineBoostTimer / ENGINE_BOOST_DURATION);
                        mMuzzleFlash.param.h = MUZZLEFLASH_SIZE * (1 + 0.5f*mEngineBoostTimer / ENGINE_BOOST_DURATION);
                        mMuzzleFlash.param.pivotX = mMuzzleFlash.param.w;
                        mMuzzleFlash.param.pivotY = mMuzzleFlash.param.h/2;
                        mMuzzleFlash.param.mirrorX = true;
                        mMuzzleFlash.param.alpha = (mEngineBoostTimer / ENGINE_BOOST_DURATION);
                        mMuzzleFlash.render();
                }
               
                mEngineExhaust.param.x = mPositionX - EXHAUST_WIDTH/2;
                mEngineExhaust.param.y = mPositionY - 1;
                mEngineExhaust.param.w = EXHAUST_WIDTH * mEngineExhaustScale;
                mEngineExhaust.param.h = EXHAUST_HEIGHT;
                mEngineExhaust.param.pivotX = mEngineExhaust.param.w;
                mEngineExhaust.param.pivotY = mEngineExhaust.param.h/2;
                mEngineExhaust.render();

               
                mSpriteInstance.param.x = mPositionX;
                mSpriteInstance.param.y = mPositionY;
                mSpriteInstance.param.w = SHIP_WIDTH;
                mSpriteInstance.param.h = SHIP_HEIGHT;
                mSpriteInstance.param.centerPivot();
                mSpriteInstance.renderFrame(mCurrentShipFrame);
               
                /*mShipFrames[mCurrentShipFrame].param.x = mPositionX;
                mShipFrames[mCurrentShipFrame].param.y = mPositionY;
                mShipFrames[mCurrentShipFrame].param.w = SHIP_WIDTH;
                mShipFrames[mCurrentShipFrame].param.h = SHIP_HEIGHT;
                mShipFrames[mCurrentShipFrame].centerPivot();
                mShipFrames[mCurrentShipFrame].render();*/

               
                if (mMuzzleFlashTimer > 0.0f)
                {
                        mMuzzleFlash.param.x = mPositionX + SHIP_WIDTH/2;
                        mMuzzleFlash.param.y = mPositionY;
                        mMuzzleFlash.param.w = MUZZLEFLASH_SIZE;
                        mMuzzleFlash.param.h = MUZZLEFLASH_SIZE;
                        mMuzzleFlash.param.pivotX = mMuzzleFlash.param.w/3 + 1.0f;
                        mMuzzleFlash.param.pivotY = mMuzzleFlash.param.h/2;
                        mMuzzleFlash.param.mirrorX = false;
                        mMuzzleFlash.param.alpha = mMuzzleFlashTimer/MUZZLEFLASH_DURATION;
                        mMuzzleFlash.render();
                }
        }
       
        public void moveBy(float x, float y, float deltaTime)
        {
                mPositionX += x*deltaTime;
                mPositionY += y*deltaTime;
               
                // TODO: scale with amount of y
                if (y < -UPDOWN_THRESHOLD)
                {
                        mMoveDirection = MoveDirection.UP;
                        //mMoveDirectionCoeffTarget = -1.0f;
                        mMoveDirectionCoeffTarget = (y + UPDOWN_THRESHOLD) * 0.01f;
                }
                else if (y > UPDOWN_THRESHOLD)
                {
                        mMoveDirection = MoveDirection.DOWN;
                        mMoveDirectionCoeffTarget = (y - UPDOWN_THRESHOLD) * 0.01f;
                }
                else
                {
                        mMoveDirection = MoveDirection.NONE;
                        mMoveDirectionCoeffTarget = 0.0f;
                }
               
                mPositionX = MathUtil.clamp(mPositionX, 0.0f, GameConsts.VIRTUAL_SCREEN_WIDTH);
                mPositionY = MathUtil.clamp(mPositionY, 0.0f, GameConsts.VIRTUAL_SCREEN_HEIGHT);
               
                mLastMoveX = x * deltaTime;
                mLastMoveY = y * deltaTime;
        }
       
        public void resetNoUpDownMovement()
        {
                mMoveDirection = MoveDirection.NONE;
                mMoveDirectionCoeffTarget = 0.0f;
        }
       
        public void shoot()
        {
                switch (getGameLogic().getShipParameters().getWeaponType())
                {
                case PLASMA_SHOT:
                        shootPlasma();
                        break;
                case BEAM_SHOT:
                        shootBeamShot();
                        break;
                case SPREAD_SHOT:
                        break;
                case NAPALM_SHOT:
                        break;
                }
               
                shootMissile();
                shootBomb();           
        }
       
        public void shootPlasma()
        {
                getGameLogic().getPlasmaShots().spawnShot(mPositionX + SHIP_WIDTH/2, mPositionY);
                mMuzzleFlashTimer = MUZZLEFLASH_DURATION;
        }
       
        public void shootMissile()
        {
                if (getGameLogic().getShipParameters().areMissilesEnabled())
                        getGameLogic().getPowerUpMissile().launch(mPositionX + SHIP_WIDTH/3, mPositionY);
        }
       
        public void shootBomb()
        {
                if (getGameLogic().getShipParameters().areBombsEnabled())
                        getGameLogic().getPowerUpBomb().launch(mPositionX + SHIP_WIDTH/3, mPositionY);
        }
       
        public void shootBeamShot()
        {
                if (mBeamShotTimer <= 0.0f)
                {
                        getGameLogic().getBeamShots().spawnShot(mPositionX + SHIP_WIDTH/2, mPositionY);
                        mBeamShotTimer = BEAMSHOT_COOLDOWN_TIME;
                }
        }
       
        public void boostEngine()
        {
                // boost for speed up powerup
                mEngineBoostTimer = ENGINE_BOOST_DURATION;
                mEngineBoostSfx.play();
        }
       
        public void processHit(ICollidable collidable)
        {
                if (mDamageCoolDown <= 0.0f)
                {
                        getGameLogic().getExplosions().spawn(mPositionX, mPositionY, 100);
                        mDamageCoolDown = DAMAGE_COOLDOWN_TIME;
                }
        }

        // Getters/Setters==================================================================================
        public float getPositionX() { return mPositionX; }
        public float getPositionY() { return mPositionY; }
       
        public AABoundingBox getBounds() { return mSpriteInstance.param.getBoundingBox(); }
       
        /** Get the shape of the projectile for testing. */
        public Shape getShape() { return mShipShape; }
       
        /** Get the transformation of the shape for testing. */
        public Matrix4 getShapeTransform() { return mSpriteInstance.param.getTransform(); }
       
}