summaryrefslogtreecommitdiffstats
path: root/core/src/ch/asynk/rustanddust/game/hud
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/game/hud
parente66f9f2a61d3dab4545e996046486de0d44e2901 (diff)
downloadRustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.zip
RustAndDust-de0463bcf0f76ef8b07f2719679c9e0d72745c5d.tar.gz
welcome RustAndDust
Diffstat (limited to 'core/src/ch/asynk/rustanddust/game/hud')
-rw-r--r--core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java185
-rw-r--r--core/src/ch/asynk/rustanddust/game/hud/EngagementPanel.java255
-rw-r--r--core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java202
-rw-r--r--core/src/ch/asynk/rustanddust/game/hud/StatisticsPanel.java120
-rw-r--r--core/src/ch/asynk/rustanddust/game/hud/UnitDock.java226
5 files changed, 988 insertions, 0 deletions
diff --git a/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java b/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java
new file mode 100644
index 0000000..323767f
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java
@@ -0,0 +1,185 @@
+package ch.asynk.rustanddust.game.hud;
+
+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 ch.asynk.rustanddust.game.Ctrl;
+import ch.asynk.rustanddust.game.State.StateType;
+import ch.asynk.rustanddust.ui.Widget;
+import ch.asynk.rustanddust.ui.Bg;
+import ch.asynk.rustanddust.ui.Position;
+
+public class ActionButtons extends Widget
+{
+ public static int PADDING = 5;
+
+ private final Ctrl ctrl;
+
+ public enum Buttons {
+ NONE(-1, 0),
+ PROMOTE(0, 1),
+ DONE(1, 2),
+ ABORT(2, 4),
+ LAST(3, 0);
+
+ Buttons(int i, int b)
+ {
+ this.i = i;
+ this.b = b;
+ }
+
+ public int i;
+ public int b;
+ }
+
+ private Sprite bg;
+ private int idx;
+ private Bg buttons [];
+ private StateType states [];
+
+ public ActionButtons(Ctrl ctrl, TextureAtlas uiAtlas, TextureAtlas hudAtlas)
+ {
+ this.bg = new Sprite(uiAtlas.findRegion("disabled"));
+ this.ctrl = ctrl;
+ this.visible = false;
+ this.position = Position.BOTTOM_RIGHT;
+ this.idx = Buttons.NONE.i;
+
+
+ this.buttons = new Bg[Buttons.LAST.i];
+ this.buttons[Buttons.DONE.i] = new Bg(uiAtlas.findRegion("ok"));
+ this.buttons[Buttons.ABORT.i] = new Bg(uiAtlas.findRegion("cancel"));
+ this.buttons[Buttons.PROMOTE.i] = new Bg(hudAtlas.findRegion("promote"));
+
+ this.states = new StateType[Buttons.LAST.i];
+ this.states[Buttons.DONE.i] = StateType.DONE;
+ this.states[Buttons.ABORT.i] = StateType.ABORT;
+ this.states[Buttons.PROMOTE.i] = StateType.PROMOTE;
+ }
+
+ @Override
+ public void dispose()
+ {
+ for (int i = 0; i < Buttons.LAST.i; i++)
+ buttons[i].dispose();
+ }
+
+ public void update(Position position)
+ {
+ setPosition(position);
+ updatePosition();
+ }
+
+ public void updatePosition()
+ {
+ if (!visible) return;
+ float dx = (position.getX(rect.width) - rect.x);
+ float dy = (position.getY(rect.height) - rect.y);
+ translate(dx, dy);
+ for (int i = 0; i < Buttons.LAST.i; i++)
+ buttons[i].translate(dx, dy);
+ }
+
+ public void hide()
+ {
+ for (int i = 0; i < Buttons.LAST.i; i++)
+ buttons[i].visible = false;
+ this.visible = false;
+ }
+
+ private float setButton(Bg btn, float x, float y)
+ {
+ btn.visible = true;
+ btn.setPosition(x, y);
+ return (y + btn.getHeight() + PADDING);
+ }
+
+ public void show(int bits)
+ {
+ int b = bits;
+ int count = 0;
+ while (b > 0) {
+ if ((b & 0x01) == 1)
+ count += 1;
+ b /= 2;
+ }
+
+ if (count == 0) {
+ this.visible = false;
+ return;
+ }
+
+ rect.width = (buttons[0].getWidth() + (2 * PADDING));
+ rect.height = ((buttons[0].getHeight() * count) + ((count + 1) * PADDING));
+ rect.x = position.getX(rect.width);
+ rect.y = position.getY(rect.height);
+
+ float x = (rect.x + PADDING);
+ float y = (rect.y + PADDING);
+
+ b = 1;
+ for (int i = 0; i < Buttons.LAST.i; i++) {
+ if ((bits & b) == b)
+ y = setButton(buttons[i], x, y);
+ else
+ buttons[i].visible = false;
+ b *= 2;
+ }
+
+ this.visible = true;
+ }
+
+ public boolean touchDown(float x, float y)
+ {
+ idx = Buttons.NONE.i;
+
+ if (!super.hit(x,y))
+ return false;
+
+ for (int i = 0; i < Buttons.LAST.i; i++) {
+ if (buttons[i].hit(x, y)) {
+ idx = i;
+ break;
+ }
+ }
+
+ return (idx != Buttons.NONE.i);
+ }
+
+ public boolean touchUp(float x, float y)
+ {
+ if (idx == Buttons.NONE.i)
+ return false;
+
+ boolean ret = false;
+
+ if (super.hit(x,y) && buttons[idx].hit(x, y)) {
+ ctrl.setState(states[idx]);
+ ret = true;
+ }
+
+ idx = Buttons.NONE.i;
+
+ return ret;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ if (!visible) return;
+ batch.draw(bg, rect.x, rect.y, rect.width, rect.height);
+ for (int i = 0; i < Buttons.LAST.i; i++)
+ buttons[i].draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer shapes)
+ {
+ if (!visible) return;
+ super.drawDebug(shapes);
+ for (int i = 0; i < Buttons.LAST.i; i++)
+ buttons[i].drawDebug(shapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/game/hud/EngagementPanel.java b/core/src/ch/asynk/rustanddust/game/hud/EngagementPanel.java
new file mode 100644
index 0000000..790c8b5
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/game/hud/EngagementPanel.java
@@ -0,0 +1,255 @@
+package ch.asynk.rustanddust.game.hud;
+
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.game.Engagement;
+import ch.asynk.rustanddust.game.Army;
+import ch.asynk.rustanddust.engine.gfx.Animation;
+import ch.asynk.rustanddust.engine.gfx.animations.DiceAnimation;
+import ch.asynk.rustanddust.ui.Bg;
+import ch.asynk.rustanddust.ui.Label;
+import ch.asynk.rustanddust.ui.Patch;
+import ch.asynk.rustanddust.ui.Position;
+
+public class EngagementPanel extends Patch implements Animation
+{
+ private enum State { ROLL1, MOVE, ROLL2, RESULT };
+
+ public static int FLAG_HEIGHT = 24;
+ public static int OK_OFFSET = 10;
+ public static int PADDING = 20;
+ public static int VSPACING = 10;
+ public static int HSPACING = 5;
+ public static float MOVE_STEP = 2f;
+
+ private State state;
+ private boolean reroll;
+ private float rerollY;
+ private Sprite usFlag;
+ private Sprite geFlag;
+ private Sprite winner;
+ private Sprite attackImg;
+ private Sprite defenseImg;
+ private Label attack;
+ private Label defense;
+ private Label attackR;
+ private Label defenseR;
+ private Bg okBtn;
+ private DiceAnimation d1Animation;
+ private DiceAnimation d2Animation;
+ private DiceAnimation d3Animation;
+ private DiceAnimation d4Animation;
+
+ public EngagementPanel(BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas)
+ {
+ super(uiAtlas.createPatch("typewriter"));
+ usFlag = new Sprite(hudAtlas.findRegion("us-flag"));
+ geFlag = new Sprite(hudAtlas.findRegion("ge-flag"));
+ attackImg = new Sprite(hudAtlas.findRegion("attack"));
+ defenseImg = new Sprite(hudAtlas.findRegion("defense"));
+ this.attack = new Label(font);
+ this.defense = new Label(font);
+ this.attackR = new Label(font);
+ this.defenseR = new Label(font);
+ this.okBtn = new Bg(uiAtlas.findRegion("ok"));
+ this.visible = false;
+ this.d1Animation = new DiceAnimation();
+ this.d2Animation = new DiceAnimation();
+ this.d3Animation = new DiceAnimation();
+ this.d4Animation = new DiceAnimation();
+ }
+
+ public void updatePosition()
+ {
+ if (!visible) return;
+ float dx = (position.getX(rect.width) - rect.x);
+ float dy = (position.getY(rect.height) - rect.y);
+ translate(dx, dy);
+ winner.translate(dx, dy);
+ attackImg.translate(dx, dy);
+ defenseImg.translate(dx, dy);
+ attack.translate(dx, dy);
+ defense.translate(dx, dy);
+ attackR.translate(dx, dy);
+ defenseR.translate(dx, dy);
+ okBtn.translate(dx, dy);
+ d1Animation.translate(dx, dy);
+ d2Animation.translate(dx, dy);
+ d3Animation.translate(dx, dy);
+ d4Animation.translate(dx, dy);
+ }
+
+ public void show(Engagement e, Position position, float volume)
+ {
+ DiceAnimation.initSound(volume);
+ attack.write(String.format(" + %d + %d =", e.unitCount, e.flankBonus));
+ if (e.weatherDefense == 0)
+ defense.write(String.format("%d + %d =", e.unitDefense, e.terrainDefense));
+ else
+ defense.write(String.format("%d + %d + %d =", e.unitDefense, e.terrainDefense, e.weatherDefense));
+ attackR.write(String.format(" %2d", e.attackSum));
+ defenseR.write(String.format(" %2d", e.defenseSum));
+ if (e.success)
+ winner = ((e.attacker.getArmy() == Army.US) ? usFlag : geFlag);
+ else
+ winner = ((e.attacker.getArmy() == Army.US) ? geFlag : usFlag);
+
+ this.position = position;
+ placeElements();
+
+ state = State.ROLL1;
+ reroll = (e.d3 != 0);
+
+ d1Animation.set(e.d1);
+ d2Animation.set(e.d2);
+ if (reroll) {
+ d3Animation.set(e.d3);
+ d4Animation.set(e.d4);
+ }
+
+ visible = true;
+ }
+
+ private void placeElements()
+ {
+ float w = attackR.getWidth();
+ float w2 = defenseR.getWidth();
+ if (w2 > w)
+ w = w2;
+ float height = (okBtn.getHeight() + attackImg.getHeight() + defenseImg.getHeight() + (2 * VSPACING) + (2 * PADDING));
+ float width = (attackImg.getWidth() + (2 * d1Animation.getWidth()) + attack.getWidth() + w + (4 * HSPACING) + (2 * PADDING));
+ float x = position.getX(width);
+ float y = position.getY(height);
+ setPosition(x, y, width, height);
+
+ okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET));
+
+ x = getX() + PADDING;
+ y = getY() + PADDING;
+ winner.setPosition((getX() + (width / 2f) - (winner.getWidth() / 2f)), y);
+ y += (winner.getHeight() + VSPACING);
+
+ defenseImg.setPosition(x, y);
+ y = (y + (defenseImg.getHeight() / 2f) - (defense.getHeight() / 2f));
+ defenseR.setPosition((getX() + width - w - PADDING), y);
+ // x += (defenseImg.getWidth() + HSPACING);
+ defense.setPosition((defenseR.getX() - defense.getWidth() - HSPACING), y);
+
+ x = getX() + PADDING;
+ y += defenseImg.getHeight() + VSPACING;
+ attackImg.setPosition(x, y);
+ x += (attackImg.getWidth() + HSPACING);
+ d1Animation.setPosition(x, y);
+ d3Animation.setPosition(x, y);
+ x += (d1Animation.getWidth() + HSPACING);
+ d2Animation.setPosition(x, (y));
+ d4Animation.setPosition(x, y);
+ x += (d1Animation.getWidth() + HSPACING);
+ y = (y + (attackImg.getHeight() / 2f) - (attack.getHeight() / 2f));
+ attack.setPosition(x, y);
+ attackR.setPosition(defenseR.getX(), y);
+
+ rerollY = (d1Animation.getY() + d1Animation.getHeight() + VSPACING);
+ }
+
+ @Override
+ public boolean hit(float x, float y)
+ {
+ return rect.contains(x, y);
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ if (!visible) return true;
+ if (state == State.ROLL1) {
+ d1Animation.animate(delta);
+ d2Animation.animate(delta);
+ if (d1Animation.isDone() && d2Animation.isDone()) {
+ if (reroll)
+ state = State.MOVE;
+ else
+ state = State.RESULT;
+ }
+ }
+
+ if (state == State.MOVE) {
+ float y = (d1Animation.getY() + MOVE_STEP);
+ if (y >= rerollY) {
+ y = rerollY;
+ state = State.ROLL2;
+ }
+ setPosition(getX(), getY(), getWidth(), (y + d1Animation.getHeight() + VSPACING - getY()));
+ d1Animation.setPosition(d1Animation.getX(), y);
+ d2Animation.setPosition(d2Animation.getX(), y);
+ }
+
+ if (state == State.ROLL2) {
+ if (d1Animation.getY() < rerollY) {
+ d1Animation.setPosition(d1Animation.getX(), (d1Animation.getY() + d1Animation.getHeight() + VSPACING));
+ d2Animation.setPosition(d2Animation.getX(), (d2Animation.getY() + d2Animation.getHeight() + VSPACING));
+ } else {
+ d3Animation.animate(delta);
+ d4Animation.animate(delta);
+ if (d3Animation.isDone() && d4Animation.isDone())
+ state = State.RESULT;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void dispose()
+ {
+ super.dispose();
+ attack.dispose();
+ defense.dispose();
+ attackR.dispose();
+ defenseR.dispose();
+ d1Animation.dispose();
+ d2Animation.dispose();
+ d3Animation.dispose();
+ d4Animation.dispose();
+ okBtn.dispose();
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ if (!visible) return;
+ super.draw(batch);
+ attackImg.draw(batch);
+ d1Animation.draw(batch);
+ d2Animation.draw(batch);
+ if ((state == State.ROLL2) || (reroll && (state == State.RESULT))) {
+ d3Animation.draw(batch);
+ d4Animation.draw(batch);
+ }
+ attack.draw(batch);
+ defenseImg.draw(batch);
+ defense.draw(batch);
+ defenseR.draw(batch);
+ okBtn.draw(batch);
+ if (state == State.RESULT) {
+ attackR.draw(batch);
+ winner.draw(batch);
+ }
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer shapes)
+ {
+ if (!visible) return;
+ super.drawDebug(shapes);
+ attack.drawDebug(shapes);
+ defense.drawDebug(shapes);
+ attackR.drawDebug(shapes);
+ defenseR.drawDebug(shapes);
+ okBtn.drawDebug(shapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java b/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java
new file mode 100644
index 0000000..dd77c8e
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java
@@ -0,0 +1,202 @@
+package ch.asynk.rustanddust.game.hud;
+
+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.BitmapFont;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.engine.gfx.Animation;
+import ch.asynk.rustanddust.engine.gfx.Drawable;
+
+import ch.asynk.rustanddust.game.State.StateType;
+import ch.asynk.rustanddust.game.Ctrl;
+import ch.asynk.rustanddust.game.Hud;
+import ch.asynk.rustanddust.game.Army;
+import ch.asynk.rustanddust.game.Unit;
+import ch.asynk.rustanddust.game.Player;
+import ch.asynk.rustanddust.ui.LabelImage;
+import ch.asynk.rustanddust.ui.Position;
+
+public class PlayerInfo implements Disposable, Drawable, Animation
+{
+ public static int PADDING = 5;
+
+ private final Ctrl ctrl;
+
+ private Object hit;
+
+ private Sprite flag;
+ private Sprite usFlag;
+ private Sprite geFlag;
+ private LabelImage turns;
+ private LabelImage aps;
+ private LabelImage reinforcement;
+ public UnitDock unitDock;
+ private Position position;
+
+ public PlayerInfo(Ctrl ctrl, BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas)
+ {
+ this.ctrl = ctrl;
+ this.position = Position.MIDDLE_CENTER;
+ usFlag = new Sprite(hudAtlas.findRegion("us-flag"));
+ geFlag = new Sprite(hudAtlas.findRegion("ge-flag"));
+ turns = new LabelImage(hudAtlas.findRegion("turns"), font, 5f);
+ aps = new LabelImage(hudAtlas.findRegion("aps"), font, 5f);
+ reinforcement = new LabelImage(hudAtlas.findRegion("reinforcement"), font, 5f);
+ unitDock = new UnitDock(ctrl, uiAtlas.findRegion("disabled"), hudAtlas.findRegion("reinforcement-selected"), 10f);
+ }
+
+ @Override
+ public void dispose()
+ {
+ turns.dispose();
+ aps.dispose();
+ reinforcement.dispose();
+ unitDock.dispose();
+ }
+
+ public void updatePosition()
+ {
+ float dx = (position.getX(usFlag.getWidth()) - usFlag.getX());
+ float dy = (position.getY(usFlag.getHeight()) - usFlag.getY());
+ usFlag.translate(dx, dy);
+ geFlag.translate(dx, dy);
+ turns.translate(dx, dy);
+ aps.translate(dx, dy);
+ reinforcement.translate(dx, dy);
+ unitDock.translate(dx, dy);
+ }
+
+ public void setPosition(Position position)
+ {
+ if (this.position == position)
+ return;
+ this.position = position;
+
+ float width = (usFlag.getWidth() + turns.getWidth() + aps.getWidth() + (2 * PADDING));
+ float height = (usFlag.getHeight() + reinforcement.getHeight() + (1 * PADDING));
+ float x = position.getX(width);
+ float y = position.getY(height);
+
+ if (position.isLeft()) {
+ reinforcement.setPosition(x, y);
+ y += (reinforcement.getHeight() + PADDING);
+ usFlag.setPosition(x, y);
+ geFlag.setPosition(x, y);
+ x += (usFlag.getWidth() + PADDING);
+ turns.setPosition(x, y);
+ x += (turns.getWidth() + PADDING);
+ aps.setPosition(x, y);
+ } else {
+ x = (x + width);
+ reinforcement.setPosition((x - reinforcement.getWidth()), y);
+ y += (reinforcement.getHeight() + PADDING);
+ x -= usFlag.getWidth();
+ usFlag.setPosition(x, y);
+ geFlag.setPosition(x, y);
+ x -= (turns.getWidth() + PADDING);
+ turns.setPosition(x, y);
+ x -= (aps.getWidth() + PADDING);
+ aps.setPosition(x, y);
+ }
+ aps.setLabelPosition(Position.TOP_RIGHT);
+ turns.setLabelPosition(Position.MIDDLE_CENTER);
+ reinforcement.setLabelPosition(Position.TOP_LEFT);
+ unitDock.setPosition(position, reinforcement.getY() - PADDING);
+ }
+
+ public void update(Player player, Position position)
+ {
+ unitDock.hide();
+ turns.write(String.format("%d", player.getCurrentTurn()));
+ aps.write(String.format("%d", player.getAp()));
+ int r = player.reinforcement();
+ if (r == 0) {
+ reinforcement.visible = false;
+ } else {
+ reinforcement.visible = true;
+ reinforcement.write(String.format("%d", r));
+ }
+
+ if (player.is(Army.GE))
+ flag = geFlag;
+ else
+ flag = usFlag;
+
+ setPosition(position);
+ }
+
+ public void blockEndOfTurn(boolean blocked)
+ {
+ turns.blocked = blocked;
+ }
+
+ public boolean touchDown(float x, float y)
+ {
+ hit = null;
+
+ if (reinforcement.hit(x, y))
+ hit = reinforcement;
+ else if (unitDock.hit(x, y))
+ hit = unitDock;
+ else if (turns.hit(x,y))
+ hit = turns;
+
+ return (hit != null);
+ }
+
+ public boolean touchUp(float x, float y)
+ {
+ if (hit == null)
+ return false;
+
+ if (hit == turns) {
+ if (turns.hit(x, y))
+ ctrl.hud.askEndOfTurn();
+ }
+ else if (hit == reinforcement) {
+ if (reinforcement.hit(x, y))
+ ctrl.reinforcementHit();
+ }
+ else if (hit == unitDock) {
+ if (unitDock.hit(x, y)) {
+ ctrl.hud.notify(unitDock.select(x, y).toString());
+ ctrl.stateTouchUp();
+ }
+ }
+
+ hit = null;
+
+ return true;
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ unitDock.animate(delta);
+ return false;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ flag.draw(batch);
+ turns.draw(batch);
+ aps.draw(batch);
+ reinforcement.draw(batch);
+ unitDock.draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer debugShapes)
+ {
+ turns.drawDebug(debugShapes);
+ aps.drawDebug(debugShapes);
+ reinforcement.drawDebug(debugShapes);
+ unitDock.drawDebug(debugShapes);
+ debugShapes.rect(flag.getX(), flag.getY(), flag.getWidth(), flag.getHeight());
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/game/hud/StatisticsPanel.java b/core/src/ch/asynk/rustanddust/game/hud/StatisticsPanel.java
new file mode 100644
index 0000000..2e6546b
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/game/hud/StatisticsPanel.java
@@ -0,0 +1,120 @@
+package ch.asynk.rustanddust.game.hud;
+
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+
+import ch.asynk.rustanddust.game.Player;
+import ch.asynk.rustanddust.ui.Bg;
+import ch.asynk.rustanddust.ui.Label;
+import ch.asynk.rustanddust.ui.Patch;
+import ch.asynk.rustanddust.ui.Position;
+
+public class StatisticsPanel extends Patch
+{
+ public static int OK_OFFSET = 10;
+ public static int PADDING = 20;
+ public static int VSPACING = 10;
+ public static int HSPACING = 10;
+
+ private Label title;
+ private Label header;
+ private Label stats1;
+ private Label stats2;
+ private Bg okBtn;
+
+ public StatisticsPanel(BitmapFont font, TextureAtlas atlas)
+ {
+ super(atlas.createPatch("typewriter"));
+ this.title = new Label(font);
+ this.header = new Label(font);
+ this.stats1 = new Label(font);
+ this.stats2 = new Label(font);
+ this.okBtn = new Bg(atlas.findRegion("ok"));
+ this.visible = false;
+ this.header.write("\nActions\nUnits Left\nUnits Withrawed\nCasualties\nWon Attacks\nLost Attacks");
+ }
+
+ public void updatePosition()
+ {
+ if (!visible) return;
+ float dx = (position.getX(rect.width) - rect.x);
+ float dy = (position.getY(rect.height) - rect.y);
+ translate(dx, dy);
+ title.translate(dx, dy);
+ header.translate(dx, dy);
+ stats1.translate(dx, dy);
+ stats2.translate(dx, dy);
+ okBtn.translate(dx, dy);
+ }
+
+ public void show(Player winner, Player loser, Position position)
+ {
+ title.write(winner.getName() + " player won the battle in " + winner.getTurnDone() + " turns.");
+ stats1.write(winner.getStats());
+ stats2.write(loser.getStats());
+
+ float height = (title.getHeight() + header.getHeight() + (2 * PADDING) + (1 * VSPACING));
+ float width = (header.getWidth() + stats1.getWidth() + stats2.getWidth() + (2 * PADDING) + (4 * HSPACING));
+ float w2 = (title.getWidth() + (2 * PADDING));
+ if (w2 > width) width = w2;
+ float x = position.getX(width);
+ float y = position.getY(height);
+ setPosition(x, y, width, height);
+
+ okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET));
+
+ y += PADDING;
+ x += PADDING;
+ header.setPosition(x, y);
+ stats1.setPosition((x + header.getWidth() + (2 * HSPACING)), y);
+ stats2.setPosition((stats1.getX() + stats1.getWidth() + (2 * HSPACING)), y);
+ y += (header.getHeight() + VSPACING);
+ title.setPosition(x, y);
+ visible = true;
+ }
+
+ @Override
+ public boolean hit(float x, float y)
+ {
+ if (okBtn.hit(x, y))
+ return true;
+ return false;
+ }
+
+ @Override
+ public void dispose()
+ {
+ super.dispose();
+ title.dispose();
+ header.dispose();
+ stats1.dispose();
+ stats2.dispose();
+ okBtn.dispose();
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ if (!visible) return;
+ super.draw(batch);
+ title.draw(batch);
+ header.draw(batch);
+ stats1.draw(batch);
+ stats2.draw(batch);
+ okBtn.draw(batch);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer shapes)
+ {
+ if (!visible) return;
+ super.drawDebug(shapes);
+ title.drawDebug(shapes);
+ header.drawDebug(shapes);
+ stats1.drawDebug(shapes);
+ stats2.drawDebug(shapes);
+ okBtn.drawDebug(shapes);
+ }
+}
diff --git a/core/src/ch/asynk/rustanddust/game/hud/UnitDock.java b/core/src/ch/asynk/rustanddust/game/hud/UnitDock.java
new file mode 100644
index 0000000..11895ba
--- /dev/null
+++ b/core/src/ch/asynk/rustanddust/game/hud/UnitDock.java
@@ -0,0 +1,226 @@
+package ch.asynk.rustanddust.game.hud;
+
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.math.Matrix4;
+import com.badlogic.gdx.math.Rectangle;
+
+import ch.asynk.rustanddust.engine.gfx.Animation;
+import ch.asynk.rustanddust.engine.Orientation;
+import ch.asynk.rustanddust.game.Ctrl;
+import ch.asynk.rustanddust.game.Unit;
+import ch.asynk.rustanddust.game.UnitList;
+import ch.asynk.rustanddust.ui.Bg;
+import ch.asynk.rustanddust.ui.Position;
+
+public class UnitDock extends Bg implements Animation
+{
+ private static final float SCALE = 0.4f;
+ private static final float STEP = 5f;
+ private final Ctrl ctrl;
+
+ private int n;
+ private float y;
+ private float to;
+ private float dx;
+ private float step;
+ private boolean show;
+ private boolean mvtDone;
+ public Unit selectedUnit;
+ private Sprite selected;
+ private UnitList units;
+ private Vector3 point;
+ private Matrix4 saved;
+ private Matrix4 transform;
+ private Rectangle scaledRect;
+
+ public UnitDock(Ctrl ctrl, TextureRegion region, TextureRegion selected, float padding)
+ {
+ super(region);
+ this.ctrl = ctrl;
+ this.padding = padding;
+ this.mvtDone = true;
+ this.point = new Vector3();
+ this.saved = new Matrix4();
+ this.transform = new Matrix4();
+ this.scaledRect = new Rectangle();
+ this.selected = new Sprite(selected);
+ this.visible = false;
+ this.dx = 0f;
+ }
+
+ @Override
+ public void translate(float _dx, float _dy)
+ {
+ this.y += _dy;
+ if (!visible) return;
+ super.translate(_dx, _dy);
+ for (Unit unit : units)
+ unit.translate(_dx, _dy);
+ to = position.getX(rect.width * SCALE);
+ transform.idt();
+ transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0);
+ point.set(rect.x, rect.y, 0).mul(transform);
+ scaledRect.x = point.x;
+ scaledRect.y = point.y;
+ point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform);
+ scaledRect.width = point.x - scaledRect.x;
+ scaledRect.height = point.y - scaledRect.y;
+ }
+
+ public void setPosition(Position position, float y)
+ {
+ if (this.position == position)
+ return;
+ this.position = position;
+ this.y = y;
+ this.step = (position.isLeft() ? STEP : -STEP);
+ this.mvtDone = true;
+ this.visible = false;
+ this.dx = 0f;
+ }
+
+ @Override
+ public void dispose()
+ {
+ super.dispose();
+ }
+
+ @Override
+ public boolean hit(float x, float y)
+ {
+ return (visible && scaledRect.contains(x, y));
+ }
+
+ public Unit select(float x, float y)
+ {
+ int i = (int) ((scaledRect.y + scaledRect.height - y) / (scaledRect.height / units.size()));
+ selectedUnit = units.get(i);
+ return selectedUnit;
+ }
+
+ public void hide()
+ {
+ if (!visible) return;
+ resize();
+ to = rect.x;
+
+ show = false;
+ mvtDone = false;
+ selectedUnit = null;
+ }
+
+ public void show()
+ {
+ if (!resize())
+ return;
+ to = position.getX(rect.width * SCALE);
+
+ show = true;
+ mvtDone = false;
+ selectedUnit = null;
+ visible = true;
+ }
+
+ private boolean resize()
+ {
+ int count = ctrl.player.reinforcement();
+ if (count == 0) {
+ n = 0;
+ return false;
+ }
+ if (count == n) return true;
+ n = count;
+
+ units = ctrl.player.reinforcement;
+ rect.width = units.get(0).getWidth() + (2 * padding);
+ rect.height = ((units.get(0).getHeight() * n) + ((n + 1) * padding));
+ float scaledWidth = (rect.width * SCALE);
+ to = position.getX(scaledWidth);
+ rect.x = to + (position.isLeft() ? -scaledWidth : scaledWidth);
+ rect.y = y - rect.height;
+
+ float px = rect.x;
+ float py = rect.y + rect.height;
+ float ph = units.get(0).getHeight();
+ for (Unit unit : units) {
+ py -= (ph + padding);
+ // unit.setPosition(px, py, Orientation.SOUTH.r());
+ unit.centerOn((px + (rect.width / 2)), py + (ph / 2));
+ unit.setRotation(position.isLeft() ? Orientation.NORTH.r() : Orientation.SOUTH.r());
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean animate(float delta)
+ {
+ if (!visible) return true;
+ if (mvtDone) return true;
+
+ float x = (rect.x + dx);
+ if (show) {
+ if ((position.isLeft() && (x < to)) || (!position.isLeft() && x > to))
+ dx += step;
+ else {
+ dx = (to - rect.x);
+ mvtDone = true;
+ }
+ } else {
+ if ((position.isLeft() && (x > to)) || (!position.isLeft() && x < to))
+ dx -= step;
+ else {
+ dx = (to - rect.x);
+ mvtDone = true;
+ visible = false;
+ }
+ }
+
+ transform.idt();
+ transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0);
+ point.set(rect.x, rect.y, 0).mul(transform);
+ scaledRect.x = point.x;
+ scaledRect.y = point.y;
+ point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform);
+ scaledRect.width = point.x - scaledRect.x;
+ scaledRect.height = point.y - scaledRect.y;
+ return false;
+ }
+
+ @Override
+ public void draw(Batch batch)
+ {
+ if (!visible) return;
+
+ saved.set(batch.getTransformMatrix());
+ batch.setTransformMatrix(transform);
+
+ super.draw(batch);
+ for (Unit unit : units) {
+ unit.draw(batch);
+ if (unit == selectedUnit) {
+ selected.setCenter((unit.getX() + (unit.getWidth() / 2)), (unit.getY() + (unit.getHeight() / 2)));
+ selected.draw(batch);
+ }
+ }
+
+ batch.setTransformMatrix(saved);
+ }
+
+ @Override
+ public void drawDebug(ShapeRenderer shapes)
+ {
+ if (!visible) return;
+
+ saved.set(shapes.getTransformMatrix());
+ shapes.setTransformMatrix(transform);
+
+ shapes.rect(rect.x, rect.y, rect.width, rect.height);
+
+ shapes.setTransformMatrix(saved);
+ }
+}