summaryrefslogtreecommitdiffstats
path: root/core/src/ch/asynk/tankontank/engine/Pawn.java
blob: 7e0f9da39ded74281bc6c5c0848c06202744ac02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
package ch.asynk.tankontank.engine;

import java.util.Iterator;

import com.badlogic.gdx.utils.Disposable;

import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

import ch.asynk.tankontank.engine.gfx.Moveable;
import ch.asynk.tankontank.engine.gfx.StackedImages;
import ch.asynk.tankontank.engine.gfx.animations.MoveToAnimation;
import ch.asynk.tankontank.engine.gfx.animations.RunnableAnimation;
import ch.asynk.tankontank.engine.gfx.animations.AnimationSequence;

public abstract class Pawn implements Moveable, Disposable
{
    public interface PawnType
    {
    }

    public interface PawnId
    {
    }

    private static final float MOVE_TIME = 0.4f;

    private Vector3 position;
    private Vector3 prevPosition;
    private Tile tile;
    private Tile prevTile;
    protected Faction faction;
    protected String descr;
    private Sprite sprite;
    private StackedImages overlays;
    protected Attack attack;
    protected Move move;

    public abstract int getMovementPoints();
    public abstract int getRoadMarchBonus();
    public abstract int getAngleOfAttack();
    public abstract int getFlankSides();
    public abstract int getEngagementRangeFrom(Tile tile);
    public abstract int getDefense(Tile tile);

    public abstract boolean isUnit();
    public abstract boolean isA(PawnId id);
    public abstract boolean isA(PawnType type);
    public abstract boolean isHq();
    public abstract boolean isHqOf(Pawn other);
    public abstract boolean isHardTarget();

    public abstract boolean canMove();
    public abstract boolean canRotate();
    public abstract boolean canEngage();
    public abstract boolean canEngage(Pawn other);
    public abstract boolean canAssistEngagementWithoutLos();

    public abstract void move();
    public abstract void engage();

    public abstract void revertLastMove();

    protected Pawn()
    {
        this.tile = null;
        this.prevTile = null;
        this.position = new Vector3(0f, 0f, 0f);
        this.prevPosition = new Vector3(0f, 0f, 0f);
        this.attack = new Attack(this);
    }

    public Pawn(Faction faction, String name, TextureAtlas pawns, TextureAtlas overlays)
    {
        this();
        this.faction = faction;
        this.descr = descr;
        this.sprite = new Sprite(pawns.findRegion(name));
        this.overlays = new StackedImages(overlays);
    }

    @Override
    public String toString()
    {
        return descr;
    }

    @Override
    public void dispose()
    {
    }

    @Override
    public Faction getFaction()
    {
        return faction;
    }

    public void reset()
    {
        attack.reset();
        if (move != null) {
            move.dispose();
            move  = null;
        }
    }

    public void move(Move move)
    {
        if (move.isEntry())
            throw new RuntimeException("wrong MoveType");

        if (this.move != null) {
            if (this.move.isEntry())
                this.move.dispose();
            else
                throw new RuntimeException("try to override an existing move instance");
        }

        setMove(move);
    }

    public void enter(Move move)
    {
        if (!move.isEntry())
            throw new RuntimeException("wrong MoveType");

        if (this.move != null)
            throw new RuntimeException("try to override an existing move instance");

        setMove(move);
    }

    private void setMove(Move move)
    {
        this.move = move;
        move();
    }

    public void setAttack(Pawn target, int distance)
    {
        attack.reset();
        attack.target = target;
        attack.distance = distance;
    }

    public boolean justEntered()
    {
        return ((move != null) && move.isEntry());
    }

    public boolean is(Faction faction)
    {
        return (this.faction == faction);
    }

    public boolean isEnemy(Faction other)
    {
        return faction.isEnemy(other);
    }

    public boolean isEnemy(Pawn other)
    {
        return faction.isEnemy(other.faction);
    }

    public boolean isFlankAttack()
    {
        return (attack.isClear && attack.isFlank);
    }

    public int attackDistance()
    {
        return attack.distance;
    }

    public Tile getTile()
    {
        return tile;
    }

    public Tile getPreviousTile()
    {
        return prevTile;
    }

    public Vector3 getPosition()
    {
        return position;
    }

    public Vector3 getPreviousPosition()
    {
        return prevPosition;
    }

    private void revertPosition()
    {
        this.tile = this.prevTile;
        this.prevTile = null;
        position.set(prevPosition);
        prevPosition.set(0f, 0f, 0f);
        setPosition(position.x, position.y, position.z);
    }

    public float getCenterX()
    {
        return (getX() + (getWidth() / 2f));
    }

    public float getCenterY()
    {
        return (getY() + (getHeight() / 2f));
    }

    public Vector2 getPosAt(Tile tile, Vector2 pos)
    {
        float x = (tile.getX() - (getWidth() / 2f));
        float y = (tile.getY() - (getHeight() / 2f));
        if (pos == null)
            return new Vector2(x, y);
        else
            pos.set(x, y);
        return pos;
    }

    public void setOnTile(Tile tile, float z)
    {
        this.prevTile = this.tile;
        this.tile = tile;
        float x = (tile.getX() - (getWidth() / 2f));
        float y = (tile.getY() - (getHeight() / 2f));
        setPosition(x, y, z);
    }

    @Override
    public void setAlpha(float alpha)
    {
        sprite.setAlpha(alpha);
        overlays.setAlpha(alpha);
    }

    @Override
    public float getX()
    {
        return sprite.getX();
    }

    @Override
    public float getY()
    {
        return sprite.getY();
    }

    @Override
    public float getWidth()
    {
        return sprite.getWidth();
    }

    @Override
    public float getHeight()
    {
        return sprite.getHeight();
    }

    @Override
    public float getRotation()
    {
        return sprite.getRotation();
    }

    public Orientation getOrientation()
    {
        return Orientation.fromRotation(getRotation());
    }

    public void translate(float dx, float dy)
    {
        setPosition((getX() + dx), (getY() + dy));
    }

    public void centerOn(float x, float y)
    {
        setPosition((x - (getWidth() / 2f)), (y - (getHeight() / 2f)));
    }

    @Override
    public void setPosition(float x, float y)
    {
        position.set(x, y, 0f);
        sprite.setPosition(x, y);
        float cx = x + (getWidth() / 2f);
        float cy = y + (getHeight() / 2f);
        overlays.centerOn(cx, cy);
    }

    public void setRotation(float z)
    {
        position.z = z;
        sprite.setRotation(z);
        overlays.setRotation(z);
    }

    @Override
    public void setPosition(float x, float y, float z)
    {
        setPosition(x, y);
        setRotation(z);
    }

    public boolean hasOverlayEnabled()
    {
        return overlays.isEnabled();
    }

    public boolean enableOverlay(int i, boolean enable)
    {
        overlays.enable(i, enable);
        if (enable) return true;
        return hasOverlayEnabled();
    }

    public AnimationSequence getRotateAnimation(float z, int size)
    {
        prevPosition.set(position);
        AnimationSequence seq = AnimationSequence.get(1 + size);
        seq.addAnimation(MoveToAnimation.get(this, position.x, position.y, z, MOVE_TIME));

        return seq;
    }

    public AnimationSequence getMoveAnimation(Iterator<Vector3> vectors, int size, MoveToAnimation.MoveToAnimationCb cb)
    {
        prevPosition.set(position);
        AnimationSequence seq = AnimationSequence.get(size);
        while (vectors.hasNext())
            seq.addAnimation(MoveToAnimation.get(this, vectors.next(), MOVE_TIME, cb));

        return seq;
    }

    public AnimationSequence getRevertLastMoveAnimation(int size)
    {
        AnimationSequence seq = AnimationSequence.get(2 + size);
        seq.addAnimation(MoveToAnimation.get(this, prevPosition, MOVE_TIME));
        seq.addAnimation(RunnableAnimation.get(this, new Runnable() {
            @Override
            public void run() {
                revertPosition();
            }
        }));

        return seq;
    }

    @Override
    public void draw(Batch batch)
    {
        sprite.draw(batch);
        overlays.draw(batch);
    }

    @Override
    public void drawDebug(ShapeRenderer debugShapes)
    {
        float w = sprite.getWidth();
        float h = sprite.getHeight();
        debugShapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation());
        overlays.drawDebug(debugShapes);
    }
}