Mercurial > hg > ristipolku
view game/Engine.java @ 21:df494a65bf8c
More work.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 31 Jan 2011 19:46:41 +0200 |
parents | 4507a431b410 |
children | afde253ec705 |
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 javax.imageio.*; import javax.swing.*; import java.util.*; import java.io.*; import game.*; import javax.sound.sampled.*; enum Sound { PIECE_PLACED("placed.wav", true), MUSIC_GAME1("gamemusic.wav", false); private final String name; private final boolean effect; Sound(String name, boolean effect) { this.name = name; this.effect = effect; } public String getName() { return this.name; } public boolean isEffect() { return effect; } } class SoundElement implements Runnable { private final String name; private Clip clip; private AudioInputStream stream; private AudioFormat format; private SourceDataLine line; private Thread playThread; private int loopCount; private boolean doPlay; SoundElement(String filename, boolean effect) throws IOException { this.name = filename; ResourceLoader res = new ResourceLoader(name); if (res == null || res.getStream() == null) { throw new IOException("Could not load audio resource '"+name+"'.\n"); } try { stream = AudioSystem.getAudioInputStream(res.getStream()); } catch (UnsupportedAudioFileException e) { throw new IOException("Unsupported audio file format for '"+name+"'.\n"); } catch (IOException e) { throw new IOException("Could not load audio resource '"+name+"'.\n"); } format = stream.getFormat(); if (effect) { System.out.print("Loading '"+name+"' as a clip\n"); try { clip = AudioSystem.getClip(); clip.open(stream); } catch (LineUnavailableException e) { throw new IOException("Line unavailable for '"+name+"'.\n"); } finally { stream.close(); } } else { clip = null; System.out.print("Loading '"+name+"' as stream\n"); try { SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format); System.out.print("info: "+stream.getFrameLength() + ", " + format.getFrameSize() + "\n"); line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); } catch (LineUnavailableException e) { throw new IOException("Line unavailable for '"+name+"'.\n"); } } } public boolean isClip() { return (clip != null && line == null); } public void play() { System.out.print("Sound("+name+").play()\n"); if (isClip()) { clip.setFramePosition(0); clip.start(); } else { if (playThread == null) { doPlay = true; loopCount = 1; playThread = new Thread(this); playThread.start(); } } } public void loop(int n) { System.out.print("Sound("+name+").loop("+n+")\n"); if (isClip()) { clip.setFramePosition(0); if (n < 0) clip.loop(Clip.LOOP_CONTINUOUSLY); else clip.loop(n); } else { if (playThread == null) { doPlay = true; loopCount = n; playThread = new Thread(this); playThread.start(); } } } public void stop() { if (isClip()) { if (clip.isRunning()) clip.stop(); } else { if (playThread != null) { playThread.interrupt(); doPlay = false; playThread = null; } } } public boolean isPlaying() { if (isClip()) return clip.isRunning(); else return (playThread != null && doPlay); } public void run() { line.start(); byte[] buf = new byte[line.getBufferSize()]; while (doPlay && (loopCount > 0 || loopCount == -1)) { try { int numRead = 0; while ((numRead = stream.read(buf, 0, buf.length)) >= 0 && doPlay) { int offset = 0; while (offset < numRead) { System.out.print("audioThread: offs="+offset+", numread="+numRead+"\n"); offset += line.write(buf, offset, numRead - offset); } } line.drain(); System.out.print("audioThread: stream.reset()\n"); stream.reset(); } catch (IOException e) { } if (loopCount > 0) loopCount--; } line.stop(); doPlay = false; } } class PathInfo { public int in, inX, inY, out, outX, outY; public PathInfo(int in, int inX, int inY, int out, int outX, int outY) { this.in = in; this.inX = inX; this.inY = inY; this.out = out; this.outX = outX; this.outY = outY; } } /* 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 { public static final int boardSize = 9; public static final int boardMiddle = 4; Piece[][] board; Piece current; public boolean flagGameOver; int moveX, moveY, movePoint; public GameBoard() { board = new Piece[boardSize][boardSize]; board[boardMiddle][boardMiddle] = new Piece(PieceType.START); moveX = boardMiddle; moveY = boardMiddle - 1; movePoint = 0; pieceFinishTurn(); flagGameOver = false; } public void paint(Graphics2D g, int sx, int 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); } } private boolean isEmpty(int x, int y) { return (x >= 0 && x < boardSize && y >= 0 && y < boardSize && board[x][y] == null); } private Piece getPiece(int x, int y) { if (x >= 0 && x < boardSize && y >= 0 && y < boardSize) return board[x][y]; else return null; } public void pieceRotate(boolean dir) { if (current != null) current.rotate(dir); } public PathInfo resolvePath(int startX, int startY, int startPoint, boolean mark) { int x = startX, y = startY; int point = -1; Piece curr = getPiece(startX, startY); if (curr == null) return null; /* while (curr != null) { // curr.(true); // elements.spawn("", ); } */ return new PathInfo(startPoint, startX, startY, point, x, y); } public void pieceFinishTurn() { if (current != null) { current.setType(PieceType.LOCKED); PathInfo i = resolvePath(moveX, moveY, movePoint, true); if (i != null) { } } current = new Piece(PieceType.ACTIVE); if (isEmpty(moveX, moveY)) { board[moveX][moveY] = current; } else { PathInfo i = resolvePath(moveX, moveY, movePoint, true); if (i != null) board[moveX][moveY] = current; else flagGameOver = true; } } } public class Engine extends JPanel implements Runnable, KeyListener, MouseListener { Thread animThread; boolean animEnable = false; GameBoard lauta = null; BufferedImage lautaBG = null, lautaBGScaled = null; Dimension oldDim; float clock; SoundElement[] sounds; public SoundElement snd(Sound snd) { return sounds[snd.ordinal()]; } public Engine() { BufferedImage img; clock = 0; System.out.print("Engine() constructor\n"); try { ResourceLoader res = new ResourceLoader("graphics/board.png"); lautaBG = ImageIO.read(res.getStream()); sounds = new SoundElement[16]; for (Sound s : Sound.values()) { System.out.print(s +" = "+ s.ordinal() +"\n"); sounds[s.ordinal()] = new SoundElement("sounds/" + s.getName(), s.isEffect()); } } catch (IOException e) { /* JOptionPane.showMessageDialog(null, e.getMessage(), "Initialization error", JOptionPane.ERROR_MESSAGE); */ System.out.print(e.getMessage()); } lauta = new GameBoard(); addKeyListener(this); addMouseListener(this); // Get initial focus if (!hasFocus()) { System.out.print("Engine(): requesting focus\n"); requestFocus(); } snd(Sound.MUSIC_GAME1).loop(-1); // snd(Sound.PIECE_PLACED).loop(-1); } 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"); if (animThread != null) { animThread.interrupt(); animEnable = false; animThread = null; } } public void mousePressed(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseClicked(MouseEvent e) { System.out.print("mouseClicked()\n"); if (!hasFocus()) { System.out.print("requesting focus\n"); requestFocus(); } } 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); // Rescale background if component size has changed Dimension dim = getSize(); if (oldDim == null || !dim.equals(oldDim)) { 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); oldDim = dim; System.out.print("scale changed\n"); } // Background, pieces g2.drawImage(lautaBGScaled, 0, 0, null); lauta.paint(g2, 100, 150, 60); // Other elements } public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { System.out.print("running "+ snd(Sound.MUSIC_GAME1) + "\n"); switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: case KeyEvent.VK_UP: lauta.pieceRotate(false); break; case KeyEvent.VK_RIGHT: case KeyEvent.VK_DOWN: lauta.pieceRotate(true); break; case KeyEvent.VK_ENTER: lauta.pieceFinishTurn(); snd(Sound.PIECE_PLACED).stop(); snd(Sound.PIECE_PLACED).play(); break; } } public void run() { while (animEnable) { clock++; // System.out.print("clock=" + clock + "\n"); lauta.animate(clock); if (clock % 2 == 1) repaint(); try { Thread.sleep(10); } catch (InterruptedException x) { } } } }