summaryrefslogtreecommitdiffstats
path: root/core/src/ch/asynk/tankontank/engine/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/ch/asynk/tankontank/engine/gfx')
-rw-r--r--core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java203
1 files changed, 203 insertions, 0 deletions
diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java
new file mode 100644
index 0000000..3ab8642
--- /dev/null
+++ b/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java
@@ -0,0 +1,203 @@
+package ch.asynk.tankontank.engine.gfx.animations;
+
+import java.util.Random;
+
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.Pool;
+
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.tankontank.engine.gfx.Drawable;
+import ch.asynk.tankontank.engine.gfx.Animation;
+
+public class InfantryFireAnimation implements Disposable, Animation, Pool.Poolable
+{
+ class Shot
+ {
+ public TextureRegion fireRegion;
+ public float fire_a;
+ public float fire_x;
+ public float fire_y;
+ public float fire_w;
+ public float fire_dx;
+ public float fire_dy;
+ public float fire_dw;
+
+ public boolean fired;
+ public boolean hit;
+ public boolean completed;
+
+ public float fire_time;
+ public float hit_time;
+ public float end_time;
+
+ public int hit_frame;
+
+ public Shot(TextureRegion region)
+ {
+ this.fireRegion = region;
+ }
+ }
+
+ private static final int SHOT_COUNT = 10;
+ private static final float SHOT_SCATTERING = 40f;
+ private static final float TIME_SCATTERING = 0.6f;
+ private static final float START_DELAY = 0.8f;
+ private static final float SHOT_SPEED = 1000f;
+ private static final float HIT_FRAME_DURATION = 0.07f;
+
+ private Shot[] shots;
+
+ private float elapsed;
+
+ private float volume;
+
+ private static final Pool<InfantryFireAnimation> fireAnimationPool = new Pool<InfantryFireAnimation>() {
+ @Override
+ protected InfantryFireAnimation newObject() {
+ return new InfantryFireAnimation();
+ }
+ };
+
+ public static InfantryFireAnimation get(float volume, float offset, float x0, float y0, float x1, float y1)
+ {
+ InfantryFireAnimation a = fireAnimationPool.obtain();
+ a.set(volume, offset, x0, y0, x1, y1);
+ return a;
+ }
+
+ public InfantryFireAnimation()
+ {
+ this.shots = new Shot[SHOT_COUNT];
+ for (int i = 0; i < shots.length; i++)
+ shots[i] = new Shot(new TextureRegion(FireAnimation.infantryFire.frames[0]));
+ }
+
+ private void set(float volume, float offset, float _x0, float _y0, float _x1, float _y1)
+ {
+ this.volume = volume;
+ this.elapsed = 0f;
+
+ for (Shot shot : shots) {
+ // fire geometry
+ float x0 = _x0;
+ float y0 = (_y0 - (FireAnimation.infantryFire.height / 2.0f));
+ float x1 = (_x1 + ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)));
+ float y1 = (_y1 + ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)));
+
+ double r = Math.atan2((y0 - y1), (x0 - x1));
+ float xadj = (float) (Math.cos(r) * offset);
+ float yadj = (float) (Math.sin(r) * offset);
+ x0 -= xadj;
+ y0 -= yadj;
+
+ float a = (float) Math.toDegrees(r);
+ float dx = (x1 - x0);
+ float dy = (y1 - y0);
+ float w = (float) Math.sqrt((dx * dx) + (dy * dy));
+
+ // timing
+ float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING);
+ float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED));
+ float hit_duration = (FireAnimation.infantryFire.rows * HIT_FRAME_DURATION);
+
+ shot.fired = false;
+ shot.fire_time = delay;
+ shot.hit_time = (shot.fire_time + fire_duration);
+ shot.end_time = (shot.hit_time + hit_duration);
+
+ // fire vars
+ shot.fire_a = a;
+ shot.fire_x = x0;
+ shot.fire_y = y0;
+ shot.fire_w = 0;
+ shot.fire_dx = (dx / fire_duration);
+ shot.fire_dy = (dy / fire_duration);
+ shot.fire_dw = (w / fire_duration);
+ shot.hit_frame = 0;
+ }
+ }
+
+ @Override
+ public void reset()
+ {
+ }
+
+ @Override
+ public void dispose()
+ {
+ fireAnimationPool.free(this);
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ elapsed += delta;
+
+ boolean completed = true;
+ for (Shot shot : shots) {
+ completed &= shot.completed;
+
+ if (!shot.fired && (elapsed < shot.fire_time))
+ continue;
+
+ if (!shot.fired) {
+ shot.fired = true;
+ FireAnimation.infantryFireSndPlay(volume);
+ }
+
+ if (!shot.hit && (elapsed < shot.hit_time)) {
+ shot.fire_w += (shot.fire_dw * delta);
+ shot.fire_x += (shot.fire_dx * delta);
+ shot.fire_y += (shot.fire_dy * delta);
+ shot.fireRegion.setRegionWidth((int) shot.fire_w);
+ continue;
+ }
+
+ if (!shot.hit)
+ shot.hit = true;
+
+ if (elapsed < shot.end_time) {
+ int frame = (int) ((elapsed - shot.hit_time) / HIT_FRAME_DURATION);
+ if (frame != shot.hit_frame) {
+ shot.hit_frame = frame;
+ shot.fireRegion.setRegion(FireAnimation.infantryFire.frames[shot.hit_frame]);
+ shot.fireRegion.setRegionWidth((int) shot.fire_w);
+ }
+ continue;
+ } else
+ shot.completed = true;
+ }
+
+ return completed;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ for (Shot shot : shots) {
+ if (shot.fired)
+ batch.draw(shot.fireRegion, shot.fire_x, shot.fire_y, 0, 0,
+ shot.fireRegion.getRegionWidth(), shot.fireRegion.getRegionHeight(), 1f, 1f, shot.fire_a);
+ }
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ // debugShapes.end();
+ // debugShapes.begin(ShapeRenderer.ShapeType.Line);
+ // debugShapes.identity();
+ // debugShapes.translate(fire_x, fire_y, 0);
+ // debugShapes.rotate(0, 0, 1, fire_a);
+ // debugShapes.translate(-fire_x, -fire_y, 0);
+ // debugShapes.rect(fire_x, fire_y, fire_w, FireAnimation.infantryFire.height);
+ // debugShapes.end();
+ // debugShapes.begin(ShapeRenderer.ShapeType.Line);
+ // debugShapes.identity();
+ }
+}