Subversion Repositories AndroidProjects

Rev

Rev 629 | Rev 631 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.PonPonChun.gamestates;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.gebauz.Bauzoid.game.Game;
import com.gebauz.Bauzoid.gamestates.BaseGameState;
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.PonPonChun.game.GameConsts;
import com.gebauz.PonPonChun.game.entities.Block;
import com.gebauz.PonPonChun.game.entities.BlockBreakParticles;
import com.gebauz.PonPonChun.game.entities.BlockSprites;

public class LogoState extends BaseGameState
{
        // Constants========================================================================================
       
        public static final int NUM_BLOCKS = 6;
       
        public static final int BLOCK_SIZE = 64;
        public static final int BREAKBLOCK_SIZE = 68;
        public static final int BLOCK_OFFSET = 4;
       
        public static final float FALLING_SPEED = BLOCK_SIZE/0.05f;
       
        public static final float Y_TARGET = 400.0f;
        public static final float SQUASH_TIME = 0.2f;
       
        public static final float SWAP_TIME = 0.2f;
        public static final float CLEARING_TIME = 1.0f;
       
        public static final float LOGO_WAIT_TIME = 3.0f;
       
       
        public static final int BLOCK_TYPES[] =
                {
                        Block.TYPE_BLUE, Block.TYPE_BLUE, Block.TYPE_RED,
                        Block.TYPE_BLUE, Block.TYPE_RED, Block.TYPE_RED
                };

        // Embedded Types===================================================================================
       
        public enum State
        {
                WAIT_FOR_BLOCKS,
                SWAP_BLOCKS,
                WAIT_FOR_BLOCKS_CLEARING,
                WAIT_LOGO
        }
       
        public enum BlockState
        {
                FALLING,
                SQUASHING,
                RESTING,
                CLEARING,
                DESTROYED
        }
       
        public class LogoBlock
        {
                public int type;
                public float x;
                public float y;
                public float startY;
                public float timer;
                public BlockState state = BlockState.FALLING;
               
                public LogoBlock(float _x, float _y, int _type)
                {
                        x = _x;
                        y = _y;
                        startY = _y;
                        type = _type;
                       
                        timer = 0;
                }
               
                public void update(float deltaTime)
                {
                        timer += deltaTime;
                        if (state == BlockState.FALLING)
                        {
                                if (y < Y_TARGET)
                                {
                                        y += FALLING_SPEED*deltaTime;
                                        if (y >= Y_TARGET)
                                        {
                                                y = Y_TARGET;
                                               
                                                mBlockFall.play();
                                               
                                                state = BlockState.SQUASHING;
                                                timer = 0.0f;
                                        }
                                }
                        }
                        else if (state == BlockState.SQUASHING)
                        {
                                if (timer > SQUASH_TIME)
                                {
                                        state = BlockState.RESTING;
                                        timer = 0.0f;
                                }
                        }
                        else if (state == BlockState.CLEARING)
                        {
                                if (timer > CLEARING_TIME)
                                {
                                        mParticles.spawnParticles(x, y-BLOCK_SIZE/2);
                                        mParticles.spawnParticles(x, y+BLOCK_SIZE/2);
                                       
                                        state = BlockState.DESTROYED;
                                        timer = 0.0f;
                                }
                        }
                }
               
                public void render()
                {
                        if (state == BlockState.DESTROYED)
                                return;
                       
                        AtlasSpriteInstance s = mBlockSprites.getBlockSprite(type);
                       
                        float alphaMultiply = 1;
                        if (state == BlockState.CLEARING)
                        {
                                alphaMultiply = 1 - MathUtil.clamp(timer / CLEARING_TIME, 0, 1);
                        }
                       
                        s.x = x;
                        s.y = y;
                        s.w = BLOCK_SIZE;
                        s.h = BLOCK_SIZE;
                        s.pivotX = s.w/2;
                        s.pivotY = s.h;
                        s.mirrorY = false;
                        s.alpha = 1*alphaMultiply;
                       
                        if (state == BlockState.SQUASHING)
                        {
                                float f = 1 - MathUtil.clamp(timer / SQUASH_TIME, 0, 1);
                                float squashFactor = f*f;
                                s.w *= 1.2f - 0.2f * squashFactor;                     
                                s.h *= 0.8f + 0.2f * squashFactor;
                                s.pivotX = s.w/2;
                                s.pivotY = s.h;
                        }                      
                        s.render();
                       
                        float phase = getGame().getTime();
                       
                        // render break sprite if applicable
                        renderBreakSprite(s, phase);
                       
                        // render mirror image
                        s.mirrorY = true;
                        final float diffY = Y_TARGET;
                        s.y = Y_TARGET + diffY - y;
                        s.alpha = 0.5f*alphaMultiply;
                        s.render();                    
                       
                        renderBreakSprite(s, phase);
                }
               
                public void renderBreakSprite(AtlasSpriteInstance s, float phase)
                {
                        if (state == BlockState.CLEARING)
                        {
                                AtlasSprite breakSprite = mBlockSprites.getBreakSprite();
                               
                                breakSprite.x = s.x;
                                breakSprite.y = s.y + (BREAKBLOCK_SIZE-BLOCK_SIZE)/2;
                                breakSprite.w = BREAKBLOCK_SIZE;
                                breakSprite.h = BREAKBLOCK_SIZE;
                                breakSprite.pivotX = breakSprite.w/2;
                                breakSprite.pivotY = breakSprite.h;
                                breakSprite.mirrorY = s.mirrorY;
                                if (breakSprite.mirrorY)
                                        breakSprite.alpha = 0.5f;
                                else
                                        breakSprite.alpha = 1.0f;
                               
                                float t = MathUtil.clamp(timer / CLEARING_TIME, 0, 1);
                                //float t = CLEARING_TIME - timer;
                                if (t < 0.2f)
                                        // fade in
                                        breakSprite.alpha *= t / 0.2f;
                                else if (timer <= 0.0f)
                                        breakSprite.alpha *= 0.0f;
                                else
                                        breakSprite.alpha *= 1.0f;                             
               
                                float animate = (phase * 10.0f) % 1.0f;
                                int n = 0;
                                if (animate < 0.33f)
                                        n = 1;
                                else if (animate > 0.66f)
                                        n = 2;
                                breakSprite.render(n);
                        }
                }
        }

        // Fields===========================================================================================
       
        private BlockSprites mBlockSprites = null;
       
        private Sprite mBackground = null;
        private Sprite mGebauzLogo = null;
       
        private LogoBlock mBlocks[] = new LogoBlock[NUM_BLOCKS];
       
        private BlockBreakParticles mParticles = null;
       
        private Sound mBlockFall = null;
        private Sound mBlockSwap = null;
        private Sound mBlockClear = null;
        private Sound mBlockClearDestroy = null;
       
        private State mState = State.WAIT_FOR_BLOCKS;
        private float mStateTimer = 0.0f;
       
        // Methods==========================================================================================

        public LogoState(Game game)
        {
                super(game);
                setFading(true, true);
                mBlockSprites = new BlockSprites(getGraphics());
                mBackground = new Sprite(getGraphics(), "data/textures/logo_bg.png");
                mParticles = new BlockBreakParticles(game, mBlockSprites);
                mGebauzLogo = new Sprite(getGraphics(), "data/textures/gebauzlogo.png");
        }
       
        @Override
        public void initAsync(String param)
        {
                mBackground.initAsync();
                mGebauzLogo.initAsync();
               
                getAssetManager().load("data/sounds/block_fall.wav", Sound.class);
                getAssetManager().load("data/sounds/swap.wav", Sound.class);
                getAssetManager().load("data/sounds/super_clear.wav", Sound.class);
                getAssetManager().load("data/sounds/glass_break.wav", Sound.class);
        }

        @Override
        public void init(String param)
        {
                mBlockFall = getAssetManager().get("data/sounds/block_fall.wav", Sound.class);
                mBlockSwap = getAssetManager().get("data/sounds/swap.wav", Sound.class);
                mBlockClear = getAssetManager().get("data/sounds/super_clear.wav", Sound.class);
                mBlockClearDestroy = getAssetManager().get("data/sounds/glass_break.wav", Sound.class);
               
                mBlockSprites.init();
                mBackground.init(0, 0, GameConsts.VIRTUAL_SCREEN_WIDTH, GameConsts.VIRTUAL_SCREEN_HEIGHT, 0, 0);
                mGebauzLogo.init(240, 350, 400, 100);
               
                for (int i = 0; i < NUM_BLOCKS; i++)
                {
                        float posX = getBlockX(i);
                        float posY = -20 - getGame().getRandomInt(0, 300);
                       
                        mBlocks[i] = new LogoBlock(posX, posY, BLOCK_TYPES[i]);
                }
               
                mParticles.init();
        }

        @Override
        public void exit()
        {
                getAssetManager().unload("data/sounds/block_fall.wav");
                getAssetManager().unload("data/sounds/swap.wav");
                getAssetManager().unload("data/sounds/super_clear.wav");
                getAssetManager().unload("data/sounds/glass_break.wav");
               
                if (mParticles != null)
                {
                        mParticles.exit();
                        mParticles = null;
                }
               
                if (mBlockSprites != null)
                {
                        mBlockSprites.exit();
                        mBlockSprites = null;
                }
               
                if (mGebauzLogo != null)
                {
                        mGebauzLogo.dispose();
                        mGebauzLogo = null;
                }
               
                if (mBackground != null)
                {
                        mBackground.dispose();
                        mBackground = null;
                }
        }

        @Override
        public void update(float deltaTime)
        {
                if (Gdx.input.justTouched())
                {
                        getGameStateManager().switchTo(com.gebauz.PonPonChun.gamestates.TitleState.class, "");                 
                }
               
                for (int i = 0; i < NUM_BLOCKS; i++)
                {
                        mBlocks[i].update(deltaTime);
                }
               
                mStateTimer += deltaTime;              
                switch(mState)
                {
                case WAIT_FOR_BLOCKS:
                        updateWaitForBlocks(deltaTime);
                        break;
                case SWAP_BLOCKS:
                        updateSwapBlocks(deltaTime);
                        break;
                case WAIT_FOR_BLOCKS_CLEARING:
                        updateWaitForBlocksClearing(deltaTime);
                        break;
                case WAIT_LOGO:
                        updateWaitLogo(deltaTime);
                        break;
                }
               
                mParticles.update(deltaTime);
        }
       
        public void updateWaitForBlocks(float deltaTime)
        {
                for (int i = 0; i < NUM_BLOCKS; i++)
                {
                        if (mBlocks[i].state != BlockState.RESTING)
                        {
                                return;
                        }
                }
               
                // only execute if all blocks are resting
                mState = State.SWAP_BLOCKS;
                mStateTimer = 0;
                mBlockSwap.play();
        }

        public void updateSwapBlocks(float deltaTime)
        {
                // swap block index 2 and 3
               
                // block index 2 should move towards 3
                {
                        final float target = getBlockX(3);
                        final float src = getBlockX(2);
                        final float diff = target - src;
                       
                        mBlocks[2].x = src + diff * MathUtil.clamp(mStateTimer / SWAP_TIME, 0, 1);
                }
               
                // block index 3 should move towards 2
                {
                        final float target = getBlockX(2);
                        final float src = getBlockX(3);
                        final float diff = target - src;
                       
                        mBlocks[3].x = src + diff * MathUtil.clamp(mStateTimer / SWAP_TIME, 0, 1);
                }
               
                if (mStateTimer > SWAP_TIME)
                {
                        for (int i = 0; i < NUM_BLOCKS; i++)
                        {
                                mBlocks[i].state = BlockState.CLEARING;
                                mBlocks[i].timer = 0;
                        }
                        mState = State.WAIT_FOR_BLOCKS_CLEARING;                       
                        mStateTimer = 0;
                        mBlockClear.play();
                }              
        }
       
        public void updateWaitForBlocksClearing(float deltaTime)
        {
                for (int i = 0; i < NUM_BLOCKS; i++)
                {
                        if (mBlocks[i].state != BlockState.DESTROYED)
                                return;
                }
               
                mBlockClearDestroy.play();
                mState = State.WAIT_LOGO;
                mStateTimer = 0.0f;
        }
       
        public void updateWaitLogo(float deltaTime)
        {
                if (mStateTimer > LOGO_WAIT_TIME)
                {
                        // switch state
                        getGameStateManager().switchTo(com.gebauz.PonPonChun.gamestates.TitleState.class, "");
                }
        }      
       

        @Override
        public void render()
        {
                getGraphics().clear(0, 0, 0, 0);
               
                getRenderStates().projection.setOrtho(
                                0.0f,
                                GameConsts.VIRTUAL_SCREEN_WIDTH-1,
                                GameConsts.VIRTUAL_SCREEN_HEIGHT-1,
                                0.0f,
                                0.0f,
                                1.0f
                        );
               
                mBackground.render();
               
                if (/*(mState == State.WAIT_FOR_BLOCKS_CLEARING) ||*/
                        (mState == State.WAIT_LOGO))
                {
                        /*float a = mStateTimer / CLEARING_TIME;
                       
                        if (a < 0.95f)
                                a = 0.0f;
                        else
                                a = MathUtil.clamp((a - 0.95f) / 0.05f, 0, 1);
                       
                        a = 0.0f;
                       
                        //if (mState == State.WAIT_LOGO)
                                a = 1.0f;*/

                       
                        final float shiftY = 16;

                        mGebauzLogo.x = 240;
                        mGebauzLogo.y = Y_TARGET + shiftY;
                        mGebauzLogo.w = 400;
                        mGebauzLogo.h = 100;
                        mGebauzLogo.pivotX = mGebauzLogo.w/2;
                        mGebauzLogo.pivotY = mGebauzLogo.h;
                        mGebauzLogo.mirrorY = false;
                        mGebauzLogo.alpha = 1.0f;
                        mGebauzLogo.render();
                       
                        mGebauzLogo.mirrorY = true;
                        mGebauzLogo.alpha = 0.3f;
                        mGebauzLogo.y = Y_TARGET - shiftY;
                        mGebauzLogo.render();
                }
               
                for (int i = 0; i < NUM_BLOCKS; i++)
                {
                        mBlocks[i].render();
                }
               
                mParticles.render();
        }
       
        public float getBlockX(int i)
        {
                final float totalWidth = NUM_BLOCKS * BLOCK_SIZE + (NUM_BLOCKS-1) * BLOCK_OFFSET;
                return (GameConsts.VIRTUAL_SCREEN_WIDTH - totalWidth) / 2 + BLOCK_SIZE/2 + i * (BLOCK_SIZE+BLOCK_OFFSET);
        }
       
        // Getters/Setters==================================================================================
}