Update statement to stabilize rule changes
[troll.git] / src / main / java / com / codingame / game / View.java
index cfde0eb..40aae3d 100644 (file)
@@ -21,6 +21,28 @@ class View {
     @Inject private GraphicEntityModule graphicEntityModule;
     @Inject PantsModule pantsModule;
 
+    /*
+     * Frame timings, for a base frame length of 2s:
+     *   - first half: stone throw
+     *   - second half: troll move
+     * The troll message is anchored around the troll move.
+     */
+    private final double STONE_THROW_START = 0.0;
+    private final double STONE_THROW_PEAK = 0.25;
+    private final double STONE_THROW_END = 0.5;
+    private final double TROLL_MOVE_START = 0.5;
+    private final double TROLL_MOVE_END = 1.0;
+    private final double TROLL_MESSAGE_START = 0.5;
+    private final double TROLL_MESSAGE_END = 1.0;
+
+    /*
+     * Castle destruction and endgame message pertain to an endgame
+     * frame only.
+     */
+    private final double AVATAR_ANIMATION_START = 0.5;
+    private final double CASTLE_DESTRUCTION_START = 0.0;
+    private final double CASTLE_DESTRUCTION_END = 0.5;
+
     class Player {
         Model.Player model;
 
@@ -128,11 +150,12 @@ class View {
         }
 
         void startTurn() {
-            graphicEntityModule.commitEntityState(0, stoneReminder);
+            graphicEntityModule.commitEntityState(0.0, stoneReminder);
         }
 
         void victory() {
             gameManager.addToGameSummary(GameManager.formatSuccessMessage(nicknameToken + " wins."));
+            View.this.endgameFrame();
             markWinner();
         }
 
@@ -156,7 +179,7 @@ class View {
         }
 
         void markWinner() {
-            graphicEntityModule.commitEntityState(0.5, avatar);
+            graphicEntityModule.commitEntityState(AVATAR_ANIMATION_START, avatar);
             avatar.setScaleX(1.5, Curve.EASE_OUT);
             avatar.setScaleY(1.5, Curve.EASE_OUT);
             avatar.setRotation((random.nextDouble() - 0.5) * Math.PI / 18,
@@ -164,7 +187,7 @@ class View {
         }
 
         void markLoser() {
-            graphicEntityModule.commitEntityState(0.5, avatar);
+            graphicEntityModule.commitEntityState(AVATAR_ANIMATION_START, avatar);
             int dir = random.nextInt(2) == 1 ? 1 : -1;
             avatar.setRotation(dir * 170 * Math.PI / 180, Curve.ELASTIC);
         }
@@ -196,6 +219,7 @@ class View {
             else {
                 stoneCounter.setText(stones + " stones");
             }
+            graphicEntityModule.commitEntityState(STONE_THROW_PEAK, stoneCounter);
         }
 
         void animateStones(int stones) {
@@ -204,36 +228,37 @@ class View {
             stone.setY(castle.getY() - 100);
             stone.setText(stonesString);
             stone.setAlpha(1);
-            graphicEntityModule.commitEntityState(0, stone);
+            graphicEntityModule.commitEntityState(STONE_THROW_START, stone);
     
             int peakX = (castle.getX() + troll.getX()) / 2;
             int peakY = 540;
             stone.setX(peakX);
             stone.setY(peakY, Curve.EASE_OUT);
-            graphicEntityModule.commitEntityState(0.25,
+            graphicEntityModule.commitEntityState(STONE_THROW_PEAK,
                                                   stone,
                                                   stoneCounter);
     
             stone.setX(troll.getX());
             stone.setY(troll.getY() - 50, Curve.EASE_IN);
             stone.setAlpha(0, Curve.EASE_IN);
-            graphicEntityModule.commitEntityState(0.5, stone);
+            graphicEntityModule.commitEntityState(STONE_THROW_END, stone);
 
             stoneReminder.setText(stonesString);
-            graphicEntityModule.commitEntityState(0, stoneReminder);
+            graphicEntityModule.commitEntityState(0.0, stoneReminder);
         }
 
         // ========== Player/castle
 
         void displayMessage(String msg) {
             message.setText(msg);
-            graphicEntityModule.commitEntityState(0, message);
+            graphicEntityModule.commitEntityState(0.0, message);
         }
 
         void destroyCastle() {
-            graphicEntityModule.commitEntityState(0.5, castle);
+            graphicEntityModule.commitEntityState(CASTLE_DESTRUCTION_START, castle);
             castle.setX(castle.getX(), Curve.ELASTIC);
             castle.setScaleY(-0.2, Curve.EASE_IN);
+            graphicEntityModule.commitEntityState(CASTLE_DESTRUCTION_END, castle);
         }
     } // class Player
 
@@ -277,13 +302,19 @@ class View {
         animateTurnCounter();
     }
 
+    void endgameFrame() {
+        gameManager.setFrameDuration(2000);
+    }
+
     void doubleDefeat() {
         gameManager.addToGameSummary(GameManager.formatErrorMessage("Everybody loses!"));
+        endgameFrame();
         animateLoss(1920/2, 680, 150, "L0SERZ!");
     }
 
     void draw() {
         gameManager.addToGameSummary("Draw.");
+        endgameFrame();
         animateLoss(1920/2, 680, 200, "DRAW");
     }
 
@@ -487,8 +518,8 @@ class View {
         pantsModule.displayOnToggleState(trollMessage, "verboseTrolling", true);
     }
 
-    private void moveTroll() {
-        graphicEntityModule.commitEntityState(0.5, troll, trollPositionGauge);
+    void moveTroll() {
+        graphicEntityModule.commitEntityState(TROLL_MOVE_START, troll, trollPositionGauge);
         int x0 = p0.castle.getX(), x1 = p1.castle.getX();
         int y0 = p0.castle.getY(), y1 = p1.castle.getY();
         troll.setX(x0 + model.trollPosition * (x1-x0) / model.roadLength,
@@ -508,7 +539,8 @@ class View {
         else {
             trollPositionGauge.setText(distLeft + " ↔ " + distRight);
         }
-        graphicEntityModule.commitEntityState(0.75, trollPositionGauge);
+        final double moveMid = (TROLL_MOVE_START + TROLL_MOVE_END) / 2;
+        graphicEntityModule.commitEntityState(moveMid, trollPositionGauge);
         trollPositionGauge.setX(troll.getX());
     }
 
@@ -526,9 +558,9 @@ class View {
         gameManager.addToGameSummary(trollRace.starter + " " + d.movement);
 
         trollMessage.setText(selectTrollMessage(d)).setAlpha(1, Curve.NONE);
-        graphicEntityModule.commitEntityState(0.5, trollMessage);
+        graphicEntityModule.commitEntityState(TROLL_MESSAGE_START, trollMessage);
         trollMessage.setAlpha(0, Curve.EASE_IN);
-        graphicEntityModule.commitEntityState(1, trollMessage);
+        graphicEntityModule.commitEntityState(TROLL_MESSAGE_END, trollMessage);
     }
 
     String selectTrollMessage(Dir d) {
@@ -595,7 +627,7 @@ class View {
     void animateLoss(int x, int y, int size, String message) {
         int startX;
         if (x < 1920/2) { startX = 1920; }
-        else if (x > 1920/2) { startX = 1920; } // XXX
+        else if (x > 1920/2) { startX = 0; }
         else { startX = 1920 * random.nextInt(2); }
 
         Text msg = graphicEntityModule.createText(message)
@@ -614,7 +646,7 @@ class View {
             .setFillColor(0xff7f7f)
             .setFontWeight(Text.FontWeight.BOLD)
             .setTextAlign(TextBasedEntity.TextAlign.CENTER);
-        graphicEntityModule.commitEntityState(0.25, msg);
+        graphicEntityModule.commitEntityState(0.0, msg);
         Curve curve = Curve.ELASTIC;
         msg.setX(x, Curve.EASE_OUT)
             .setY(y, Curve.ELASTIC)