Mercurial > hg > ristipolku
view game/Engine.java @ 57:1435e9d7fd1a
Bugfix.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 23 Feb 2011 20:36:07 +0200 |
parents | 8718cc1c6586 |
children | fd10a9422b60 |
line wrap: on
line source
/* * Ristipolku Game Engine * (C) Copyright 2011 Matti 'ccr' Hämäläinen <ccr@tnsp.org> */ package game; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import java.awt.image.*; import java.awt.event.*; import java.awt.font.*; import javax.imageio.*; import javax.swing.*; import java.util.*; import java.io.*; import game.*; import javax.sound.sampled.*; /* class AnimatedElement { float x, y, stime, value; Interpolate lerp; boolean active; public AnimatedElement(float x, float y, ) { stime = 0; this.x = x; this.y = y; } public animate(float time) { if (!active) { active = true; stime = time; } float t = (time - stime) / 10.0f; if (t < 100) value = lerp.getValue(t); else { } } public paint(Graphics2D g, ); { } } */ class GameBoard extends IDMWidget { public static final int boardSize = 9; public static final int boardMiddle = 4; Piece[][] board; public boolean flagGameOver; public int gameScore; public Piece currPiece, nextPiece; int currX, currY, currPoint; SoundManager soundManager; Sound sndPlaced; public GameBoard(SoundManager smgr) { board = new Piece[boardSize][boardSize]; board[boardMiddle][boardMiddle] = new Piece(PieceType.START); currX = boardMiddle; currY = boardMiddle; currPoint = 0; nextPiece = new Piece(PieceType.ACTIVE); pieceFinishTurn(); flagGameOver = false; gameScore = 0; soundManager = smgr; // sndPlaced = soundManager.getSound("sounds/placed.wav"); } public void paint(Graphics2D g, float sx, float sy, float scale) { for (int y = 0; y < boardSize; y++) for (int x = 0; x < boardSize; x++) if (board[x][y] != null) { AffineTransform save = g.getTransform(); board[x][y].paint(g, sx + (x * scale), sy + (y * scale), scale - scale / 10); g.setTransform(save); } } public void animate(float time) { for (int y = 0; y < boardSize; y++) for (int x = 0; x < boardSize; x++) if (board[x][y] != null) { board[x][y].animate(time); } } public void pieceRotate(Piece.RotateDir dir) { if (currPiece != null) currPiece.rotate(dir); } private void pieceMoveTo(int point) { switch (point) { case 0: currY--; break; case 1: currY--; break; case 2: currX++; break; case 3: currX++; break; case 4: currY++; break; case 5: currY++; break; case 6: currX--; break; case 7: currX--; break; } } public void pieceCreateNew() { currPiece = nextPiece; nextPiece = new Piece(PieceType.ACTIVE); } public void pieceSwapCurrent() { if (!flagGameOver) { Piece tmp = currPiece; currPiece = nextPiece; nextPiece = tmp; board[currX][currY] = currPiece; } } public boolean pieceCheck(Piece piece) { if (piece == null) { // Create new piece pieceCreateNew(); board[currX][currY] = currPiece; return true; } else if (piece.getType() == PieceType.START) { if (currPiece != null) { // Hit center starting piece, game over flagGameOver = true; return true; } else { // Start piece as first piece means game is starting pieceMoveTo(currPoint); pieceCreateNew(); board[currX][currY] = currPiece; return true; } } // Mark the current piece as locked piece.setType(PieceType.LOCKED); // Solve connection (with rotations) through the piece currPoint = piece.getRotatedPoint(piece.getMatchingPoint(currPoint)); // Mark connection as active piece.setConnectionState(currPoint, true); // Solve exit point (with rotations) currPoint = piece.getAntiRotatedPoint(piece.getConnection(currPoint)); // Move to next position accordingly pieceMoveTo(currPoint); return false; } public void pieceFinishTurn() { boolean finished = false; int connections = 0; while (!finished) { if (currX >= 0 && currX < boardSize && currY >= 0 && currY < boardSize) { connections++; finished = pieceCheck(board[currX][currY]); } else { // Outside of the board, game over finished = true; flagGameOver = true; } } gameScore += connections * connections; if (flagGameOver) { currPiece = null; System.out.print("GameOver!\n"); } } public boolean keyPressed(KeyEvent e) { if (flagGameOver) return false; switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: case KeyEvent.VK_UP: pieceRotate(Piece.RotateDir.LEFT); return true; case KeyEvent.VK_RIGHT: case KeyEvent.VK_DOWN: pieceRotate(Piece.RotateDir.RIGHT); return true; case KeyEvent.VK_ENTER: soundManager.play(sndPlaced); pieceFinishTurn(); return true; } return false; } } public class Engine extends JPanel implements Runnable, KeyListener, MouseListener { long startTime; float gameClock, gameFrames; Thread animThread; boolean animEnable = false; Font fontMain, font1, font2; FontMetrics metrics1, metrics2; GameBoard lauta = null; BufferedImage lautaBG = null, lautaBGScaled = null; Dimension lautaDim; static final AudioFormat sfmt = new AudioFormat(22050, 16, 1, true, false); SoundManager soundManager; Sound musa; IDMContainer widgets; public Engine() { // Initialize globals System.out.print("Engine() constructor\n"); // Sound system soundManager = new SoundManager(sfmt, 16); // Load resources try { ResourceLoader res = new ResourceLoader("graphics/board.jpg"); lautaBG = ImageIO.read(res.getStream()); try { res = new ResourceLoader("graphics/font.ttf"); fontMain = Font.createFont(Font.TRUETYPE_FONT, res.getStream()); font1 = fontMain.deriveFont(24f); font2 = fontMain.deriveFont(64f); } catch (FontFormatException e) { System.out.print("Could not initialize fonts.\n"); } // musa = soundManager.getSound("sounds/gamemusic.wav"); } catch (IOException e) { JOptionPane.showMessageDialog(null, e.getMessage(), "Initialization error", JOptionPane.ERROR_MESSAGE); System.out.print(e.getMessage()); } // Create IDM GUI widgets widgets = new IDMContainer(); widgets.add(new BtnSwapPiece(0.75f, 0.60f)); widgets.add(new BtnNewGame(0.75f, 0.85f)); // Game startNewGame(); // Initialize event listeners addKeyListener(this); addMouseListener(this); // Get initial focus if (!hasFocus()) { System.out.print("Engine(): requesting focus\n"); requestFocus(); } soundManager.play(musa); } public void startNewGame() { gameClock = 0; gameFrames = 0; startTime = new Date().getTime(); lauta = new GameBoard(soundManager); } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; // Use antialiasing when rendering the game elements g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // Rescale if parent component size has changed Dimension dim = getSize(); if (lautaDim == null || !dim.equals(lautaDim)) { // Rescale background image lautaBGScaled = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB); Graphics2D gimg = lautaBGScaled.createGraphics(); gimg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); gimg.drawImage(lautaBG, 0, 0, dim.width, dim.height, null); lautaDim = dim; // Rescale IDM GUI widgets widgets.setScale(dim.width, dim.height); System.out.print("scale changed\n"); } if (metrics1 == null) metrics1 = g2.getFontMetrics(font1); if (metrics2 == null) metrics2 = g2.getFontMetrics(font2); // Background image, pieces g2.drawImage(lautaBGScaled, 0, 0, null); lauta.paint(g2, 90, 140, 65); if (!lauta.flagGameOver) { AffineTransform save = g2.getTransform(); lauta.nextPiece.paint(g2, 830, 325, 90); g2.setTransform(save); } else { String text = "Game Over!"; int textWidth = metrics2.stringWidth(text); g2.setFont(font2); g2.setPaint(new Color(0.0f, 0.0f, 0.0f, 0.5f)); g2.drawString(text, (dim.width - textWidth) / 2 + 5, dim.height / 2 + 5); double f = Math.sin(gameClock * 0.1) * 4.0; g2.setPaint(Color.white); g2.drawString(text, (dim.width - textWidth) / 2 + (float) f, dim.height / 2 + (float) f); } widgets.paint(g2); // Scores, etc g2.setFont(font2); g2.setPaint(Color.white); g2.drawString(""+ String.format("%05d", lauta.gameScore), dim.width - 230, 220); g2.setFont(font1); long currTime = new Date().getTime(); g2.drawString("fps = "+ ((gameFrames * 1000) / (currTime - startTime)), dim.width - 120, 20); } public void startThreads() { System.out.print("startThreads()\n"); if (animThread == null) { animThread = new Thread(this); animEnable = true; animThread.start(); } } public void stopThreads() { System.out.print("stopThreads()\n"); // Stop animations if (animThread != null) { animThread.interrupt(); animEnable = false; animThread = null; } // Shut down sound manager soundManager.close(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { widgets.mousePressed(e); } public void mouseReleased(MouseEvent e) { widgets.mouseReleased(e); } public void mouseClicked(MouseEvent e) { System.out.print("mouseClicked()\n"); if (!hasFocus()) { System.out.print("requesting focus\n"); requestFocus(); } } public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { // Handle keyboard input if (lauta.keyPressed(e)) return; widgets.keyPressed(e); } public void run() { while (animEnable) { // Progress game animation clock gameClock++; // Animate components if (!lauta.flagGameOver) { lauta.animate(gameClock); lauta.nextPiece.animate(gameClock); } // Repaint with a frame limiter if (gameClock % 3 == 1) { repaint(); gameFrames++; } // Sleep for a moment try { Thread.sleep(10); } catch (InterruptedException x) { } } } class BtnNewGame extends IDMButton { public BtnNewGame(float x, float y) { super(x, y, KeyEvent.VK_ESCAPE, font1, "Uusi peli"); } public void clicked() { startNewGame(); } } class BtnSwapPiece extends IDMButton { public BtnSwapPiece(float x, float y) { super(x, y, KeyEvent.VK_SPACE, font1, "Vaihda"); } public void clicked() { lauta.pieceSwapCurrent(); } } }