Add debug mode for @pb4. Also ensure it's useless by
[troll.git] / src / main / java / com / codingame / game / View.java
1 package com.codingame.game;
2
3 import java.util.Random;
4 import java.util.ArrayList;
5 import java.util.Comparator;
6
7 import com.codingame.gameengine.core.MultiplayerGameManager;
8 import com.codingame.gameengine.module.entities.GraphicEntityModule;
9 import com.codingame.gameengine.module.entities.Rectangle;
10 import com.codingame.gameengine.module.entities.Sprite;
11 import com.codingame.gameengine.module.entities.SpriteAnimation;
12 import com.codingame.gameengine.module.entities.Text;
13 import com.codingame.gameengine.module.entities.Group;
14 import com.codingame.gameengine.module.entities.Curve;
15 import com.codingame.gameengine.module.toggle.ToggleModule;
16 import com.google.inject.Inject;
17
18 class View {
19     @Inject private MultiplayerGameManager<com.codingame.game.Player> gameManager;
20     @Inject private GraphicEntityModule graphicEntityModule;
21     @Inject ToggleModule toggleModule;
22
23     class Player {
24         Model.Player model;
25
26         int colorToken;
27         String nicknameToken;
28         String avatarToken;
29
30         double frameRot;
31
32         Group avatar;
33         Text stoneCounter;
34         Text message;
35         Sprite castle;
36         Text stone;
37         Text stoneReminder;
38
39         void init(com.codingame.game.Player p) {
40             model = p.model;
41             colorToken = p.getColorToken();
42             nicknameToken = p.getNicknameToken();
43             avatarToken = p.getAvatarToken();
44
45             boolean p0 = model.index == 0;
46             int x = p0 ? 280 : 1920 - 280;
47             int y = 220;
48
49             Sprite frame = graphicEntityModule.createSprite()
50                 .setImage("frame.png")
51                 .setAnchor(0.5)
52                 .setRotation(frameRot)
53                 .setZIndex(22)
54                 .setTint(colorToken);
55
56             Sprite frameBg = graphicEntityModule.createSprite()
57                 .setImage("frame_bg.png")
58                 .setAnchor(0.5)
59                 .setRotation(frameRot)
60                 .setZIndex(20);
61
62             Sprite avatarSprite = graphicEntityModule.createSprite()
63                 .setZIndex(21)
64                 .setImage(avatarToken)
65                 .setAnchor(0.5)
66                 .setBaseHeight(116)
67                 .setBaseWidth(116);
68
69             avatar = graphicEntityModule
70                 .createGroup(frame, frameBg, avatarSprite)
71                 .setX(x).setY(y);
72
73             Text text = graphicEntityModule.createText(nicknameToken)
74                     .setX(x)
75                     .setY(y + 120)
76                     .setZIndex(20)
77                     .setFontSize(40)
78                     .setFillColor(0x7f3f00)
79                     .setAnchor(0.5);
80
81             stoneCounter = graphicEntityModule.createText()
82                 .setX(x)
83                 .setY(y+200)
84                 .setZIndex(20)
85                 .setFontSize(40)
86                 .setFillColor(0x7f3f00)
87                 .setAnchor(0.5);
88             updateStoneCounter();
89
90             message = graphicEntityModule.createText()
91                 .setX(p0 ? 15 : 1920-15)
92                 .setY(680)
93                 .setZIndex(1)
94                 .setFontSize(40)
95                 .setFillColor(0xffbf7f)
96                 .setAnchorX(p0 ? 0 : 1)
97                 .setAnchorY(1);
98
99             castle = graphicEntityModule.createSprite()
100                 .setImage("castle.png")
101                 .setTint(colorToken)
102                 .setX(p0 ? 160 : 1920-160)
103                 .setY(p0 ? 890 : 880)
104                 .setZIndex(1)
105                 .setAnchorX(0.5)
106                 .setAnchorY(1)
107                 .setScaleX(p0 ? 1 : -1);
108
109             stone = graphicEntityModule.createText()
110                 .setZIndex(3)
111                 .setFontSize(150)
112                 .setFillColor(0x12322a)
113                 .setAnchor(0.5)
114                 .setAlpha(0);
115
116             stoneReminder = graphicEntityModule.createText()
117                 .setX(p0 ? x + 100 : x - 100)
118                 .setY(y)
119                 .setZIndex(20)
120                 .setFontSize(75)
121                 .setFillColor(0x3f3f3f)
122                 .setAnchorX(p0 ? 0 : 1)
123                 .setAnchorY(0.5);
124         }
125
126         void updateStoneCounter() {
127             int stones = model.getStones();
128             if (stones <= 0) {
129                 stoneCounter.setText("Out of stones!");
130                 stoneCounter.setFillColor(0xff7777);
131             }
132             else if (stones == 1) {
133                 stoneCounter.setText("1 stone");
134                 stoneCounter.setFillColor(0xffbb77);
135             }
136             else {
137                 stoneCounter.setText(stones + " stones");
138             }
139         }
140
141         void animateStones(int stones) {
142             String stonesString = new Integer(stones).toString();
143             stone.setX(castle.getX());
144             stone.setY(castle.getY() - 100);
145             stone.setText(stonesString);
146             stone.setAlpha(1);
147             graphicEntityModule.commitEntityState(0, stone);
148     
149             int peakX = (castle.getX() + troll.getX()) / 2;
150             int peakY = 540;
151             stone.setX(peakX);
152             stone.setY(peakY, Curve.EASE_OUT);
153             graphicEntityModule.commitEntityState(0.25,
154                                                   stone,
155                                                   stoneCounter);
156     
157             stone.setX(troll.getX());
158             stone.setY(troll.getY() - 50, Curve.EASE_IN);
159             stone.setAlpha(0, Curve.EASE_IN);
160             graphicEntityModule.commitEntityState(0.5, stone);
161
162             stoneReminder.setText(stonesString);
163             graphicEntityModule.commitEntityState(0.25, stoneReminder);
164             stoneReminder.setAlpha(1);
165             graphicEntityModule.commitEntityState(0.5, stoneReminder);
166         }
167
168         void displayMessage(String msg) {
169             message.setText(msg);
170             graphicEntityModule.commitEntityState(0, message);
171         }
172
173         void markLoser() {
174             graphicEntityModule.commitEntityState(0.5, avatar);
175             int dir = random.nextInt(2) == 1 ? 1 : -1;
176             avatar.setRotation(dir * 170 * Math.PI / 180, Curve.ELASTIC);
177         }
178
179         void destroy() {
180             graphicEntityModule.commitEntityState(0.5, castle);
181             castle.setX(castle.getX(), Curve.ELASTIC);
182             castle.setScaleY(-0.2, Curve.EASE_IN);
183         }
184
185         void startTurn() {
186             stoneReminder.setAlpha(0);
187             graphicEntityModule.commitEntityState(0, stoneReminder);
188         }
189     }
190
191     Model model;
192     Random random = new Random();
193     Sprite troll;
194     Text trollPositionGauge;
195     Player p0 = new Player(), p1 = new Player();
196
197     void init(Model m) {
198         model = m;
199         drawBackground();
200
201         /*
202          * Random π/2-grained rotation of the avatar frames.  Avoid
203          * having them π/2 apart, though, as one of them is likely
204          * going to end upside-down and the trick would be revealed.
205          * And I'd have to "draw" a new frame. Ewww.
206          */
207         p0.frameRot = random.nextInt(4) * Math.PI / 2;
208         p0.init(gameManager.getPlayer(0));
209         p1.frameRot = p1.frameRot +
210             (random.nextInt(2) == 1 ? 1 : -1) * Math.PI / 2;
211         p1.init(gameManager.getPlayer(1));
212
213         drawTroll();
214
215         drawDebug();
216     }
217
218     void startTurn() {
219         p0.startTurn();
220         p1.startTurn();
221     }
222
223     private class Pos {
224         int x, y;
225         Pos(int _x, int _y) { x = _x; y = _y; }
226     }
227
228     private void drawBackground() {
229         graphicEntityModule.createSprite()
230                 .setImage("background.png")
231                 .setAnchor(0);
232
233         int numTrees = random.nextInt(21);
234         ArrayList<Pos> poss = new ArrayList<Pos>(numTrees);
235         while (numTrees --> 0) {
236             int x, y;
237             do {
238                 x = random.nextInt(1920);
239                 // yes, this biases randomness wrt perspective! :-(
240                 y = 700 + random.nextInt(175);
241             } while (y > 880 && (x < 200 || x > 1720));
242             poss.add(new Pos(x, y));
243         }
244         poss.sort(new Comparator<Pos>() {
245                 public int compare(Pos a, Pos b) { return a.y < b.y ? -1 : 1; }
246             });
247
248         for (Pos p : poss) {
249             double scale = ( 90.0 / 433.0           // base height from PNG
250                              * (p.y - 680) / (875 - 680) ); // perspective
251             graphicEntityModule.createSprite()
252                 .setImage(random.nextInt(2) == 0 ? "Alshockv1.png"
253                                                  : "Alshockv2.png")
254                 .setAnchorX(0.5)
255                 .setAnchorY(1)
256                 .setX(p.x)
257                 .setY(p.y)
258                 .setScaleX(scale * (random.nextInt(2) == 0 ? -1 : 1)
259                            * (1 + (random.nextDouble() - 0.5) / 6))
260                 .setScaleY(scale * (1 + (random.nextDouble() -0.5) / 6))
261                 .setRotation((random.nextDouble() - 0.5) * Math.PI / 1800)
262                 .setSkewX((random.nextDouble() - 0.5) /4)
263                 .setSkewY((random.nextDouble() - 0.5) /8);
264         }
265     }
266
267     private void drawTroll() {
268         troll = graphicEntityModule.createSprite()
269             .setImage("troll.png")
270             .setAnchorX(0.5)
271             .setAnchorY(1)
272             .setX(1920/2)
273             .setY(880)
274             .setZIndex(2);
275         trollPositionGauge = graphicEntityModule.createText()
276             .setZIndex(2)
277             .setAnchor(0.5)
278             .setFontSize(40)
279             .setX(1980/2)
280             .setY(980)
281             .setFillColor(0xffffff);
282
283         moveTroll();
284     }
285
286     void moveTroll() {
287         graphicEntityModule.commitEntityState(0.5, troll, trollPositionGauge);
288         int x0 = p0.castle.getX(), x1 = p1.castle.getX();
289         int y0 = p0.castle.getY(), y1 = p1.castle.getY();
290         troll.setX(x0 + model.trollPosition * (x1-x0) / model.roadLength,
291                    Curve.ELASTIC);
292         troll.setY(y0 + model.trollPosition * (y1-y0) / model.roadLength,
293                    Curve.ELASTIC);
294
295         trollPositionGauge.setX((trollPositionGauge.getX() + troll.getX()) / 2);
296         int distLeft = model.trollPosition;
297         int distRight = model.roadLength - model.trollPosition;
298         if (distLeft <= 0) {
299             trollPositionGauge.setText("← " + distRight);
300         }
301         else if (distRight <= 0) {
302             trollPositionGauge.setText(distLeft + " →");
303         }
304         else {
305             trollPositionGauge.setText(distLeft + " ↔ " + distRight);
306         }
307         graphicEntityModule.commitEntityState(0.75, trollPositionGauge);
308         trollPositionGauge.setX(troll.getX());
309     }
310
311     void drawDebug() {
312         String[] debugModePngs = graphicEntityModule.createSpriteSheetSplitter()
313             .setSourceImage("debug.png")
314             .setImageCount(2)
315             .setWidth(900)
316             .setHeight(150)
317             .setOrigRow(0)
318             .setOrigCol(0)
319             .setImagesPerRow(1)
320             .setName("debug")
321             .split();
322         SpriteAnimation debugMode = graphicEntityModule.createSpriteAnimation()
323             .setImages(debugModePngs)
324             .setX(1920 / 2)
325             .setY(80)
326             .setAnchorX(0.5)
327             .setLoop(true);
328         toggleModule.displayOnToggleState(debugMode, "debug", true);
329     }
330 }