diff options
Diffstat (limited to 'core/src/ch')
| -rw-r--r-- | core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java | 203 | 
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(); +    } +} | 
