view game/Engine.java @ 47:695cf13c103a

Move some code.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 22 Feb 2011 07:19:26 +0200
parents 3e8d1c30f573
children f13bab4cccd3
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 PathInfo
{
    public int inPoint, inX, inY, outPoint, outX, outY; 

    public PathInfo(int inPoint, int inX, int inY, int outPoint, int outX, int outY)
    {
        this.inPoint = inPoint;
        this.inX = inX;
        this.inY = inY;

        this.outPoint = outPoint;
        this.outX = outX;
        this.outY = outY;
    }
    
    public void print()
    {
        System.out.print("PathInfo:  inP="+inPoint+", inX="+inX+", inY="+inY+"\n");
        System.out.print("          outP="+outPoint+", outX="+outX+", outY="+outY+"\n\n");
    }
}

/*
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 IDMWidget
{
    public IDMWidget()
    {
    }

    public void paint(Graphics2D g)
    {
    }
    
    public boolean contains(float x, float y)
    {
        return false;
    }
    
    public void clicked()
    {
    }
}

class IDMButton
{
    enum State { FOCUSED, PRESSED, NORMAL }
    State state;
    BufferedImage imgUp, imgPressed, img;
    Point pos;
 
    public IDMButton(float x, float y, String text)
    {
        try
        {
            ResourceLoader res = new ResourceLoader("graphics/button1_up.png");
            imgUp = ImageIO.read(res.getStream());

            res = new ResourceLoader("graphics/button1_down.png");
            imgPressed = ImageIO.read(res.getStream());
        }
        catch (IOException e)
        {
            System.out.print(e.getMessage());
        }
        
        setState(State.NORMAL);
    }
    
    private void setState(State newState)
    {
        state = newState;
        if (state == State.PRESSED)
            img = imgPressed;
        else
            img = imgUp;
    }

    public void paint(Graphics2D g)
    {
        g.drawImage(img, pos.x, pos.y, null);
    }

    public boolean contains(float x, float y)
    {
        return (x >= pos.x && y >= pos.y &&
                x < pos.x + img.getWidth() &&
                y < pos.y + img.getHeight());
    }
     
    public void clicked()
    {
    }
}


class GameBoard
{
    public static final int boardSize = 9;
    public static final int boardMiddle = 4;
    Piece[][] board;

    public boolean flagGameOver;
    
    Piece currPiece;
    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;
        
        pieceFinishTurn();        
        
        flagGameOver = false;
        
        soundManager = smgr;
        sndPlaced = soundManager.getSound("sounds/placed.wav");
    }

    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);
    }

    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 pieceFinishTurn()
    {
        while (true)
        {
            if (currX >= 0 && currX < boardSize && currY >= 0 && currY < boardSize)
            {
                Piece curr = board[currX][currY];

                if (curr == null)
                {
                    // Create new piece
                    currPiece = new Piece(PieceType.ACTIVE);
                    board[currX][currY] = currPiece;
                    return;
                }
                else
                if (curr.getType() == PieceType.START)
                {
                    if (currPiece != null)
                    {
                        // Hit center starting piece, game over
                        flagGameOver = true;
                        currPiece = null;
                        System.out.print("GameOver!\n");
                        break;
                    }
                    else
                    {
                        // Start piece as first piece means game is starting
                        pieceMoveTo(currPoint);
                        currPiece = new Piece(PieceType.ACTIVE);
                        board[currX][currY] = currPiece;
                        return;
                    }
                }
                else
                {
                    // Mark the current piece as locked
                    curr.setType(PieceType.LOCKED);
                    
                    // Solve connection (with rotations) through the piece
                    currPoint = curr.getRotatedPoint(curr.getMatchingPoint(currPoint));
                    
                    // Mark connection as active
                    curr.setConnectionState(currPoint, true);
                    
                    // Solve exit point (with rotations)
                    currPoint = curr.getAntiRotatedPoint(curr.getConnection(currPoint));
                    
                    // Move to next position accordingly
                    pieceMoveTo(currPoint);
                }
            }
            else
            {
                // Outside of the board, game over
                flagGameOver = true;
                currPiece = null;
                System.out.print("GameOver!\n");
                break;
            }
        }

    }

    public boolean keyHandler(KeyEvent e)
    {
        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;
    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;

    public Engine()
    {
        // Initialize globals
        System.out.print("Engine() constructor\n");
        
        gameClock = 0;
        gameFrames = 0;
        startTime = new Date().getTime();

        // 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(32f);
            }
            catch (FontFormatException e)
            {
                System.out.print("Could not initialize fonts.\n");
            }
            
//            musa = smgr.getSound("sounds/gamemusic.wav");
        }
        catch (IOException e)
        {
            JOptionPane.showMessageDialog(null,
                e.getMessage(),
                "Initialization error",
                JOptionPane.ERROR_MESSAGE);

            System.out.print(e.getMessage());
        }

        // Initialize game components
        lauta = new GameBoard(soundManager);
        addKeyListener(this);
        addMouseListener(this);

        // Get initial focus
        if (!hasFocus())
        {
            System.out.print("Engine(): requesting focus\n");
            requestFocus();
        }
        
        soundManager.play(musa);
    }


    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 background if component size has changed
        Dimension dim = getSize();
        if (lautaDim == null || !dim.equals(lautaDim))
        {
            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;

            System.out.print("scale changed\n");
        }
        
        // Background, pieces
        g2.drawImage(lautaBGScaled, 0, 0, null);
        lauta.paint(g2, 100, 150, 60);

        // Scores
        g2.setFont(font1);
        g2.setPaint(Color.white);
        
        
        // Other elements
        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 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 keyTyped(KeyEvent e)
    {
    }
   
    public void keyReleased(KeyEvent e)
    {
    }
   
    public void keyPressed(KeyEvent e)
    {
        // Handle keyboard input
        if (lauta.keyHandler(e))
            return;
        
        switch (e.getKeyCode())
        {
            case KeyEvent.VK_ESCAPE:
                break;
        }
    }
    
    public void run()
    {
        while (animEnable)
        {
            // Progress game animation clock
            gameClock++;

            // Animate components
            lauta.animate(gameClock);
            
            // Repaint with a frame limiter
            if (gameClock % 3 == 1)
            {
                repaint();
                gameFrames++;
            }
            
            // Sleep for a moment
            try {
                Thread.sleep(10);
            }
            catch (InterruptedException x) {
            }
        }
    }
}