Subversion Repositories AndroidProjects

Rev

Rev 949 | Rev 956 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
886 chris 1
package com.gebauz.burutaru.game.entities;
2
 
890 chris 3
import com.badlogic.gdx.audio.Sound;
886 chris 4
import com.gebauz.bauzoid.graphics.sprite.AtlasSprite;
915 chris 5
import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteFrame;
945 chris 6
import com.gebauz.bauzoid.graphics.sprite.AtlasSpriteInstance;
886 chris 7
import com.gebauz.bauzoid.math.MathUtil;
945 chris 8
import com.gebauz.bauzoid.math.Matrix4;
887 chris 9
import com.gebauz.bauzoid.math.Vector2;
950 chris 10
import com.gebauz.bauzoid.math.collision.AABoundingBox;
945 chris 11
import com.gebauz.bauzoid.math.collision.Shape;
12
import com.gebauz.bauzoid.math.collision.ShapeUtil;
886 chris 13
import com.gebauz.burutaru.GameConsts;
14
import com.gebauz.burutaru.game.GameLogic;
15
 
16
public class PowerUpMissile extends Entity
17
{
18
 
19
        // Constants========================================================================================
20
 
945 chris 21
        public static final int MISSILE_DAMAGE = 10;
22
 
890 chris 23
        public static final int MAX_MISSILES = 2;
886 chris 24
 
25
        public static final int UPPER_MISSILE = 0;
26
        public static final int LOWER_MISSILE = 1;
27
 
28
        public static final float MISSILE_WIDTH = 40;
29
        public static final float MISSILE_HEIGHT = MISSILE_WIDTH/2;
30
 
31
        public static final float MISSILE_ROTATION_DURATION = 0.5f;
32
 
33
        public static final float MISSILE_SPEED = 400.0f;
34
 
887 chris 35
        public static final float LAUNCH_TIME = 0.4f;
886 chris 36
        public static final float LAUNCH_SPEED =  100.0f;
887 chris 37
 
38
        public static final int NUM_MISSILE_FRAMES = 4;
39
        public static final int ROCKET_FIRE_FRAME = 4;
40
 
41
        public static final float ROCKET_FIRE_SIZE = 20;
42
        public static final float ROCKET_FIRE_SIZE_VARIANCE = 10;
43
        public static final float ROCKET_FIRE_OFFSET = 5;
44
 
895 chris 45
        public static final float MAX_ANGLE = 20.0f;
896 chris 46
        public static final float ANGULAR_SPEED = 25.0f;
890 chris 47
 
896 chris 48
        public static final float HEADING_UPDATE_INTERVAL = 0.125f;
886 chris 49
 
50
        // Embedded Types===================================================================================
51
 
52
        public enum MissilePhase
53
        {
54
                PHASE_LAUNCHING,
55
                PHASE_HOAMING
56
        }
57
 
945 chris 58
        public class Missile extends Projectile
886 chris 59
        {
945 chris 60
                public AtlasSpriteInstance spriteInstance = null;
61
 
886 chris 62
                public int type = -1;
63
                public float lifeTime = 0.0f;
64
 
65
                private MissilePhase mPhase;
945 chris 66
                private float angle = 0.0f;
890 chris 67
                private float mCurrentAngle = 0.0f;
886 chris 68
 
890 chris 69
                private float mHeadingUpdateTimer = 0.0f;
70
 
886 chris 71
                public Missile(int _type)
72
                {
945 chris 73
                        super(MISSILE_DAMAGE);
886 chris 74
                        type = _type;
945 chris 75
 
76
                        spriteInstance = new AtlasSpriteInstance(getGraphics(), mMissileSprite, mMissileFrames, mMissileShape);
77
                        setAlive(false);
886 chris 78
                }
79
 
945 chris 80
                public void launch(float x, float y)
886 chris 81
                {
82
                        lifeTime = 0.0f;
945 chris 83
                        angle = 0.0f;
890 chris 84
                        mCurrentAngle = 0.0f;
886 chris 85
                        mPhase = MissilePhase.PHASE_LAUNCHING;
890 chris 86
                        mHeadingUpdateTimer = 0.0f;
945 chris 87
 
88
                        spriteInstance.param.x = x;
89
                        spriteInstance.param.y = y;
90
                        spriteInstance.param.w = MISSILE_WIDTH;
91
                        spriteInstance.param.h = MISSILE_HEIGHT;
92
                        spriteInstance.param.pivotX = spriteInstance.param.w;
93
                        spriteInstance.param.pivotY = spriteInstance.param.h / 2;
949 chris 94
                        spriteInstance.param.angle = 0.0f;
945 chris 95
 
96
                        setAlive(true);
886 chris 97
                }
98
 
99
                public void update(float deltaTime)
100
                {
101
                        // search nearest enemy and adjust heading towards it
102
                        lifeTime += deltaTime;
103
 
104
                        switch(mPhase)
105
                        {
106
                        case PHASE_LAUNCHING:
107
                                //float t = MathUtil.clamp((lifeTime / LAUNCH_TIME), 0.0f, 1.0f);
108
 
109
                                if (type == UPPER_MISSILE)
110
                                {
945 chris 111
                                        spriteInstance.param.y -= LAUNCH_SPEED * deltaTime;
886 chris 112
                                }
113
                                else if (type == LOWER_MISSILE)
114
                                {
945 chris 115
                                        spriteInstance.param.y += LAUNCH_SPEED * deltaTime;                                    
886 chris 116
                                }
117
 
118
                                if (lifeTime > LAUNCH_TIME)
119
                                {
120
                                        mPhase = MissilePhase.PHASE_HOAMING;
890 chris 121
                                        mRocketFireSfx.play(0.3f);
886 chris 122
                                }                              
123
                                break;
124
                        case PHASE_HOAMING:
887 chris 125
                                // default target: just ahead
945 chris 126
                                Vector2 target = new Vector2(spriteInstance.param.x + 100.0f, spriteInstance.param.y);
127
                                getGameLogic().getNearestEnemyPosition(spriteInstance.param.x, spriteInstance.param.y, target);
890 chris 128
 
945 chris 129
                                Vector2 heading = new Vector2(target.x - spriteInstance.param.x, target.y - spriteInstance.param.y);
887 chris 130
 
890 chris 131
                                mHeadingUpdateTimer += deltaTime;
132
                                if (mHeadingUpdateTimer > HEADING_UPDATE_INTERVAL)
133
                                {
134
                                        mHeadingUpdateTimer = 0.0f;
135
                                        angle = MathUtil.radToDeg((float)Math.atan2(-heading.y, heading.x));
136
                                }
888 chris 137
 
890 chris 138
                                float diff = MathUtil.turnDegrees(angle, mCurrentAngle);
139
                                if (diff > MAX_ANGLE)
140
                                        diff = MAX_ANGLE;
141
                                if (mCurrentAngle > angle)
142
                                {
143
                                        mCurrentAngle -= diff * deltaTime * ANGULAR_SPEED;
144
                                        if (mCurrentAngle < angle)
145
                                                mCurrentAngle = angle;
146
                                }
147
                                else if (mCurrentAngle < angle)
148
                                {
149
                                        mCurrentAngle += diff * deltaTime * ANGULAR_SPEED;
150
                                        if (mCurrentAngle > angle)
151
                                                mCurrentAngle = angle;
152
                                }
153
 
154
                                heading.x = (float)Math.cos(Math.toRadians(mCurrentAngle));
155
                                heading.y = -(float)Math.sin(Math.toRadians(mCurrentAngle));
156
                                heading.normalize();
157
 
945 chris 158
                                spriteInstance.param.x += MISSILE_SPEED * deltaTime * heading.x;
159
                                spriteInstance.param.y += MISSILE_SPEED * deltaTime * heading.y;
160
                                spriteInstance.param.angle = mCurrentAngle;
886 chris 161
                                break;
162
                        }
947 chris 163
 
945 chris 164
                        getGameLogic().checkProjectileHit(this);
165
 
166
                        if ((spriteInstance.param.x > (GameConsts.VIRTUAL_SCREEN_WIDTH + MISSILE_WIDTH)) ||
167
                                (spriteInstance.param.x < (-MISSILE_WIDTH)) ||
168
                                (spriteInstance.param.y > (GameConsts.VIRTUAL_SCREEN_HEIGHT+ MISSILE_HEIGHT)) ||
169
                                (spriteInstance.param.y < (-MISSILE_HEIGHT)))
886 chris 170
                        {
171
                                // out of screen -> make un alive
945 chris 172
                                setAlive(false);
886 chris 173
                        }
174
                }
175
 
176
                public void render()
177
                {
887 chris 178
                        float t = (lifeTime % MISSILE_ROTATION_DURATION) / MISSILE_ROTATION_DURATION;
179
                        int frame = MathUtil.clamp((int)(t * NUM_MISSILE_FRAMES), 0, NUM_MISSILE_FRAMES-1);
945 chris 180
                        spriteInstance.renderFrame(frame);
947 chris 181
 
887 chris 182
                        float rocketPulse = MathUtil.sin(lifeTime * 2000.0f) * 0.3f;
183
 
890 chris 184
                        if (mPhase == MissilePhase.PHASE_HOAMING)
185
                        {
945 chris 186
                                mMissileFrames[ROCKET_FIRE_FRAME].param.x = spriteInstance.param.x;
187
                                mMissileFrames[ROCKET_FIRE_FRAME].param.y = spriteInstance.param.y;
899 chris 188
                                mMissileFrames[ROCKET_FIRE_FRAME].param.w = ROCKET_FIRE_SIZE + ROCKET_FIRE_SIZE_VARIANCE * rocketPulse;
189
                                mMissileFrames[ROCKET_FIRE_FRAME].param.h = ROCKET_FIRE_SIZE;
190
                                mMissileFrames[ROCKET_FIRE_FRAME].param.pivotX = MISSILE_WIDTH + mMissileFrames[ROCKET_FIRE_FRAME].param.w - ROCKET_FIRE_OFFSET;
191
                                mMissileFrames[ROCKET_FIRE_FRAME].param.pivotY = mMissileFrames[ROCKET_FIRE_FRAME].param.h/2;
192
                                mMissileFrames[ROCKET_FIRE_FRAME].param.angle = mCurrentAngle;                 
890 chris 193
                                mMissileFrames[ROCKET_FIRE_FRAME].render();
194
                        }
886 chris 195
                }
945 chris 196
 
197
                @Override
198
                public void processHit(Enemy enemy)
199
                {
200
                        // spawn impact effect
201
                        enemy.hit(getDamage());
202
                        setAlive(false);
203
                }
204
 
205
                @Override
206
                public Shape getShape()
207
                {
208
                        return spriteInstance.getShape();
209
                }
210
 
211
                @Override
212
                public Matrix4 getShapeTransform()
213
                {
214
                        return spriteInstance.param.getTransform();
215
                }
950 chris 216
 
217
                @Override
218
                public AABoundingBox getBounds()
219
                {
220
                        return spriteInstance.param.getBoundingBox();
221
                }
886 chris 222
        }
223
 
224
 
225
        // Fields===========================================================================================
226
 
227
        private Missile mMissiles[] = new Missile[MAX_MISSILES];
228
 
229
        private AtlasSprite mMissileSprite = null;
915 chris 230
        private AtlasSpriteFrame mMissileFrames[] = null;
890 chris 231
 
945 chris 232
        private Shape mMissileShape = null;
233
 
890 chris 234
        private Sound mRocketFireSfx = null;
886 chris 235
 
236
        // Methods==========================================================================================
237
 
238
        public PowerUpMissile(GameLogic gameLogic)
239
        {
240
                super(gameLogic);
241
                mMissileSprite = new AtlasSprite(getGraphics(), "data/textures/missile.png", "data/textures/missile.txt");
242
        }
243
 
244
        @Override
245
        public void initAsync()
246
        {
247
                mMissileSprite.initAsync();
248
        }
249
 
250
        @Override
251
        public void init()
252
        {
945 chris 253
                mMissileShape = ShapeUtil.createShapeFromFile("data/textures/missile.shape");
254
 
890 chris 255
                mRocketFireSfx = getAudio().newManagedSound("data/sounds/fire_rocket.wav");
256
 
886 chris 257
                mMissileSprite.init();
258
                mMissileFrames = mMissileSprite.createSpriteInstances();
259
 
260
                for (int i = 0; i < MAX_MISSILES; i++)
261
                {
262
                        mMissiles[i] = new Missile(i);
263
                }
264
        }
265
 
266
        @Override
267
        public void exit()
268
        {
269
                mMissileFrames = null;
270
 
271
                if (mMissileSprite != null)
272
                {
273
                        mMissileSprite.dispose();
274
                        mMissileSprite = null;
275
                }
890 chris 276
 
277
                if (mRocketFireSfx != null)
278
                {
279
                        getAudio().removeManagedSound(mRocketFireSfx);
280
                        mRocketFireSfx = null;
281
                }
886 chris 282
        }
283
 
284
        @Override
285
        public void update(float deltaTime)
286
        {
287
                int i = 0;
288
                while (i < MAX_MISSILES)
289
                {
945 chris 290
                        if (mMissiles[i].isAlive())
886 chris 291
                                mMissiles[i].update(deltaTime);
292
                        i++;
293
                }
294
 
295
        }
296
 
297
        @Override
298
        public void render()
299
        {
300
                int i = 0;
301
                while (i < MAX_MISSILES)
302
                {
945 chris 303
                        if (mMissiles[i].isAlive())
886 chris 304
                                mMissiles[i].render();
305
                        i++;
306
                }
307
        }
308
 
309
        public void launch(float x, float y)
310
        {
311
                // launch one upper, one lower
312
 
313
                for (int i = 0; i < MAX_MISSILES; i++)
314
                {
945 chris 315
                        if (!mMissiles[i].isAlive())
886 chris 316
                        {
317
                                mMissiles[i].launch(x, y);
318
                        }
319
                }
320
        }
321
 
322
        // Getters/Setters==================================================================================
323
 
324
}
325
 
326