summaryrefslogtreecommitdiffstats
path: root/core/src/ch/asynk/rustanddust/engine/gfx
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2015-07-19 13:20:33 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2015-07-19 13:20:33 +0200
commitde0463bcf0f76ef8b07f2719679c9e0d72745c5d (patch)
tree9a33df947ceeea16a3e20b400585b1d3c304e77e /core/src/ch/asynk/rustanddust/engine/gfx
parente66f9f2a61d3dab4545e996046486de0d44e2901 (diff)
downloadRustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.zip
RustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.tar.gz
welcome RustAndDust
Diffstat (limited to 'core/src/ch/asynk/rustanddust/engine/gfx')
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/Animation.java8
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/Drawable.java10
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/Moveable.java16
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/StackedImages.java99
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/AnimationSequence.java76
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/DestroyAnimation.java62
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/DiceAnimation.java141
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/FireAnimation.java87
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/InfantryFireAnimation.java222
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/MoveToAnimation.java126
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/PromoteAnimation.java98
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/RunnableAnimation.java67
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/SoundAnimation.java83
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/SpriteAnimation.java76
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/Sprites.java38
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/TankFireAnimation.java196
-rw-r--r--core/src/ch/asynk/rustanddust/engine/gfx/animations/TimedAnimation.java48
17 files changed, 1453 insertions, 0 deletions
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/Animation.java b/core/src/ch/asynk/rustanddust/engine/gfx/Animation.java
new file mode 100644
index 0000000..eb973de
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/Animation.java
@@ -0,0 +1,8 @@
+package ch.asynk.rustanddust.engine.gfx;
+
+import com.badlogic.gdx.utils.Disposable;
+
+public interface Animation extends Disposable, Drawable
+{
+ public boolean animate(float delta);
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/Drawable.java b/core/src/ch/asynk/rustanddust/engine/gfx/Drawable.java
new file mode 100644
index 0000000..d405faa
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/Drawable.java
@@ -0,0 +1,10 @@
+package ch.asynk.rustanddust.engine.gfx;
+
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+public interface Drawable
+{
+ public void draw(Batch batch);
+ public void drawDebug(ShapeRenderer debugShapes);
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/Moveable.java b/core/src/ch/asynk/rustanddust/engine/gfx/Moveable.java
new file mode 100644
index 0000000..e8790ab
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/Moveable.java
@@ -0,0 +1,16 @@
+package ch.asynk.rustanddust.engine.gfx;
+
+import ch.asynk.rustanddust.engine.Faction;
+
+public interface Moveable extends Drawable
+{
+ public void setAlpha(float alpha);
+ public float getX();
+ public float getY();
+ public float getWidth();
+ public float getHeight();
+ public float getRotation();
+ public void setPosition(float x, float y);
+ public void setPosition(float x, float y, float r);
+ public Faction getFaction();
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/StackedImages.java b/core/src/ch/asynk/rustanddust/engine/gfx/StackedImages.java
new file mode 100644
index 0000000..6d4fd1f
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/StackedImages.java
@@ -0,0 +1,99 @@
+package ch.asynk.rustanddust.engine.gfx;
+
+import com.badlogic.gdx.utils.Disposable;
+
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.badlogic.gdx.utils.Array;
+
+public class StackedImages implements Drawable, Disposable
+{
+ private boolean enabled[];
+ private Array<Sprite> sprites;
+
+ public StackedImages(TextureAtlas atlas)
+ {
+ this.sprites = atlas.createSprites();
+ this.enabled = new boolean[sprites.size];
+ }
+
+ @Override
+ public void dispose()
+ {
+ }
+
+ public void disableAll()
+ {
+ for (int i = 0; i < sprites.size; i++)
+ enabled[i] = false;
+ }
+
+ public void enable(int i, boolean enable)
+ {
+ enabled[i] = enable;
+ }
+
+ public boolean isEnabled(int i)
+ {
+ return enabled[i];
+ }
+
+ public boolean isEnabled()
+ {
+ for (int i = 0; i < sprites.size; i++)
+ if (enabled[i]) return true;
+ return false;
+ }
+
+ public void setAlpha(float alpha)
+ {
+ for (int i = 0, n = sprites.size; i < n; i++)
+ sprites.get(i).setAlpha(alpha);
+ }
+
+ public void rotate(int i, float r)
+ {
+ sprites.get(i).setRotation(r);
+ }
+
+ public void setRotation(float r)
+ {
+ for (int i = 0, n = sprites.size; i < n; i++)
+ sprites.get(i).setRotation(r);
+ }
+
+ public void translate(float dx, float dy)
+ {
+ for (int i = 0, n = sprites.size; i < n; i++)
+ sprites.get(i).translate(dx, dy);
+ }
+
+ public void centerOn(float cx, float cy)
+ {
+ for (int i = 0, n = sprites.size; i < n; i++) {
+ float x = (cx - (sprites.get(i).getWidth() / 2f));
+ float y = (cy - (sprites.get(i).getHeight() / 2f));
+ sprites.get(i).setPosition(x, y);
+ }
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ for (int i = 0, n = sprites.size; i < n; i++) {
+ if (enabled[i])
+ sprites.get(i).draw(batch);
+ }
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer shapes)
+ {
+ Sprite sprite = sprites.get(0);
+ float w = sprite.getWidth();
+ float h = sprite.getHeight();
+ shapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation());
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/AnimationSequence.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/AnimationSequence.java
new file mode 100644
index 0000000..fdd1e80
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/AnimationSequence.java
@@ -0,0 +1,76 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.util.ArrayList;
+
+import com.badlogic.gdx.utils.Pool;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class AnimationSequence implements Animation, Pool.Poolable
+{
+ private ArrayList<Animation> animations;
+
+ private static final Pool<AnimationSequence> animationSequencePool = new Pool<AnimationSequence>() {
+ @Override
+ protected AnimationSequence newObject() {
+ return new AnimationSequence();
+ }
+ };
+
+ public static AnimationSequence get(int capacity)
+ {
+ AnimationSequence seq = animationSequencePool.obtain();
+ if (seq.animations == null)
+ seq.animations = new ArrayList<Animation>(capacity);
+ else
+ seq.animations.ensureCapacity(capacity);
+
+ return seq;
+ }
+
+ @Override
+ public void reset()
+ {
+ for (int i = 0, n = animations.size(); i < n; i++)
+ animations.get(i).dispose();
+ animations.clear();
+ }
+
+ @Override
+ public void dispose()
+ {
+ animationSequencePool.free(this);
+ }
+
+ public void addAnimation(Animation animation)
+ {
+ animations.add(animation);
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ if(animations.isEmpty()) return true;
+
+ Animation animation = animations.get(0);
+ if (animation.animate(delta)) {
+ animations.remove(0);
+ }
+
+ return (animations.isEmpty());
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ animations.get(0).draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ animations.get(0).drawDebug(debugShapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/DestroyAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/DestroyAnimation.java
new file mode 100644
index 0000000..d1fc1bb
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/DestroyAnimation.java
@@ -0,0 +1,62 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Moveable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class DestroyAnimation implements Disposable, Animation
+{
+ private static final float DELAY = 1.5f;
+ private static final float DURATION = 1.5f;
+
+ private Moveable moveable;
+ private float x;
+ private float y;
+ private int alphaP;
+ private float elapsed;
+
+ @Override
+ public void dispose()
+ {
+ }
+
+ public void set(float duration, Moveable moveable)
+ {
+ this.moveable = moveable;
+ this.alphaP = 0;
+ this.elapsed = 0f;
+ this.x = (moveable.getX() + (moveable.getWidth() / 2f));
+ this.y = (moveable.getY() + (moveable.getHeight() / 2f));
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ elapsed += delta;
+ if (elapsed < DELAY)
+ return false;
+
+ int a = (int) (((elapsed - DELAY) / DURATION) * 10);
+ if (a != alphaP) {
+ alphaP = a;
+ moveable.setAlpha(1f - (alphaP / 10f));
+ }
+
+ return (elapsed >= (DELAY + DURATION));
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ moveable.draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ moveable.drawDebug(debugShapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/DiceAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/DiceAnimation.java
new file mode 100644
index 0000000..1a0a3bb
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/DiceAnimation.java
@@ -0,0 +1,141 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.util.Random;
+
+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.rustanddust.engine.gfx.Drawable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class DiceAnimation implements Animation, Drawable
+{
+ private static final float DURATION = 0.7f;
+ private static final float DURATION_SCATTERING = 0.5f;
+ private static final int DICE_DIMENSION = 24;
+
+ private static Random random = new Random();
+ private static Sprites dice;
+ private static Sound sound;
+ private static double sndId;
+ private static float volume;
+ private static int[][] rolls = new int[][]{
+ { 25, 40, 55, 70, 85, 100, 115, 99, 83, 67, 51, 36, 37, 52, 67, 66, 65, 64 },
+ { 58, 74, 59, 60, 45, 62, 78, 94, 109, 108, 123, 106, 89, 71, 70, 69, 68 },
+ { 106, 121, 120, 103, 86, 70, 54, 37, 20, 19, 18, 34, 50, 51, 52, 69, 86, 103, 119, 128 },
+ { 95, 79, 93, 92, 91, 90, 104, 103, 102, 85, 84, 67, 66, 65, 49, 32, 16, 0 },
+ { 22, 39, 56, 73, 90, 107, 124, 128, 113, 98, 83, 68, 53, 38, 23, 0, 25, 42, 59, 76 },
+ { 79, 78, 61, 76, 91, 106, 121, 120, 119, 102, 101, 84, 68, 52, 37, 38, 39, 40, 41, 58, 75, 74, 73, 72 },
+ };
+
+ private float x;
+ private float y;
+ private int frame;
+ private int[] roll;
+ private float elapsed;
+ private float duration;
+ // public boolean stop;
+
+ public static void init(Texture texture, int cols, int rows, Sound s)
+ {
+ dice = new Sprites(texture, cols, rows);
+ sound = s;
+ sndId = -1;
+ }
+
+ public static void initSound(float v)
+ {
+ sndId = -1;
+ volume = v;
+ }
+
+ public static void free()
+ {
+ sound.dispose();
+ dice.dispose();
+ }
+
+ public void translate(float dx, float dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ public float getX()
+ {
+ return x;
+ }
+
+ public float getY()
+ {
+ return y;
+ }
+
+ public int getWidth()
+ {
+ return DICE_DIMENSION;
+ }
+
+ public int getHeight()
+ {
+ return DICE_DIMENSION;
+ }
+
+ public void setPosition(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public void set(int result)
+ {
+ this.frame = 0;
+ this.elapsed = 0f;
+ this.roll = rolls[result - 1];
+ this.duration = DURATION + (DURATION_SCATTERING * random.nextFloat());
+ // this.stop = false;
+ }
+
+ public boolean isDone()
+ {
+ return (elapsed >= duration);
+ }
+
+ @Override
+ public void dispose()
+ {
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ // if (stop)
+ // return true;
+ elapsed += delta;
+ if (elapsed < duration) {
+ int idx = (int) (roll.length * elapsed / duration);
+ if (idx >= roll.length)
+ idx = (roll.length -1);
+ frame = roll[idx];
+ }
+ if (sndId == -1)
+ sndId = sound.play(volume);
+
+ return false;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ batch.draw(dice.frames[frame], x, y, DICE_DIMENSION, DICE_DIMENSION);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ debugShapes.rect(x, y, dice.frames[frame].getRegionWidth(), dice.frames[frame].getRegionHeight());
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/FireAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/FireAnimation.java
new file mode 100644
index 0000000..5835525
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/FireAnimation.java
@@ -0,0 +1,87 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.util.Random;
+
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Texture;
+
+public class FireAnimation
+{
+ public static Random random = new Random();
+
+ public static Sprites infantryFire;
+ public static Sprites tankFire;
+ public static Sprites explosion;
+
+ public static Sound infantryFireSnd;
+ public static Sound tankFireSnd;
+ public static Sound tankFireSndLong;
+ public static Sound explosionSnd;
+ public static Sound explosionSndLong;
+
+ public static double infantryFireSndLongId;
+ public static double tankFireSndLongId;
+ public static double explosionSndLongId;
+
+ public static void init(
+ Texture infantryFireT, int iCols, int iRows,
+ Texture tankFireT, int sCols, int sRows,
+ Texture explosionT, int eCols, int eRows,
+ Sound infantryFireS,
+ Sound tankFireS,
+ Sound tankFireLongS,
+ Sound explosionS,
+ Sound explosionLongS)
+ {
+ infantryFire = new Sprites(infantryFireT, iCols, iRows);
+ tankFire = new Sprites(tankFireT, sCols, sRows);
+ explosion = new Sprites(explosionT, eCols, eRows);
+ infantryFireSnd = infantryFireS;
+ tankFireSnd = tankFireS;
+ tankFireSndLong = tankFireLongS;
+ explosionSnd = explosionS;
+ explosionSndLong = explosionLongS;
+
+ reset();
+ }
+
+ public static void reset()
+ {
+ infantryFireSndLongId = -1;
+ tankFireSndLongId = -1;
+ explosionSndLongId = -1;
+ }
+
+ public static void free()
+ {
+ tankFire.dispose();
+ explosion.dispose();
+
+ tankFireSnd.dispose();
+ tankFireSndLong.dispose();
+ explosionSnd.dispose();
+ explosionSndLong.dispose();
+ }
+
+ public static void infantryFireSndPlay(float volume)
+ {
+ if (infantryFireSndLongId == -1)
+ infantryFireSndLongId = infantryFireSnd.play(volume);
+ }
+
+ public static void tankFireSndPlay(float volume)
+ {
+ if (tankFireSndLongId == -1)
+ tankFireSndLongId = tankFireSndLong.play(volume);
+ else
+ tankFireSnd.play(volume);
+ }
+
+ public static void explosionSndPlay(float volume)
+ {
+ if (explosionSndLongId == -1)
+ explosionSndLongId = explosionSndLong.play(volume);
+ else
+ explosionSnd.play(volume);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/InfantryFireAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/InfantryFireAnimation.java
new file mode 100644
index 0000000..233305a
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/InfantryFireAnimation.java
@@ -0,0 +1,222 @@
+package ch.asynk.rustanddust.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.rustanddust.engine.gfx.Drawable;
+import ch.asynk.rustanddust.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;
+ }
+
+ public void set(float delay, float x0, float y0, float x1, float y1, float w, float a)
+ {
+ float dx = (x1 - x0);
+ float dy = (y1 - y0);
+
+ // timing
+ float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED));
+ float hit_duration = (FireAnimation.infantryFire.rows * HIT_FRAME_DURATION);
+
+ this.fired = false;
+ this.fire_time = delay;
+ this.hit_time = (this.fire_time + fire_duration);
+ this.end_time = (this.hit_time + hit_duration);
+
+ // fire vars
+ this.fire_a = a;
+ this.fire_x = x0;
+ this.fire_y = y0;
+ this.fire_w = 0;
+ this.fire_dx = (dx / fire_duration);
+ this.fire_dy = (dy / fire_duration);
+ this.fire_dw = (w / fire_duration);
+ this.hit_frame = 0;
+ }
+
+ public boolean animate(float delta)
+ {
+ if (!fired && (elapsed < fire_time))
+ return false;
+
+ if (!fired) {
+ fired = true;
+ FireAnimation.infantryFireSndPlay(volume);
+ }
+
+ if (!hit && (elapsed < hit_time)) {
+ fire_w += (fire_dw * delta);
+ fire_x += (fire_dx * delta);
+ fire_y += (fire_dy * delta);
+ fireRegion.setRegionWidth((int) fire_w);
+ return false;
+ }
+
+ if (!hit)
+ hit = true;
+
+ if (elapsed < end_time) {
+ int frame = (int) ((elapsed - hit_time) / HIT_FRAME_DURATION);
+ if (frame != hit_frame) {
+ hit_frame = frame;
+ fireRegion.setRegion(FireAnimation.infantryFire.frames[hit_frame]);
+ fireRegion.setRegionWidth((int) fire_w);
+ }
+ return false;
+ }
+
+ completed = true;
+ return true;
+ }
+
+ public void draw(Batch batch)
+ {
+ if (fired && !completed)
+ batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a);
+ }
+ }
+
+ private static final int SHOT_COUNT = 19;
+ private static final float SHOT_DELAY = (1.6f / SHOT_COUNT);
+ 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.05f;
+
+ 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 x0, float y0, float x1, float y1, float halfWidth)
+ {
+ InfantryFireAnimation a = fireAnimationPool.obtain();
+ a.set(volume, x0, y0, x1, y1, halfWidth);
+ 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 x0, float y0, float x1, float y1, float halfWidth)
+ {
+ this.volume = volume;
+ this.elapsed = 0f;
+
+ float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING);
+
+ y0 -= (FireAnimation.infantryFire.height / 2.0f);
+ double r = Math.atan2((y0 - y1), (x0 - x1));
+ x0 -= ((float) (Math.cos(r) * halfWidth));
+ y0 -= ((float) (Math.sin(r) * halfWidth));
+
+ float dx = (x1 - x0);
+ float dy = (y1 - y0);
+ float w = (float) Math.sqrt((dx * dx) + (dy * dy));
+ double dr = (Math.atan2(halfWidth, w) / 2f);
+
+ double a = (r + (dr / 2f));
+ double da = (dr / (float) SHOT_COUNT);
+
+ for (Shot shot : shots) {
+ float x = (float) (x0 - (Math.cos(a) * w));
+ float y = (float) (y0 - (Math.sin(a) * w));
+
+ shot.set(delay, x0, y0, x, y, w, (float) Math.toDegrees(a));
+
+ delay += SHOT_DELAY;
+ a -= 2 * (da * FireAnimation.random.nextFloat());
+ }
+ }
+
+ @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.animate(delta);
+
+ return completed;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ for (Shot shot : shots)
+ shot.draw(batch);
+ }
+
+ @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();
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/MoveToAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/MoveToAnimation.java
new file mode 100644
index 0000000..f6380bc
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/MoveToAnimation.java
@@ -0,0 +1,126 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.utils.Pool;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Moveable;
+
+public class MoveToAnimation extends TimedAnimation
+{
+ public interface MoveToAnimationCb {
+ void moveToAnimationLeave(Moveable moveable, float x, float y, float r);
+ void moveToAnimationEnter(Moveable moveable, float x, float y, float r);
+ void moveToAnimationDone(Moveable moveable, float x, float y, float r);
+ }
+
+ private Moveable moveable;
+ private float fromX;
+ private float fromY;
+ private float fromR;
+ private float toX;
+ private float toY;
+ private float toR;
+ private float rDelta;
+ private boolean notified;
+ private MoveToAnimationCb cb;
+
+ private static final Pool<MoveToAnimation> moveToAnimationPool = new Pool<MoveToAnimation>() {
+ @Override
+ protected MoveToAnimation newObject() {
+ return new MoveToAnimation();
+ }
+ };
+
+ public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration)
+ {
+ return get(moveable, v.x, v.y, v.z, duration);
+ }
+
+ public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration, MoveToAnimationCb cb)
+ {
+ return get(moveable, v.x, v.y, v.z, duration, cb);
+ }
+
+ public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration)
+ {
+ return get(moveable, x, y, r, duration, null);
+ }
+
+ public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration, MoveToAnimationCb cb)
+ {
+ MoveToAnimation a = moveToAnimationPool.obtain();
+
+ a.moveable = moveable;
+ a.toX = x;
+ a.toY = y;
+ a.toR = r;
+ a.duration = duration;
+ a.cb = cb;
+ a.rDelta = 0;
+ a.notified = false;
+
+ return a;
+ }
+
+ @Override
+ public void dispose()
+ {
+ moveToAnimationPool.free(this);
+ }
+
+ @Override
+ protected void begin()
+ {
+ fromX = moveable.getX();
+ fromY = moveable.getY();
+ fromR = moveable.getRotation();
+ notified = ((fromX == toX) && (fromY == toY));
+
+ if (Math.abs(toR - fromR) <= 180.f)
+ rDelta = (toR - fromR);
+ else {
+ if (toR > fromR)
+ rDelta = (toR - 360 - fromR);
+ else
+ rDelta = (toR + 360 - fromR);
+ }
+ }
+
+ @Override
+ protected void end()
+ {
+ if (cb != null)
+ cb.moveToAnimationDone(moveable, (toX + (moveable.getWidth() / 2)), (toY + (moveable.getHeight() / 2)), toR);
+ dispose();
+ }
+
+ @Override
+ protected void update(float percent)
+ {
+ if ((cb != null) && !notified && (percent >= 0.5)) {
+ float dw = (moveable.getWidth() / 2);
+ float dh = (moveable.getHeight() / 2);
+ cb.moveToAnimationLeave(moveable, (fromX + dw), (fromY + dh), fromR);
+ cb.moveToAnimationEnter(moveable, (toX + dw), (toY + dh), toR);
+ notified = true;
+ }
+ if (percent == 1f)
+ moveable.setPosition(toX, toY, (int) toR);
+ else
+ moveable.setPosition(fromX + ((toX - fromX) * percent), fromY + ((toY - fromY) * percent), (fromR + (rDelta * percent)));
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ moveable.draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ moveable.drawDebug(debugShapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/PromoteAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/PromoteAnimation.java
new file mode 100644
index 0000000..24eac18
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/PromoteAnimation.java
@@ -0,0 +1,98 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.lang.Math;
+
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Drawable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class PromoteAnimation implements Animation, Drawable
+{
+ private static PromoteAnimation instance = new PromoteAnimation();
+
+ private static final float DURATION = 0.3f;
+ private static final float MAX_SCALE = 2f;
+
+ private static Sound usSound;
+ private static Sound geSound;
+ private static Sound snd;
+ private static TextureRegion region;
+
+ private float x0;
+ private float y0;
+ private float x;
+ private float y;
+ private float scale;
+ private float step;
+ private float volume;
+ private float elapsed;
+
+ public static void init(TextureAtlas atlas, Sound usSnd, Sound geSnd)
+ {
+ region = atlas.findRegion("stars");
+ usSound = usSnd;
+ geSound = geSnd;
+ }
+
+ public static void free()
+ {
+ }
+
+ protected void PromoteAnimation()
+ {
+ }
+
+ public static PromoteAnimation get(boolean us, float x, float y, float v)
+ {
+ x = (x - (region.getRegionWidth() / 2.0f));
+ y = (y - (region.getRegionHeight() / 2.0f));
+
+ instance.volume = v;
+ instance.x0 = x;
+ instance.y0 = y;
+ instance.scale = 0f;
+ instance.elapsed = 0f;
+ snd = (us ? usSound : geSound);
+
+ return instance;
+ }
+
+ @Override
+ public void dispose()
+ {
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ elapsed += delta;
+ if (elapsed >= DURATION) {
+ snd.play(volume);
+ return true;
+ }
+
+ float s = MAX_SCALE * (float) Math.sin(Math.PI / DURATION * elapsed);
+ scale = 1f + s;
+ x = x0 - ((region.getRegionWidth() * scale) / 4f);
+ y = y0 - ((region.getRegionHeight() * scale) / 4f);
+
+ return false;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ batch.draw(region, x, y, 0, 0, region.getRegionWidth(), region.getRegionHeight(), scale, scale, 0f);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ debugShapes.rect(x, y, region.getRegionWidth(), region.getRegionHeight());
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/RunnableAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/RunnableAnimation.java
new file mode 100644
index 0000000..231f859
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/RunnableAnimation.java
@@ -0,0 +1,67 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.utils.Pool;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Moveable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class RunnableAnimation implements Animation, Pool.Poolable
+{
+ private Runnable runnable;
+ private Moveable moveable;
+ private boolean ran;
+
+ private static final Pool<RunnableAnimation> runnableAnimationPool = new Pool<RunnableAnimation>() {
+ @Override
+ protected RunnableAnimation newObject() {
+ return new RunnableAnimation();
+ }
+ };
+
+ public static RunnableAnimation get(Moveable moveable, Runnable runnable)
+ {
+ RunnableAnimation a = runnableAnimationPool.obtain();
+ a.runnable = runnable;
+ a.moveable = moveable;
+ return a;
+ }
+
+ @Override
+ public void reset()
+ {
+ ran = false;
+ }
+
+ @Override
+ public void dispose()
+ {
+ runnableAnimationPool.free(this);
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ if (ran) return true;
+
+ runnable.run();
+ runnable = null;
+ ran = true;
+ dispose();
+
+ return true;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ moveable.draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ moveable.drawDebug(debugShapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/SoundAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/SoundAnimation.java
new file mode 100644
index 0000000..7e83f38
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/SoundAnimation.java
@@ -0,0 +1,83 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.utils.Pool;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+public class SoundAnimation extends TimedAnimation
+{
+ public enum Action
+ {
+ FADE_IN,
+ FADE_OUT
+ };
+
+ private Sound sound;
+ private long soundId;
+ private Action action;
+ private float volume;
+
+ private static final Pool<SoundAnimation> soundAnimationPool = new Pool<SoundAnimation>() {
+ @Override
+ protected SoundAnimation newObject() {
+ return new SoundAnimation();
+ }
+ };
+
+ public static SoundAnimation get(Action action, Sound sound, long soundId, float volume, float duration)
+ {
+ SoundAnimation a = soundAnimationPool.obtain();
+
+ a.action = action;
+ a.sound = sound;
+ a.soundId = soundId;
+ a.volume = volume;
+ a.duration = duration;
+
+ return a;
+ }
+
+ @Override
+ public void dispose()
+ {
+ soundAnimationPool.free(this);
+ }
+
+ @Override
+ protected void begin()
+ {
+ }
+
+ @Override
+ protected void end()
+ {
+ dispose();
+ }
+
+ @Override
+ protected void update(float percent)
+ {
+ float v;
+ switch(action) {
+ case FADE_IN:
+ v = ( volume * percent);
+ sound.setVolume(soundId, v);
+ break;
+ case FADE_OUT:
+ v = (volume - ( volume * percent));
+ sound.setVolume(soundId, v);
+ break;
+ }
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/SpriteAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/SpriteAnimation.java
new file mode 100644
index 0000000..4d10210
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/SpriteAnimation.java
@@ -0,0 +1,76 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.util.Random;
+
+import com.badlogic.gdx.utils.Disposable;
+
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Drawable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class SpriteAnimation implements Disposable, Animation
+{
+ private static Random random = new Random();
+ private Sprites sprites;
+ private float duration;
+ private float frameDuration;
+ private float elapsed;
+ private float x0;
+ private float y0;
+ private float x1;
+ private float y1;
+ private int randFreq;
+
+ public SpriteAnimation(Texture texture, int cols, int rows, int randFreq)
+ {
+ this.sprites = new Sprites(texture, cols, rows);
+ this.randFreq = randFreq;
+ }
+
+ @Override
+ public void dispose()
+ {
+ sprites.dispose();
+ }
+
+ public void init(float duration, float x, float y)
+ {
+ this.duration = duration;
+ this.frameDuration = (duration / (float) sprites.frames.length);
+ this.x0 = x - (sprites.width / 2f);
+ this.y0 = y - (sprites.height / 2f);
+ this.elapsed = 0f;
+ randPos();
+ }
+
+ private void randPos()
+ {
+ this.x1 = this.x0 + (random.nextInt(sprites.width) - (sprites.width / 2));
+ this.y1 = this.y0 + (random.nextInt(sprites.height) - (sprites.height / 2));
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ elapsed += delta;
+ return (elapsed >= duration);
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ int n = (((int)(elapsed / frameDuration)) % sprites.frames.length);
+ if ((n > 0) && (n % randFreq) == 0)
+ randPos();
+ batch.draw(sprites.frames[n], x1, y1);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/Sprites.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/Sprites.java
new file mode 100644
index 0000000..2d2a0c1
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/Sprites.java
@@ -0,0 +1,38 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+
+public class Sprites implements Disposable
+{
+ public Texture texture;
+ public TextureRegion[] frames;
+ public final int width;
+ public final int height;
+ public final int cols;
+ public final int rows;
+
+ public Sprites(Texture texture, int cols, int rows)
+ {
+ this.cols = cols;
+ this.rows = rows;
+ this.width = (texture.getWidth() / cols);
+ this.height = (texture.getHeight() / rows);
+ this.texture = texture;
+ TextureRegion[][] tmp = TextureRegion.split(texture, width, height);
+ frames = new TextureRegion[cols * rows];
+ int idx = 0;
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ frames[idx++] = tmp[i][j];
+ }
+ }
+ }
+
+ @Override
+ public void dispose()
+ {
+ texture.dispose();
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/TankFireAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/TankFireAnimation.java
new file mode 100644
index 0000000..82a87fd
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/TankFireAnimation.java
@@ -0,0 +1,196 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import java.util.Random;
+
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.Pool;
+
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Drawable;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public class TankFireAnimation implements Disposable, Animation, Pool.Poolable
+{
+ private static final float SHOT_SCATTERING = 60f;
+ private static final float TIME_SCATTERING = 0.6f;
+ private static final float START_DELAY = 0.8f;
+ private static final float SHOT_SPEED = 900f;
+ private static final float EXPLOSION_FRAME_DURATION = 0.07f;
+
+ private TextureRegion fireRegion;
+ private float fire_a;
+ private float fire_x;
+ private float fire_y;
+ private float fire_w;
+ private float fire_dx;
+ private float fire_dy;
+ private float fire_dw;
+
+ private float smoke_df;
+ private int smoke_frame;
+
+ private float explosion_x;
+ private float explosion_y;
+ private float explosion_df;
+ private int explosion_frame;
+
+ private boolean fired;
+ private boolean hit;
+ private float elapsed;
+ private float fire_time;
+ private float hit_time;
+ private float end_time;
+
+ private float volume;
+
+ private static final Pool<TankFireAnimation> fireAnimationPool = new Pool<TankFireAnimation>() {
+ @Override
+ protected TankFireAnimation newObject() {
+ return new TankFireAnimation();
+ }
+ };
+
+ public static TankFireAnimation get(float volume, float x0, float y0, float x1, float y1, float halfWidth)
+ {
+ TankFireAnimation a = fireAnimationPool.obtain();
+ a.set(volume, x0, y0, x1, y1, halfWidth);
+ return a;
+ }
+
+ public TankFireAnimation()
+ {
+ this.fireRegion = new TextureRegion(FireAnimation.tankFire.frames[0]);
+ }
+
+ private void set(float volume, float x0, float y0, float x1, float y1, float halfWidth)
+ {
+ this.fired = false;
+ this.hit = false;
+ this.volume = volume;
+
+ // fire geometry
+ y0 -= (FireAnimation.tankFire.height / 2.0f);
+ x1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f));
+ y1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f));
+
+ double r = Math.atan2((y0 - y1), (x0 - x1));
+ float xadj = (float) (Math.cos(r) * halfWidth);
+ float yadj = (float) (Math.sin(r) * halfWidth);
+ 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 explosion_duration = (FireAnimation.explosion.cols * EXPLOSION_FRAME_DURATION);
+
+ this.elapsed = 0f;
+ this.fire_time = delay;
+ this.hit_time = (fire_time + fire_duration);
+ this.end_time = (hit_time + explosion_duration);
+
+ // fire vars
+ this.fire_a = a;
+ this.fire_x = x0;
+ this.fire_y = y0;
+ this.fire_w = 0;
+ this.fire_dx = (dx / fire_duration);
+ this.fire_dy = (dy / fire_duration);
+ this.fire_dw = (w / fire_duration);
+
+ // smoke var
+ this.smoke_df = (FireAnimation.tankFire.rows / explosion_duration);
+ this.smoke_frame = 0;
+
+ // explosion vars
+ this.explosion_x = (x1 - (FireAnimation.explosion.width / 2.0f));
+ this.explosion_y = (y1 - (FireAnimation.explosion.height / 2.0f));
+ this.explosion_df = (FireAnimation.explosion.cols / explosion_duration);
+ this.explosion_frame = (FireAnimation.random.nextInt(FireAnimation.explosion.rows) * FireAnimation.explosion.cols);
+ }
+
+ @Override
+ public void reset()
+ {
+ }
+
+ @Override
+ public void dispose()
+ {
+ fireAnimationPool.free(this);
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ elapsed += delta;
+
+ if (!fired && (elapsed < fire_time))
+ return false;
+
+ if (!fired) {
+ fired = true;
+ FireAnimation.tankFireSndPlay(volume);
+ }
+
+ if (!hit && (elapsed < hit_time)) {
+ fire_w += (fire_dw * delta);
+ fire_x += (fire_dx * delta);
+ fire_y += (fire_dy * delta);
+ fireRegion.setRegionWidth((int) fire_w);
+ return false;
+ }
+
+ if (!hit) {
+ hit = true;
+ FireAnimation.explosionSndPlay(volume);
+ }
+
+ if (elapsed < end_time) {
+ int frame = (int) ((elapsed - hit_time) * smoke_df);
+ if (frame != smoke_frame) {
+ smoke_frame = frame;
+ fireRegion.setRegion(FireAnimation.tankFire.frames[smoke_frame]);
+ fireRegion.setRegionWidth((int) fire_w);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ if (fired)
+ batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a);
+
+ if (hit) {
+ int frame = (explosion_frame + (int) ((elapsed - hit_time) * explosion_df));
+ batch.draw(FireAnimation.explosion.frames[frame], explosion_x, explosion_y);
+ }
+ }
+
+ @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.tankFire.height);
+ debugShapes.end();
+ debugShapes.begin(ShapeRenderer.ShapeType.Line);
+ debugShapes.identity();
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/engine/gfx/animations/TimedAnimation.java b/core/src/ch/asynk/rustanddust/engine/gfx/animations/TimedAnimation.java
new file mode 100644
index 0000000..0c0d14d
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/engine/gfx/animations/TimedAnimation.java
@@ -0,0 +1,48 @@
+package ch.asynk.rustanddust.engine.gfx.animations;
+
+import com.badlogic.gdx.utils.Pool;
+
+import ch.asynk.rustanddust.engine.gfx.Animation;
+
+public abstract class TimedAnimation implements Animation, Pool.Poolable
+{
+ private float time;
+ private boolean began;
+ private boolean completed;
+ protected float duration;
+
+ abstract protected void begin();
+ abstract protected void end();
+ abstract protected void update(float percent);
+
+ @Override
+ public void reset()
+ {
+ time = 0f;
+ began = false;
+ completed = false;
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ if (completed) return true;
+
+ if (!began) {
+ begin();
+ began = true;
+ }
+
+ time += delta;
+ completed = (time >= duration);
+
+ if (!completed) {
+ update(time / duration);
+ return false;
+ }
+
+ update(1);
+ end();
+ return true;
+ }
+}