Subversion Repositories AndroidProjects

Rev

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

package com.gebauz.pingK.game;

import java.util.Vector;

import com.gebauz.framework.util.MathUtil;
import com.gebauz.framework.util.Sprite2D;
import com.gebauz.framework.util.Vector2;
import com.gebauz.pingK.R;

public class Crystals
{
        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 = mGameLogic.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 ((!mGameLogic.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);
                        /*float dx = posX - x;
                        float dy = posX - y;
                        float lengthSqr = dx*dx + dy*dy;
                       
                        return (lengthSqr <= GameConsts.POWERUP_CRYSTAL_RADIUS_SQR);*/

                }
               
/*              public boolean isGrown()
                {
                        return (mLifeTime > GameConsts.POWERUP_CRYSTAL_PARTICLE_GROWTH_TIME);
                }*/

        }
       
        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].setColor(GameConsts.PINGK_COLOR.x, GameConsts.PINGK_COLOR.y, GameConsts.PINGK_COLOR.z, 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 GameLogic mGameLogic = null;
        private Vector<Particle> mParticles = new Vector<Particle>();
        private Vector<Shard> mShards = new Vector<Shard>();
       
        private static int[] mShardSpriteIds =
        {
                R.drawable.shard1,
                R.drawable.shard2,
                R.drawable.shard3,
                R.drawable.shard4,
                R.drawable.shard5,
        };
       
        private static final int NUM_SHARD_SPRITES = mShardSpriteIds.length;
       
        private Sprite2D mCrystal = new Sprite2D();
        private Sprite2D[] mShardSprites = new Sprite2D[NUM_SHARD_SPRITES];
       
       
        public Crystals(GameLogic gameLogic)
        {
                mGameLogic = gameLogic;
               
                mCrystal.init(R.drawable.crystal);
                mCrystal.setColor(GameConsts.PINGK_COLOR);
               
                for (int i = 0; i < NUM_SHARD_SPRITES; i++)
                {
                        mShardSprites[i] = new Sprite2D();
                        mShardSprites[i].init(mShardSpriteIds[i]);
                }
        }
       
        public void update(float deltaTime)
        {
                Ball ball = mGameLogic.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);
                               
                                // add hit
                                mGameLogic.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++;                   
                }
        }
       
        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 = mGameLogic.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);
               
                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 = mGameLogic.getRandomizer().nextInt(NUM_SHARD_SPRITES);
                        float x = posX + mGameLogic.getRandomFloat(-GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD, GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD);
                        float y = posY + mGameLogic.getRandomFloat(-GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD, GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD);
                       
                        Vector2 direction = Vector2.fromRotation(mGameLogic.getRandomFloat(0.0f, 360.0f));     
                        direction.setLength(GameConsts.POWERUP_CRYSTAL_SHARDS_SPREAD_SPEED);
                       
                        float size = mGameLogic.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();
        }
}