Package bs

Source Code of bs.PongGame

package bs;

import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.swing.JPanel;
import javax.swing.Timer;

import bs.sound.Sound;
import bs.sound.SoundManager;

public class PongGame extends JPanel {
    // Statics
    private enum GameState {
        WAITING_FOR_FIRE, PLAYING, FORCED_PAUSE, PAUSED, SHOW_WINNER
    };

    protected static final int FONT_SIZE = 24;

    private static final DisplayMode POSSIBLE_MODES[] = { new DisplayMode(1280, 1024, 24, 0),
            new DisplayMode(1280, 1024, 32, 0), new DisplayMode(1280, 1024, 16, 0),
            new DisplayMode(1024, 768, 24, 0), new DisplayMode(1024, 768, 32, 0),
            new DisplayMode(1024, 768, 16, 0), new DisplayMode(800, 600, 16, 0),
            new DisplayMode(800, 600, 32, 0), new DisplayMode(800, 600, 24, 0),
            new DisplayMode(640, 480, 16, 0), new DisplayMode(640, 480, 32, 0),
            new DisplayMode(640, 480, 24, 0), };

    private final static int KEEPER_WIDTH = 20;
    private final static int KEEPER_EXTRA_BOUNCE_MARGIN = 10;
    private final static int BALL_DIAM = 20;
    private final static int KEEPER_SPACING = 10;
    private final static int POINTS_TO_WIN = 8;

    private final static int KEEPER_HEIGHT_STEP = 5;

    private final static Color[] COLORS = { Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green,
            Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow };

    // Collaborators
    private final ScreenManager screen;

    private final InputManager inputManager;
   
    private final SoundManager soundManager;

    private final PressAndHoldKeyGameAction upL, downL, upR, downR;

    private final PressKeyGameAction esc, space, f1, f2, f3, f4, f5, f6, f7;
   
    private final Sound bounce;

    // uncompressed, 22050Hz, 8-bit, mono, not signed, little-endian
    final AudioFormat AUDIO_FORMAT = new AudioFormat(22050, 8, 1, false, false);

    // State
    private int ballSpeed = 5;
    private  int keeperLeftHeight = 100;
    private  int keeperRightHeight = 400;
    private int currentColor = 4;
   
    private GameState state = GameState.WAITING_FOR_FIRE;
    private boolean running = true;

    private boolean leftStartedLastGame;

    private int keeperLeftY, keeperRightY;

    private boolean leftMissed, rightMissed;

    private boolean leftFire, rightFire;

    private int leftPoints, rightPoints;

    private int ballVert, ballHor;

    private Point ballPos = new Point(0, 0);

    private float winnerFlowerSize = 1;

    public static void main(String[] args) {
        try {
            new PongGame().go();
        } catch (RuntimeException e) {
            e.printStackTrace(System.err);
            System.exit(1);
        } catch (Error e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }
    }

    public PongGame() {
        screen = new ScreenManager();
        DisplayMode displayMode = screen.findFirstCompatibleMode(POSSIBLE_MODES);
        screen.setFullScreen(displayMode);

        Window window = screen.getFullScreenWindow();
        window.setFont(new Font("Dialog", Font.PLAIN, FONT_SIZE));
        window.setBackground(Color.black);
        window.setForeground(Color.white);

        inputManager = new InputManager(window);
        upL = new PressAndHoldKeyGameAction("upL");
        downL = new PressAndHoldKeyGameAction("downL");
        upR = new PressAndHoldKeyGameAction("upR");
        downR = new PressAndHoldKeyGameAction("downR");
        esc = new PressKeyGameAction("escape");
        space = new PressKeyGameAction("space");
        f1 = new PressKeyGameAction("f1");
        f2 = new PressKeyGameAction("f2");
        f3 = new PressKeyGameAction("f3");
        f4 = new PressKeyGameAction("f4");
        f5 = new PressKeyGameAction("f5");
        f6 = new PressKeyGameAction("f6");
        f7 = new PressKeyGameAction("f7");

        inputManager.mapToKey(upL, KeyEvent.VK_A);
        inputManager.mapToKey(downL, KeyEvent.VK_Z);
        inputManager.mapToKey(upR, KeyEvent.VK_UP);
        inputManager.mapToKey(downR, KeyEvent.VK_DOWN);
        inputManager.mapToPress(esc, KeyEvent.VK_ESCAPE);
        inputManager.mapToPress(space, KeyEvent.VK_SPACE);
        inputManager.mapToPress(f1, KeyEvent.VK_F1);
        inputManager.mapToPress(f2, KeyEvent.VK_F2);
        inputManager.mapToPress(f3, KeyEvent.VK_F3);
        inputManager.mapToPress(f4, KeyEvent.VK_F4);
        inputManager.mapToPress(f5, KeyEvent.VK_F5);
        inputManager.mapToPress(f6, KeyEvent.VK_F6);
        inputManager.mapToPress(f7, KeyEvent.VK_F7);
       
    soundManager = new SoundManager(AUDIO_FORMAT);
    InputStream is = PongGame.class.getResourceAsStream("/BEAT1.WAV");
    bounce = soundManager.getSound(is);

        state = GameState.WAITING_FOR_FIRE;
        leftFire = true;
    }

    private void go() {
        long startTime = System.currentTimeMillis();
        long currTime = startTime;

        initGame();

        while (running) {
            long elapsedTime = System.currentTimeMillis() - currTime;
            currTime += elapsedTime;

            // update
            update(elapsedTime);

            // draw the screen
            Graphics g = screen.getGraphics();
            draw(g);
            g.dispose();
            screen.update();

            // Thread.yield();

            // take a nap
            try {
                Thread.sleep(10);
            } catch (InterruptedException ex) {
            }
        }
    }

    private void initGame() {
        leftPoints = 0;
        rightPoints = 0;

        leftFire = !leftStartedLastGame;
        rightFire = leftStartedLastGame;
        leftStartedLastGame = !leftStartedLastGame;

        space.wasPressedAndReset(); // Reset space
        state = GameState.WAITING_FOR_FIRE;
    }

    /** Update game state */
    private void update(long elapsedTime) {
        if (esc.wasPressedAndReset()) {
            System.exit(0);
        }

        long now = System.currentTimeMillis();
        int max = screen.getHeight();
        switch (state) {
        case PLAYING:
            updateKeepers(now, max);
            updateBall();
            missed();
            win();
            updateSettings();
            break;

        case FORCED_PAUSE:
            updateKeepers(now, max);
            updateSettings();
            break;

        case WAITING_FOR_FIRE:
            updateKeepers(now, max);
            updateBallStickToKeeper();
            fire();
            updateSettings();
            break;

        case SHOW_WINNER:
            updateKeepers(now, max);
            updateBall();
            updateWinnerFlowerSize(now);
            detectContinue();
            updateSettings();
            break;

        default:
            break;
        }
    }

    private void fire() {
        if (space.wasPressedAndReset()) {
            ballVert = ballSpeed;
            state = GameState.PLAYING;
            if (leftFire) {
                ballHor = +ballSpeed;
                leftFire = false;
            } else if (rightFire) {
                ballHor = -ballSpeed;
                rightFire = false;
            }
        }
    }

    private void missed() {
        if (ballOffScreen()) {
            if (leftMissed) {
                leftPoints -= 3;
                if (leftPoints < 0) {
                    leftPoints = 0;
                }
                leftMissed = false;
                leftFire = true;
            } else if (rightMissed) {
                rightPoints -= 3;
                if (rightPoints < 0) {
                    rightPoints = 0;
                }
                rightMissed = false;
                rightFire = true;
            } else {
                throw new AssertionError();
            }
            state = GameState.FORCED_PAUSE;

            // Force pause
            Timer forcePauseTimer = new Timer(2000, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    space.wasPressedAndReset(); // Reset space
                    state = GameState.WAITING_FOR_FIRE;
                }
            });
            forcePauseTimer.setRepeats(false);
            forcePauseTimer.start();
        }
    }

    private void win() {
        if (leftPoints == POINTS_TO_WIN || rightPoints == POINTS_TO_WIN) {
            space.wasPressedAndReset(); // Reset space
            state = GameState.SHOW_WINNER;
        }
    }

    private boolean ballOffScreen() {
        int curX = (int) Math.round(ballPos.getX());
        return curX + BALL_DIAM < 0 || curX > screen.getWidth();
    }

    private void updateKeepers(long now, int max) {
        final float divide = 2;
        int uL = (int) Math.round(upL.getAndResetPressDuration(now) / divide);
        int dL = (int) Math.round(downL.getAndResetPressDuration(now) / divide);
        keeperLeftY = keeperLeftY + dL - uL;
        if (keeperLeftY < 0) {
            keeperLeftY = 0;
        }
        if (keeperLeftY > max - keeperLeftHeight) {
            keeperLeftY = max - keeperLeftHeight;
        }

        int uR = (int) Math.round(upR.getAndResetPressDuration(now) / divide);
        int dR = (int) Math.round(downR.getAndResetPressDuration(now) / divide);
        keeperRightY = keeperRightY + dR - uR;
        if (keeperRightY < 0) {
            keeperRightY = 0;
        }
        if (keeperRightY > max - keeperRightHeight) {
            keeperRightY = max - keeperRightHeight;
        }
    }

    private void updateBall() {
        int newX = bounceKeepers();
        int newY = bounceTopAndBottom();
        ballPos.setLocation(newX, newY);
    }

    /**
     * During WAINTING state the ball sticks to one keeper.
     */
    private void updateBallStickToKeeper() {
        final int ballX, ballY;
        if (leftFire) {
            ballX = KEEPER_SPACING + KEEPER_WIDTH;
            ballY = keeperLeftY + (keeperLeftHeight / 2) - (BALL_DIAM / 2);
        } else if (rightFire) {
            ballX = screen.getWidth() - (KEEPER_SPACING + KEEPER_WIDTH + BALL_DIAM);
            ballY = keeperRightY + (keeperRightHeight / 2) - (BALL_DIAM / 2);
        } else {
            throw new AssertionError();
        }
        ballPos.setLocation(ballX, ballY);
    }

    private void updateWinnerFlowerSize(long now) {
        long sec = now % 1000;
        float twoPiRadiansPerSec = (float) (sec / (1000 / (2 * Math.PI)));
        winnerFlowerSize = 1.0f + (float) Math.sin(twoPiRadiansPerSec) * 0.5f;
        return;
    }

    private void updateSettings() {
        // Left keeper height
        if (f1.wasPressedAndReset()) {
            keeperLeftHeight -= KEEPER_HEIGHT_STEP;
        }
        if (f2.wasPressedAndReset()) {
            keeperLeftHeight += KEEPER_HEIGHT_STEP;
        }

        // Right keeper height
        if (f3.wasPressedAndReset()) {
            keeperRightHeight -= KEEPER_HEIGHT_STEP;
        }
        if (f4.wasPressedAndReset()) {
            keeperRightHeight += KEEPER_HEIGHT_STEP;
        }

        // Ball speed
        if (f5.wasPressedAndReset()) {
            if (ballSpeed > 1) {
                ballSpeed--;
                ballHor -= (ballHor > 0 ? 1 : (ballHor < 0 ? -1 : 0));
                ballVert -= (ballVert > 0 ? 1 : (ballVert < 0 ? -1 : 0));
            }
        }
        if (f6.wasPressedAndReset()) {
            ballSpeed++;
            ballHor += (ballHor >= 0 ? 1 : -1);
            ballVert += (ballVert >= 0 ? 1 : -1);
        }
       
        // Color
        if (f7.wasPressedAndReset()) {
            currentColor++;
            if (currentColor >= COLORS.length) {
                currentColor = 0;
            }
        }
    }

    private void detectContinue() {
        if (space.wasPressedAndReset()) {
            initGame();
        }
    }

    private int bounceTopAndBottom() {
        int height = screen.getHeight();
        int curY = (int) Math.round(ballPos.getY());
        final int newY;
        if (curY + ballVert + BALL_DIAM > height) {
            // Bounce bottom
            newY = height - (curY + ballVert + BALL_DIAM - height) - BALL_DIAM;
            ballVert = -ballVert;
        } else if (curY + ballVert < 0) {
            // Bouce top
            newY = -(curY + ballVert);
            ballVert = -ballVert;
        } else {
            newY = curY + ballVert;
        }
        return newY;
    }

    private int bounceKeepers() {
        int width = screen.getWidth();
        int curX = (int) Math.round(ballPos.getX());
        int curY = (int) Math.round(ballPos.getY());

        int ballRight = curX + BALL_DIAM;
        int rightKeeperLeft = width - KEEPER_SPACING - KEEPER_WIDTH;
        int ballLeft = curX;
        int leftKeeperRight = KEEPER_SPACING + KEEPER_WIDTH;

        final int newX;
        if (ballRight > rightKeeperLeft) {
            if (!rightMissed && curY >= keeperRightY - KEEPER_EXTRA_BOUNCE_MARGIN
                    && curY <= (keeperRightY + keeperRightHeight + KEEPER_EXTRA_BOUNCE_MARGIN)) {
                // Bounce right keeper
              soundManager.play(bounce);
                newX = rightKeeperLeft - (ballRight - rightKeeperLeft) - BALL_DIAM;
                ballHor = -ballHor;
                if (state == GameState.PLAYING) {
                    rightPoints++;
                }
            } else {
                // Mark as missed and then let the ball go offscreen
                rightMissed = true;
                newX = curX + ballHor;
            }
        } else if (ballLeft < leftKeeperRight) {
            if (!leftMissed && curY >= keeperLeftY - KEEPER_EXTRA_BOUNCE_MARGIN
                    && curY <= (keeperLeftY + keeperLeftHeight + KEEPER_EXTRA_BOUNCE_MARGIN)) {
                // Bounce left keeper
              soundManager.play(bounce);
                newX = leftKeeperRight + (leftKeeperRight - ballLeft);
                ballHor = -ballHor;
                if (state == GameState.PLAYING) {
                    leftPoints++;
                }
            } else {
                // Mark as missed and then let the ball go offscreen
                leftMissed = true;
                newX = curX + ballHor;
            }
        } else {
            newX = curX + ballHor;
        }

        return newX;
    }

    /** Update view state */
    private void draw(Graphics g) {
        g.setColor(Color.black);
        g.fillRect(0, 0, screen.getWidth(), screen.getHeight());

        if (state == GameState.SHOW_WINNER) {
            if (leftPoints == POINTS_TO_WIN) {
                FlowerDrawer.draw((Graphics) g, 100, (screen.getHeight() - FlowerDrawer.HEIGHT) / 2,
                        leftPoints, winnerFlowerSize);
                FlowerDrawer.draw((Graphics) g, screen.getWidth() - 100 - FlowerDrawer.WIDTH,
                        (screen.getHeight() - FlowerDrawer.HEIGHT) / 2, rightPoints);
            } else {
                FlowerDrawer.draw((Graphics) g, 100, (screen.getHeight() - FlowerDrawer.HEIGHT) / 2,
                        leftPoints);
                FlowerDrawer.draw((Graphics) g, screen.getWidth() - 100 - FlowerDrawer.WIDTH,
                        (screen.getHeight() - FlowerDrawer.HEIGHT) / 2, rightPoints, winnerFlowerSize);
            }

        } else {
            FlowerDrawer.draw((Graphics) g, 100, (screen.getHeight() - FlowerDrawer.HEIGHT) / 2, leftPoints);
            FlowerDrawer.draw((Graphics) g, screen.getWidth() - 100 - FlowerDrawer.WIDTH,
                    (screen.getHeight() - FlowerDrawer.HEIGHT) / 2, rightPoints);
        }

        int width = screen.getWidth();
        g.setColor(COLORS[currentColor]);
        g.fillRect(KEEPER_SPACING, keeperLeftY, KEEPER_WIDTH, keeperLeftHeight);
        g.fillRect(width - KEEPER_SPACING - KEEPER_WIDTH, keeperRightY, KEEPER_WIDTH, keeperRightHeight);

        g.fillOval((int) Math.round(ballPos.getX()), (int) Math.round(ballPos.getY()), BALL_DIAM, BALL_DIAM);

        g.setColor(Color.gray);
        g.drawString(String.format("%d", leftPoints), 50, (screen.getHeight() - FONT_SIZE) / 2);
        g.drawString(String.format("%d", rightPoints), screen.getWidth() - 80,
                (screen.getHeight() - FONT_SIZE) / 2);

        if (state == GameState.SHOW_WINNER) {
            g.drawString("Press space", (screen.getWidth() - 100) / 2, (screen.getHeight() - 24) / 2);
        }
    }
}
TOP

Related Classes of bs.PongGame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.