Subversion Repositories AndroidProjects

Rev

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

package com.gebauz.pingk.entities;

import java.util.Vector;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.Bauzoid.graphics.sprite.Sprite;
import com.gebauz.Bauzoid.math.MathUtil;
import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.pingk.game.GameConsts;
import com.gebauz.pingk.game.GameLogic;

public class Crystals extends Entity
{
        public class Particle
        {
                private float x;
                private float y;
                private float mAngle;
                private float mLifeTime;
                private int mNumSpawned;
                private Vector2 mDirection;
                private float mRegrowthTime;           
       
                public Particle(float posX, float posY, Vector2 direction, float regrowthTime)
                {
                        x = posX;
                        y = posY;
                        //mAngle = mGameLogic.getRandomFloat(0.0f, 360.0f);
                        mAngle = new Vector2(direction.x, -direction.y).getAngle();
                       
                        mLifeTime = 0.0f;
                        mNumSpawned = 0;
                        mDirection = direction;
                        mRegrowthTime = regrowthTime;
                }
               
                public void update(float deltaTime)
                {
                        mLifeTime += deltaTime;
                       
                        if ((mNumSpawned < GameConsts.POWERUP_CRYSTAL_PARTICLE_MAX_RESPAWN) && (mLifeTime > mRegrowthTime))
                        {
                                // check possible direction for growth (no other crystal must be in its way)
                                for (int i = 0; i < 10; i++)
                                {
                                        //float nextX = x + mGameLogic.getRandomFloat(-d, d);
                                        //float nextY = y + mGameLogic.getRandomFloat(-d, d);
                                        float rot = getGameLogic().getGame().getRandomFloat(0.0f, 360.0f);
                                        Vector2 direction = Vector2.fromRotation(rot);
                                        float testX = x + direction.x * GameConsts.POWERUP_CRYSTAL_SIZE;
                                        float testY = y + direction.y * GameConsts.POWERUP_CRYSTAL_SIZE;

                                        float nextX = x + direction.x * GameConsts.POWERUP_CRYSTAL_PARTICLE_DISTANCE;
                                        float nextY = y + direction.y * GameConsts.POWERUP_CRYSTAL_PARTICLE_DISTANCE;
                                       
                                        if ((!getGameLogic().getPlayField().isOutOfBoardInner(testX, testY)) && (findCrystalAt(testX, testY, GameConsts.POWERUP_CRYSTAL_RADIUS - 5.0f) == null))
                                        {
                                                // grow new
                                                spawnCrystal(nextX, nextY, direction);
                                                mNumSpawned++;

                                                break;
                                        }
                                }
                               
                                // reset grow timer
                                mLifeTime = GameConsts.POWERUP_CRYSTAL_PARTICLE_FADE_TIME;
                        }
                }
               
                public void render()
                {
                        float growth = MathUtil.clamp(mLifeTime / GameConsts.POWERUP_CRYSTAL_PARTICLE_FADE_TIME, 0.0f, 1.0f);
                       
                        mCrystal.x = x;
                        mCrystal.y = y;
                        mCrystal.w = GameConsts.POWERUP_CRYSTAL_SIZE * growth;
                        mCrystal.h = GameConsts.POWERUP_CRYSTAL_SIZE * growth;
                        mCrystal.pivotX = mCrystal.w / 2.0f;
                        mCrystal.pivotY = mCrystal.h / 2.0f;
                        mCrystal.angle = mAngle;
                       
                        mCrystal.x -= mDirection.x * GameConsts.POWERUP_CRYSTAL_SIZE * (1.0f-growth);
                        mCrystal.y -= mDirection.y * GameConsts.POWERUP_CRYSTAL_SIZE * (1.0f-growth);
                       
                        mCrystal.render();
                }
               
                public float distanceFrom(float posX, float posY)
                {
                        float dx = posX - x;
                        float dy = posY - y;
                       
                        return ((float)Math.sqrt(dx*dx + dy*dy) - GameConsts.POWERUP_CRYSTAL_RADIUS);
                }
               
                public boolean isInside(float posX, float posY)
                {
                        return (distanceFrom(posX, posY) <= 0.0f);
                }
        }
       
       
        public class Shard
        {
                private float x;
                private float y;
                private int mSpriteIndex;
                private Vector2 mDirection;
                private float mLifeTime;
                private float mSize;
               
                public Shard(float posX, float posY, int spriteIndex, Vector2 direction, float size)
                {
                        x = posX;
                        y = posY;
                        mDirection = direction;
                        mSpriteIndex = spriteIndex;
                        mLifeTime = 0.0f;
                        mSize = size;
                }
               
                public void update(float deltaTime)
                {
                        mLifeTime += deltaTime;
                       
                        x += mDirection.x * deltaTime;
                        y += mDirection.y * deltaTime;
                }
               
                public void render()
                {
                        float alpha = 1.0f - MathUtil.clamp(mLifeTime/GameConsts.POWERUP_CRYSTAL_SHARDS_LIFETIME, 0.0f, 1.0f);
                        // TODO: ease?
                       
                        mShardSprites[mSpriteIndex].color.w = alpha;
                        mShardSprites[mSpriteIndex].x = x;
                        mShardSprites[mSpriteIndex].y = y;
                        mShardSprites[mSpriteIndex].w = 32.0f;
                        mShardSprites[mSpriteIndex].h = 32.0f;
                        mShardSprites[mSpriteIndex].angle = mLifeTime * GameConsts.POWERUP_CRYSTAL_SHARDS_ROTATE_SPEED;
                        mShardSprites[mSpriteIndex].pivotX = mShardSprites[mSpriteIndex].w/2.0f;
                        mShardSprites[mSpriteIndex].pivotY = mShardSprites[mSpriteIndex].h/2.0f;
                        mShardSprites[mSpriteIndex].render();
                }
               
                public boolean isDone()
                {
                        return (mLifeTime > GameConsts.POWERUP_CRYSTAL_SHARDS_LIFETIME);
                }
        }
       
        private Vector<Particle> mParticles = new Vector<Particle>();
        private Vector<Shard> mShards = new Vector<Shard>();
       
        private static String[] mShardSpriteNames =
        {
                "data/textures/shard1.png",
                "data/textures/shard2.png",
                "data/textures/shard3.png",
                "data/textures/shard4.png",
                "data/textures/shard5.png",
        };
       
        private static final int NUM_SHARD_SPRITES = mShardSpriteNames.length;
       
        private Sprite mCrystal = null;
        private Sprite[] mShardSprites = new Sprite[NUM_SHARD_SPRITES];
       
        private Sound mCrystal1 = null;
        private Sound mCrystal2 = null;
       
        public Crystals(GameLogic gameLogic)
        {
                super(gameLogic);
        }

        @Override
        public void init()
        {
                mCrystal = new Sprite(getGraphics(), new Texture("data/textures/crystal.png"));
                mCrystal.color = GameConsts.PINGK_COLOR.copy();
               
                for (int i = 0; i < NUM_SHARD_SPRITES; i++)
                {
                        mShardSprites[i] = new Sprite(getGraphics(), new Texture(mShardSpriteNames[i]));
                        mShardSprites[i].color = GameConsts.PINGK_COLOR.copy();
                }
               
                mCrystal1 = getAudio().newManagedSound("data/sounds/crystal1.wav");
                mCrystal2 = getAudio().newManagedSound("data/sounds/crystal2.wav");
        }

        @Override
        public void exit()
        {
                if (mCrystal != null)
                {
                        mCrystal.dispose();
                        mCrystal = null;
                }
               
                for (int i = 0; i < NUM_SHARD_SPRITES; i++)
                {
                        if (mShardSprites[i] != null)
                        {
                                mShardSprites[i].dispose();
                                mShardSprites[i] = null;
                        }
                }
               
                getAudio().removeManagedSound(mCrystal1);
                getAudio().removeManagedSound(mCrystal2);
        }

        @Override
        public void update(float deltaTime)
        {
                Ball ball = getGameLogic().getBall();
               
                int i = 0;
                while (i < mParticles.size())
                {
                        Particle p = mParticles.get(i);
                        p.update(deltaTime);
                       
                        // check destruction
                       
                        if (p.isInside(ball.getX(), ball.getY()) && !p.isInside(ball.getLastX(), ball.getLastY()))
                        {
                                // reflect
                                Vector2 normal = new Vector2(ball.getX() - p.x, ball.getY() - p.y);
                                float angle = normal.getAngle();
                                ball.reflectAlongNormal(angle);
                               
                                // destroy
                                spawnShards(p.x, p.y);
                               
                                // remove
                                mParticles.remove(i);
                               
                                // play sound
                                //mGameLogic.playSound(R.raw.crystal1);
                                getAudio().playSound(mCrystal1);
                               
                                // add hit
                                getGameLogic().getCrystalHitCounter().addHit(p.x, p.y);
                               
                                continue;
                        }
                       
                        i++;
                }
               
                i = 0;
                while (i < mShards.size())
                {
                        Shard s = mShards.get(i);
                        s.update(deltaTime);
                       
                        if (s.isDone())
                        {
                                mShards.remove(i);
                                continue;
                        }
                       
                        i++;                   
                }
        }

        @Override
        public void render()
        {
                for (int i = mParticles.size()-1; i >= 0; i--)
                {
                        mParticles.get(i).render();
                }
               
                for (int i = 0; i < mShards.size(); i++)
                {
                        mShards.get(i).render();
                }
        }
       
        public void spawnCrystal(float posX, float posY, Vector2 direction)
        {
                if (mParticles.size() < GameConsts.POWERUP_CRYSTAL_MAX_PARTICLES)
                {
                        float regrowthTime = getGameLogic().getGame().getRandomFloat(GameConsts.POWERUP_CRYSTAL_PARTICLE_GROWTH_TIME_MIN, GameConsts.POWERUP_CRYSTAL_PARTICLE_GROWTH_TIME_MIN);
                        Particle p = new Particle(posX, posY, direction, regrowthTime);
                        mParticles.add(p);
                }
        }
               
        public void destroyCrystals()
        {
/*              if (mParticles.size() > 0)
                        mGameLogic.playSound(R.raw.crystal2);*/

                getAudio().playSound(mCrystal2);
               
                for (int i = 0; i<  mParticles.size(); i++)
                {
                        Particle p = mParticles.get(i);
                        spawnShards(p.x, p.y);
                }
               
                mParticles.clear();            
        }
       
        public Particle findCrystalAt(float posX, float posY, float maxDistance)
        {
                for (int i = 0; i < mParticles.size(); i++)
                {
                        Particle p = mParticles.get(i);
                       
                        if (p.distanceFrom(posX, posY) <= maxDistance)
                                return p;
                }
               
                return null;
        }
       
        public Particle findCrystalAt(float posX, float posY)
        {
                return findCrystalAt(posX, posY, 0.0f);
        }
       
        public void spawnShards(float posX, float posY)
        {
                // spawn multiple shards
                for (int i = 0; i < GameConsts.POWERUP_CRYSTAL_MAX_SHARDS; i++)
                {                      
                        int whichSprite = getGameLogic().getGame().getRandomInt(0, NUM_SHARD_SPRITES);
                        float x = posX + getGameLogic().getGame().getRandomFloat(-GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD, GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD);
                        float y = posY + getGameLogic().getGame().getRandomFloat(-GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD, GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD);
                       
                        Vector2 direction = Vector2.fromRotation(getGameLogic().getGame().getRandomFloat(0.0f, 360.0f));       
                        direction.setLength(GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD_SPEED);
                       
                        float size = getGameLogic().getGame().getRandomFloat(GameConsts.POWERUP_CRYSTAL_SHARDS_MIN_SIZE, GameConsts.POWERUP_CRYSTAL_SHARDS_MAX_SIZE);
                       
                        mShards.add(new Shard(x, y, whichSprite, direction, size));
                }
        }
       
        public int getNumCrystals()
        {
                return mParticles.size();
        }
}