Mercurial > hg > ristipolku
comparison game/Piece.java @ 162:e8eeac403e5f
Backed out changeset fb33d3796942
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 01 Dec 2016 14:33:25 +0200 |
parents | src/Piece.java@fb33d3796942 |
children | 7bf508d363bd |
comparison
equal
deleted
inserted
replaced
161:fb33d3796942 | 162:e8eeac403e5f |
---|---|
1 /* | |
2 * Ristipolku | |
3 * (C) Copyright 2011 Matti 'ccr' Hämäläinen <ccr@tnsp.org> | |
4 */ | |
5 package game; | |
6 | |
7 import java.awt.*; | |
8 import java.awt.geom.*; | |
9 import java.util.*; | |
10 import java.math.*; | |
11 | |
12 | |
13 public class Piece | |
14 { | |
15 public enum RotateDir { LEFT, RIGHT } | |
16 | |
17 static final int numConnections = 8; | |
18 static final float maxTime = 50.0f; | |
19 | |
20 int currRotation; | |
21 int[] connections; | |
22 boolean[] states; | |
23 PieceType type, prevType; | |
24 | |
25 boolean rotationChanged, rotationActive, | |
26 typeChanged, typeActive, | |
27 stateChanged, stateActive, | |
28 active; | |
29 | |
30 float currAngle, rotationTime, rotationSpeed, | |
31 typeTime, typeValue, throbTime; | |
32 | |
33 Interpolate lerpRotation, | |
34 lerpScale, | |
35 lerpType; | |
36 | |
37 | |
38 public Piece(PieceType ptype) | |
39 { | |
40 // Initialize | |
41 connections = new int[numConnections]; | |
42 states = new boolean[numConnections]; | |
43 type = ptype; | |
44 | |
45 rotationChanged = false; | |
46 rotationActive = false; | |
47 currRotation = 4 * 5000; | |
48 currAngle = getAngle(currRotation); | |
49 | |
50 typeChanged = false; | |
51 typeActive = false; | |
52 | |
53 throbTime = 0; | |
54 | |
55 lerpType = new Interpolate(1.0f, 0.0f, maxTime); | |
56 lerpScale = new Interpolate(0.0f, (float) Math.PI, maxTime); | |
57 | |
58 // Initialize connections between endpoints of the paths inside the piece | |
59 for (int i = 0; i < numConnections; i++) | |
60 connections[i] = -1; | |
61 | |
62 | |
63 // Randomize connections in the piece | |
64 Random rnd = new Random(); | |
65 for (int i = 0; i < numConnections; i++) | |
66 { | |
67 while (connections[i] < 0) | |
68 { | |
69 int tmp = rnd.nextInt(numConnections); | |
70 if (tmp != i && connections[tmp] < 0) | |
71 { | |
72 connections[i] = tmp; | |
73 connections[tmp] = i; | |
74 } | |
75 } | |
76 } | |
77 } | |
78 | |
79 public Piece() | |
80 { | |
81 this(PieceType.NONE); | |
82 } | |
83 | |
84 | |
85 public void changed() | |
86 { | |
87 typeChanged = true; | |
88 } | |
89 | |
90 public void setType(PieceType ptype) | |
91 { | |
92 // typeChanged = (prevType != ptype) && (ptype == PieceType.LOCKED); | |
93 prevType = type; | |
94 type = ptype; | |
95 } | |
96 | |
97 public void clearStates() | |
98 { | |
99 for (int i = 0; i < numConnections; i++) | |
100 states[i] = false; | |
101 stateChanged = true; | |
102 } | |
103 | |
104 public int getRotation() | |
105 { | |
106 return currRotation % 4; | |
107 } | |
108 | |
109 public int getRotatedPoint(int in) | |
110 { | |
111 int point = (in - (getRotation() * 2)) % 8; | |
112 if (point < 0) point = 8 + point; | |
113 return point; | |
114 } | |
115 | |
116 public int getAntiRotatedPoint(int in) | |
117 { | |
118 int point = (in + (getRotation() * 2)) % 8; | |
119 if (point < 0) point = 8 + point; | |
120 return point; | |
121 } | |
122 | |
123 public int getMatchingPoint(int point) | |
124 { | |
125 switch (point) | |
126 { | |
127 case 0: return 5; | |
128 case 1: return 4; | |
129 | |
130 case 2: return 7; | |
131 case 3: return 6; | |
132 | |
133 case 4: return 1; | |
134 case 5: return 0; | |
135 | |
136 case 6: return 3; | |
137 case 7: return 2; | |
138 } | |
139 return -1; | |
140 } | |
141 | |
142 public void setConnectionState(int point, boolean state) | |
143 { | |
144 states[point] = state; | |
145 states[connections[point]] = state; | |
146 stateChanged = true; | |
147 } | |
148 | |
149 public int getConnection(int point) | |
150 { | |
151 return connections[point]; | |
152 } | |
153 | |
154 private float getAngle(float rotation) | |
155 { | |
156 return (float) ((rotation * Math.PI) / 2.0f); | |
157 } | |
158 | |
159 public void rotate(RotateDir dir) | |
160 { | |
161 // Only normal | |
162 if (type != PieceType.LOCKED && type != PieceType.ACTIVE) | |
163 return; | |
164 | |
165 currRotation = (currRotation + (dir == RotateDir.RIGHT ? 1 : -1)); | |
166 lerpRotation = new Interpolate(getAngle(currRotation), currAngle, maxTime); | |
167 rotationChanged = true; | |
168 } | |
169 | |
170 public Point2D getPointCoords(float x, float y, float dim, int index) | |
171 { | |
172 float ox = 0, oy = 0; | |
173 float step = dim / 10; | |
174 | |
175 switch (index) { | |
176 // Normal line starting and ending points | |
177 case 0: ox = 3.0f; oy = 0.4f; break; | |
178 case 1: ox = 7.0f; oy = 0.4f; break; | |
179 | |
180 case 2: ox = 9.6f; oy = 3.0f; break; | |
181 case 3: ox = 9.6f; oy = 7.0f; break; | |
182 | |
183 case 4: ox = 7.0f; oy = 9.6f; break; | |
184 case 5: ox = 3.0f; oy = 9.6f; break; | |
185 | |
186 case 6: ox = 0.4f; oy = 7.0f; break; | |
187 case 7: ox = 0.4f; oy = 3.0f; break; | |
188 | |
189 | |
190 // Matching control points for each point above (+8) | |
191 case 8: ox = 3.0f; oy = 2.5f; break; | |
192 case 9: ox = 7.0f; oy = 2.5f; break; | |
193 | |
194 case 10: ox = 7.5f; oy = 3.0f; break; | |
195 case 11: ox = 7.5f; oy = 7.0f; break; | |
196 | |
197 case 12: ox = 7.0f; oy = 7.5f; break; | |
198 case 13: ox = 3.0f; oy = 7.5f; break; | |
199 | |
200 case 14: ox = 2.5f; oy = 7.0f; break; | |
201 case 15: ox = 2.5f; oy = 3.0f; break; | |
202 } | |
203 | |
204 return new Point2D.Float(x + ox * step, y + oy * step); | |
205 } | |
206 | |
207 public PieceType getType() | |
208 { | |
209 return type; | |
210 } | |
211 | |
212 public void animate(float time) | |
213 { | |
214 active = false; | |
215 | |
216 if (rotationChanged) | |
217 { | |
218 rotationTime = time; | |
219 rotationActive = true; | |
220 rotationChanged = false; | |
221 rotationSpeed = 1.0f; | |
222 } | |
223 | |
224 if (typeChanged && type == PieceType.LOCKED) | |
225 { | |
226 rotationSpeed = 1.5f; | |
227 } | |
228 | |
229 if (rotationActive) | |
230 { | |
231 float t = (time - rotationTime) * rotationSpeed; | |
232 | |
233 if (t < maxTime) | |
234 { | |
235 currAngle = lerpRotation.getValue(t); | |
236 } | |
237 else | |
238 { | |
239 currAngle = lerpRotation.start; | |
240 rotationActive = false; | |
241 } | |
242 | |
243 active = true; | |
244 } | |
245 | |
246 if (typeChanged) | |
247 { | |
248 typeTime = time; | |
249 typeActive = true; | |
250 typeChanged = false; | |
251 } | |
252 | |
253 if (typeActive) | |
254 { | |
255 float t = (time - typeTime) * 2.0f; | |
256 | |
257 if (t < maxTime) | |
258 { | |
259 typeValue = lerpType.getValue(t); | |
260 } | |
261 else | |
262 { | |
263 typeValue = lerpType.start; | |
264 typeActive = false; | |
265 } | |
266 | |
267 | |
268 active = true; | |
269 } | |
270 | |
271 if (stateChanged) | |
272 { | |
273 } | |
274 | |
275 throbTime = (time % 100) / 100.0f; | |
276 } | |
277 | |
278 public void paint(Graphics2D g, float x, float y, float dim) | |
279 { | |
280 AffineTransform save = g.getTransform(); | |
281 Composite csave = g.getComposite(); | |
282 | |
283 | |
284 // Change compositing alpha for the whole piece drawing | |
285 // when the piece is being "introduced". | |
286 if (typeActive) | |
287 { | |
288 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, typeValue)); | |
289 } | |
290 | |
291 | |
292 // Transform drawing by current angle | |
293 g.rotate(currAngle, x + dim / 2.0f, y + dim / 2.0f); | |
294 | |
295 // Color piece by type | |
296 switch (type) { | |
297 case LOCKED: g.setPaint(new Color(0.3f, 0.8f, 0.3f, 0.35f)); break; | |
298 case ACTIVE: g.setPaint(new Color(0.9f, 0.3f, 0.3f, 0.35f)); break; | |
299 case START: g.setPaint(new Color(1.0f, 0.6f, 0.0f, 0.95f)); break; | |
300 } | |
301 | |
302 float corner = dim / 10.0f; | |
303 g.fill(new RoundRectangle2D.Float(x, y, dim, dim, corner, corner)); | |
304 | |
305 // Start pieces (center piece) have a different kind of border | |
306 // and no connections drawn inside | |
307 if (type == PieceType.START) | |
308 { | |
309 // Draw piece border | |
310 g.setPaint(Color.black); | |
311 g.setStroke(new BasicStroke(2.0f)); | |
312 g.draw(new RoundRectangle2D.Float(x, y, dim, dim, corner, corner)); | |
313 } | |
314 else | |
315 { | |
316 // Active piece has a throbbing "ghost" border | |
317 if (type == PieceType.ACTIVE) | |
318 { | |
319 float offs1 = throbTime * 10.0f, | |
320 offs2 = throbTime * 20.0f; | |
321 | |
322 g.setPaint(new Color(0.0f, 0.0f, 0.0f, (float) (1.0f - throbTime) )); | |
323 g.setStroke(new BasicStroke(2.0f + throbTime * 2.0f)); | |
324 g.draw(new RoundRectangle2D.Float( | |
325 x - offs1, y - offs1, | |
326 dim + offs2, dim + offs2, | |
327 corner, corner)); | |
328 } | |
329 | |
330 // Draw piece border | |
331 g.setPaint(new Color(0.0f, 0.0f, 0.0f, 0.6f)); | |
332 g.setStroke(new BasicStroke(5.0f)); | |
333 g.draw(new RoundRectangle2D.Float(x, y, dim, dim, dim / 10, dim / 10)); | |
334 | |
335 // Draw the connections | |
336 g.setStroke(new BasicStroke(5.5f)); | |
337 CubicCurve2D curve = new CubicCurve2D.Float(); | |
338 boolean[] drawn = new boolean[numConnections]; | |
339 for (int i = 0; i < numConnections; i++) | |
340 if (!drawn[i]) | |
341 { | |
342 Point2D start, cp1, cp2, end; | |
343 boolean isActive = states[i] || states[connections[i]]; | |
344 | |
345 g.setPaint(isActive ? Color.white : Color.black); | |
346 | |
347 start = getPointCoords(x, y, dim, i); | |
348 end = getPointCoords(x, y, dim, connections[i]); | |
349 cp1 = getPointCoords(x, y, dim, i + 8); | |
350 cp2 = getPointCoords(x, y, dim, connections[i] + 8); | |
351 | |
352 curve.setCurve(start, cp1, cp2, end); | |
353 g.draw(curve); | |
354 | |
355 // Mark connection drawn, so we don't overdraw | |
356 drawn[i] = true; | |
357 drawn[connections[i]] = true; | |
358 } | |
359 | |
360 } // !PieceType.START | |
361 | |
362 g.setTransform(save); | |
363 g.setComposite(csave); | |
364 } | |
365 } |