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