diff options
author | Jérémy Zurcher <jeremy@asynk.ch> | 2015-07-19 13:20:33 +0200 |
---|---|---|
committer | Jérémy Zurcher <jeremy@asynk.ch> | 2015-07-19 13:20:33 +0200 |
commit | de0463bcf0f76ef8b07f2719679c9e0d72745c5d (patch) | |
tree | 9a33df947ceeea16a3e20b400585b1d3c304e77e /core/src/ch/asynk/rustanddust/engine/gfx | |
parent | e66f9f2a61d3dab4545e996046486de0d44e2901 (diff) | |
download | RustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.zip RustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.tar.gz |
welcome RustAndDust
Diffstat (limited to 'core/src/ch/asynk/rustanddust/engine/gfx')
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; + } +} |