Mercurial > hg > ristipolku
annotate game/Engine.java @ 35:aa15b2c556b4
Add comments.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 17 Feb 2011 03:40:01 +0200 |
parents | e480579cc460 |
children | 3dc5ae9f1c80 |
rev | line source |
---|---|
0 | 1 /* |
9 | 2 * Ristipolku Game Engine |
0 | 3 * (C) Copyright 2011 Matti 'ccr' Hämäläinen <ccr@tnsp.org> |
4 */ | |
9 | 5 package game; |
6 | |
0 | 7 import java.awt.*; |
8 import java.awt.geom.*; | |
1 | 9 import java.awt.event.*; |
7 | 10 import java.awt.image.*; |
11 import java.awt.event.*; | |
25 | 12 import java.awt.font.*; |
9 | 13 import javax.imageio.*; |
7 | 14 import javax.swing.*; |
1 | 15 import java.util.*; |
6 | 16 import java.io.*; |
1 | 17 import game.*; |
18 | |
21 | 19 |
1 | 20 class PathInfo |
21 { | |
2 | 22 public int in, inX, inY, out, outX, outY; |
1 | 23 |
2 | 24 public PathInfo(int in, int inX, int inY, int out, int outX, int outY) |
25 { | |
26 this.in = in; | |
27 this.inX = inX; | |
28 this.inY = inY; | |
29 | |
30 this.out = out; | |
31 this.outX = outX; | |
32 this.outY = outY; | |
33 } | |
27 | 34 |
35 public void print() | |
36 { | |
37 System.out.print("PathInfo: inP="+in+", inX="+inX+", inY="+inY+"\n"); | |
38 System.out.print(" outP="+out+", outX="+outX+", outY="+outY+"\n"); | |
39 } | |
1 | 40 } |
0 | 41 |
8 | 42 /* |
43 class AnimatedElement | |
44 { | |
45 float x, y, stime, value; | |
46 Interpolate lerp; | |
47 boolean active; | |
48 | |
49 public AnimatedElement(float x, float y, ) | |
50 { | |
51 stime = 0; | |
52 this.x = x; | |
53 this.y = y; | |
54 | |
55 } | |
56 | |
57 public animate(float time) | |
58 { | |
59 if (!active) | |
60 { | |
61 active = true; | |
62 stime = time; | |
63 } | |
64 | |
65 float t = (time - stime) / 10.0f; | |
66 if (t < 100) | |
67 value = lerp.getValue(t); | |
68 else | |
69 { | |
70 | |
71 } | |
72 } | |
73 | |
74 public paint(Graphics2D g, ); | |
75 { | |
76 } | |
77 } | |
78 */ | |
0 | 79 |
30 | 80 class IDMWidget |
81 { | |
82 public IDMWidget() | |
83 { | |
84 } | |
85 | |
86 public void paint(Graphics2D g) | |
87 { | |
88 } | |
89 | |
90 public boolean hit(float x, float y) | |
91 { | |
92 return false; | |
93 } | |
94 } | |
95 | |
96 class IDMButton | |
97 { | |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
98 BufferedImage imgUp, imgPressed; |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
99 |
30 | 100 public IDMButton(float x, float y, String text) |
101 { | |
102 } | |
103 | |
104 public void paint(Graphics2D g) | |
105 { | |
106 } | |
107 | |
108 public boolean hit(float x, float y) | |
109 { | |
110 return false; | |
111 } | |
112 } | |
113 | |
1 | 114 class GameBoard |
0 | 115 { |
2 | 116 public static final int boardSize = 9; |
117 public static final int boardMiddle = 4; | |
118 Piece[][] board; | |
119 Piece current; | |
8 | 120 public boolean flagGameOver; |
7 | 121 |
122 int moveX, moveY, movePoint; | |
9 | 123 |
2 | 124 public GameBoard() |
125 { | |
126 board = new Piece[boardSize][boardSize]; | |
127 | |
128 board[boardMiddle][boardMiddle] = new Piece(PieceType.START); | |
129 | |
130 moveX = boardMiddle; | |
131 moveY = boardMiddle - 1; | |
30 | 132 movePoint = 5; |
8 | 133 |
9 | 134 pieceFinishTurn(); |
8 | 135 |
136 flagGameOver = false; | |
2 | 137 } |
0 | 138 |
7 | 139 public void paint(Graphics2D g, int sx, int sy, float scale) |
2 | 140 { |
141 for (int y = 0; y < boardSize; y++) | |
142 for (int x = 0; x < boardSize; x++) | |
143 if (board[x][y] != null) | |
144 { | |
6 | 145 AffineTransform save = g.getTransform(); |
146 | |
4 | 147 board[x][y].paint(g, |
148 sx + (x * scale), | |
149 sy + (y * scale), | |
150 scale - scale / 10); | |
6 | 151 |
152 g.setTransform(save); | |
2 | 153 } |
154 } | |
9 | 155 |
156 public void animate(float time) | |
157 { | |
158 for (int y = 0; y < boardSize; y++) | |
159 for (int x = 0; x < boardSize; x++) | |
160 if (board[x][y] != null) | |
161 { | |
162 board[x][y].animate(time); | |
163 } | |
10 | 164 |
9 | 165 } |
1 | 166 |
2 | 167 private boolean isEmpty(int x, int y) |
168 { | |
169 return (x >= 0 && x < boardSize && y >= 0 && y < boardSize && board[x][y] == null); | |
170 } | |
1 | 171 |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
172 public void pieceRotate(Piece.RotateDir dir) |
2 | 173 { |
9 | 174 if (current != null) |
175 current.rotate(dir); | |
2 | 176 } |
1 | 177 |
8 | 178 public PathInfo resolvePath(int startX, int startY, int startPoint, boolean mark) |
7 | 179 { |
180 int x = startX, y = startY; | |
27 | 181 int point = startPoint; |
182 Piece curr = board[x][y]; | |
9 | 183 |
27 | 184 do |
7 | 185 { |
27 | 186 if (x >= 0 && x < boardSize && y >= 0 && y < boardSize) |
187 { | |
188 curr = board[x][y]; | |
189 if (curr == null) | |
190 break; | |
191 | |
192 if (curr.getType() == PieceType.START) | |
193 { | |
194 // Hit center starting piece | |
195 return null; | |
196 } | |
197 else | |
198 { | |
199 // Mark, if needed | |
200 if (mark) | |
201 { | |
202 curr.setType(PieceType.LOCKED); | |
203 curr.setActiveConnection(point); | |
204 } | |
205 | |
206 // Get next piece | |
207 point = curr.getConnection(point); | |
208 switch (point) | |
209 { | |
210 case 0: y--; break; | |
211 case 1: y--; break; | |
212 case 2: x++; break; | |
213 case 3: x++; break; | |
214 case 4: y++; break; | |
215 case 5: y++; break; | |
216 case 6: x--; break; | |
217 case 7: x--; break; | |
218 } | |
219 } | |
220 } | |
221 else | |
222 { | |
223 // Outside of the board | |
224 return null; | |
225 } | |
7 | 226 } |
27 | 227 while (curr != null); |
228 | |
7 | 229 return new PathInfo(startPoint, startX, startY, point, x, y); |
230 } | |
231 | |
2 | 232 public void pieceFinishTurn() |
233 { | |
35 | 234 // Do we have a piece? |
2 | 235 if (current != null) |
7 | 236 { |
35 | 237 // Yes, place and lock it |
6 | 238 current.setType(PieceType.LOCKED); |
8 | 239 PathInfo i = resolvePath(moveX, moveY, movePoint, true); |
7 | 240 |
241 if (i != null) | |
242 { | |
27 | 243 System.out.print("moveX="+moveX+", moveY="+moveY+", movePoint="+movePoint+"\n"); |
244 i.print(); | |
245 moveX = i.outX; | |
246 moveY = i.outY; | |
247 movePoint = i.out; | |
7 | 248 } |
249 } | |
250 | |
35 | 251 // Create a new piece |
8 | 252 current = new Piece(PieceType.ACTIVE); |
35 | 253 |
254 // Find a place for it | |
7 | 255 if (isEmpty(moveX, moveY)) |
2 | 256 { |
35 | 257 // Current position is empty, use it |
8 | 258 board[moveX][moveY] = current; |
259 } | |
260 else | |
261 { | |
35 | 262 // Resolve path |
8 | 263 PathInfo i = resolvePath(moveX, moveY, movePoint, true); |
264 if (i != null) | |
265 board[moveX][moveY] = current; | |
266 else | |
27 | 267 { |
35 | 268 // Path ended up center/gameboard walls - it's game over, man |
27 | 269 System.out.print("pieceFinishTurn(): Game Over!\n"); |
8 | 270 flagGameOver = true; |
27 | 271 } |
2 | 272 } |
1 | 273 } |
274 } | |
275 | |
276 | |
9 | 277 public class Engine extends JPanel |
18 | 278 implements Runnable, KeyListener, MouseListener |
1 | 279 { |
25 | 280 long startTime; |
281 float gameClock, gameFrames; | |
8 | 282 Thread animThread; |
283 boolean animEnable = false; | |
25 | 284 |
285 Font fontMain, font1, font2; | |
4 | 286 GameBoard lauta = null; |
9 | 287 BufferedImage lautaBG = null, lautaBGScaled = null; |
25 | 288 Dimension lautaDim; |
22 | 289 |
21 | 290 SoundElement[] sounds; |
25 | 291 |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
292 Piece testi; int con = 0; |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
293 |
21 | 294 public SoundElement snd(Sound snd) |
295 { | |
296 return sounds[snd.ordinal()]; | |
297 } | |
1 | 298 |
9 | 299 public Engine() |
2 | 300 { |
25 | 301 // Initialize globals |
302 System.out.print("Engine() constructor\n"); | |
303 | |
304 gameClock = 0; | |
305 gameFrames = 0; | |
306 startTime = new Date().getTime(); | |
4 | 307 |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
308 testi = new Piece(PieceType.LOCKED); |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
309 |
9 | 310 |
25 | 311 // Load resources |
4 | 312 try |
313 { | |
24 | 314 ResourceLoader res = new ResourceLoader("graphics/board.jpg"); |
18 | 315 lautaBG = ImageIO.read(res.getStream()); |
21 | 316 |
25 | 317 try { |
318 res = new ResourceLoader("graphics/font.ttf"); | |
319 fontMain = Font.createFont(Font.TRUETYPE_FONT, res.getStream()); | |
320 font1 = fontMain.deriveFont(24f); | |
321 font2 = fontMain.deriveFont(32f); | |
322 } | |
323 catch (FontFormatException e) | |
324 { | |
325 System.out.print("Could not initialize fonts.\n"); | |
326 } | |
327 | |
21 | 328 sounds = new SoundElement[16]; |
329 for (Sound s : Sound.values()) | |
330 { | |
331 System.out.print(s +" = "+ s.ordinal() +"\n"); | |
23
0741dc117808
Remove sound code for later refactoring.
Matti Hamalainen <ccr@tnsp.org>
parents:
22
diff
changeset
|
332 sounds[s.ordinal()] = new SoundElement("sounds/" + s.getName(), s.isStreaming()); |
21 | 333 } |
4 | 334 } |
335 catch (IOException e) | |
336 { | |
18 | 337 /* |
4 | 338 JOptionPane.showMessageDialog(null, |
21 | 339 e.getMessage(), |
4 | 340 "Initialization error", |
341 JOptionPane.ERROR_MESSAGE); | |
18 | 342 */ |
21 | 343 System.out.print(e.getMessage()); |
18 | 344 } |
345 | |
346 lauta = new GameBoard(); | |
347 addKeyListener(this); | |
348 addMouseListener(this); | |
349 | |
350 // Get initial focus | |
351 if (!hasFocus()) | |
352 { | |
353 System.out.print("Engine(): requesting focus\n"); | |
354 requestFocus(); | |
4 | 355 } |
22 | 356 |
21 | 357 snd(Sound.MUSIC_GAME1).loop(-1); |
8 | 358 } |
359 | |
25 | 360 |
361 public void paintComponent(Graphics g) | |
362 { | |
363 Graphics2D g2 = (Graphics2D) g; | |
364 | |
365 // Use antialiasing when rendering the game elements | |
366 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
367 RenderingHints.VALUE_ANTIALIAS_ON); | |
368 | |
369 g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, | |
370 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); | |
371 | |
372 // Rescale background if component size has changed | |
373 Dimension dim = getSize(); | |
374 if (lautaDim == null || !dim.equals(lautaDim)) | |
375 { | |
376 lautaBGScaled = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB); | |
377 Graphics2D gimg = lautaBGScaled.createGraphics(); | |
378 gimg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, | |
379 RenderingHints.VALUE_INTERPOLATION_BICUBIC); | |
380 | |
381 gimg.drawImage(lautaBG, 0, 0, dim.width, dim.height, null); | |
382 lautaDim = dim; | |
383 | |
384 System.out.print("scale changed\n"); | |
385 } | |
386 | |
387 // Background, pieces | |
388 g2.drawImage(lautaBGScaled, 0, 0, null); | |
389 lauta.paint(g2, 100, 150, 60); | |
390 | |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
391 testi.paint(g2, 50f,50f,100f); |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
392 |
25 | 393 // Scores |
394 g2.setFont(font1); | |
395 g2.setPaint(Color.white); | |
396 | |
397 | |
398 // Other elements | |
399 long currTime = new Date().getTime(); | |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
400 g2.drawString("fps = "+ ((gameFrames * 1000) / (currTime - startTime)), dim.width - 120, 20); |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
401 |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
402 g2.drawString("con = "+ con, 20, 30); |
25 | 403 } |
404 | |
8 | 405 public void startThreads() |
406 { | |
9 | 407 System.out.print("startThreads()\n"); |
8 | 408 if (animThread == null) |
409 { | |
410 animThread = new Thread(this); | |
411 animEnable = true; | |
412 animThread.start(); | |
413 } | |
414 } | |
415 | |
416 public void stopThreads() | |
417 { | |
9 | 418 System.out.print("stopThreads()\n"); |
8 | 419 if (animThread != null) |
420 { | |
421 animThread.interrupt(); | |
422 animEnable = false; | |
423 animThread = null; | |
424 } | |
22 | 425 |
426 for (Sound s : Sound.values()) | |
427 { | |
428 if (snd(s) != null) | |
429 snd(s).stop(); | |
430 } | |
2 | 431 } |
0 | 432 |
18 | 433 public void mousePressed(MouseEvent e) { } |
434 public void mouseEntered(MouseEvent e) { } | |
435 public void mouseExited(MouseEvent e) { } | |
436 public void mouseReleased(MouseEvent e) { } | |
437 | |
438 public void mouseClicked(MouseEvent e) | |
439 { | |
440 System.out.print("mouseClicked()\n"); | |
441 if (!hasFocus()) | |
442 { | |
443 System.out.print("requesting focus\n"); | |
444 requestFocus(); | |
445 } | |
446 } | |
447 | |
9 | 448 public void keyTyped(KeyEvent e) |
2 | 449 { |
450 } | |
1 | 451 |
2 | 452 public void keyReleased(KeyEvent e) |
453 { | |
454 } | |
1 | 455 |
9 | 456 public void keyPressed(KeyEvent e) |
2 | 457 { |
26
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
458 // Handle keyboard input |
7 | 459 switch (e.getKeyCode()) |
2 | 460 { |
7 | 461 case KeyEvent.VK_LEFT: |
462 case KeyEvent.VK_UP: | |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
463 lauta.pieceRotate(Piece.RotateDir.LEFT); |
2 | 464 break; |
0 | 465 |
7 | 466 case KeyEvent.VK_RIGHT: |
467 case KeyEvent.VK_DOWN: | |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
468 lauta.pieceRotate(Piece.RotateDir.RIGHT); |
2 | 469 break; |
470 | |
7 | 471 case KeyEvent.VK_ENTER: |
2 | 472 lauta.pieceFinishTurn(); |
23
0741dc117808
Remove sound code for later refactoring.
Matti Hamalainen <ccr@tnsp.org>
parents:
22
diff
changeset
|
473 snd(Sound.PIECE_PLACED).stop(); |
0741dc117808
Remove sound code for later refactoring.
Matti Hamalainen <ccr@tnsp.org>
parents:
22
diff
changeset
|
474 snd(Sound.PIECE_PLACED).play(); |
2 | 475 break; |
35 | 476 |
477 case KeyEvent.VK_ESCAPE: | |
478 break; | |
2 | 479 } |
480 } | |
8 | 481 |
482 public void run() | |
483 { | |
484 while (animEnable) | |
485 { | |
26
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
486 // Progress game animation clock |
25 | 487 gameClock++; |
9 | 488 |
26
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
489 // Animate components |
25 | 490 lauta.animate(gameClock); |
9 | 491 |
26
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
492 // Repaint with a frame limiter |
25 | 493 if (gameClock % 3 == 1) |
24 | 494 { |
10 | 495 repaint(); |
25 | 496 gameFrames++; |
24 | 497 } |
32
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
498 |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
499 // debugataan |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
500 con = ((int) (gameClock / 100)) & 7; |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
501 testi.clearActiveConnections(); |
e480579cc460
More work on debugging the path resolving.
Matti Hamalainen <ccr@tnsp.org>
parents:
30
diff
changeset
|
502 testi.setActiveConnection(con); |
26
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
503 |
3d4cc47df31a
Cleanups, fix piece rendering and rotation.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
504 // Sleep for a moment |
9 | 505 try { |
506 Thread.sleep(10); | |
507 } | |
508 catch (InterruptedException x) { | |
509 } | |
8 | 510 } |
511 } | |
0 | 512 } |