// // // // Pong2 - Active rendering example // // // Copyright (c) 2007-2008 Knute Johnson, all rights reserved // // // package com.knutejohnson.games.pong; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.*; import java.net.*; import javax.swing.*; import javax.sound.sampled.*; public class Pong2 extends Canvas implements ActionListener { final static double TWOPI = Math.PI * 2.0; final static double BALL_DIAMETER = 17.0; final static double BALL_RADIUS = BALL_DIAMETER / 2.0; final static double PADDLE_WIDTH = 70.0; final static double PADDLE_HEIGHT = 10.0; final static double PIXELS_PER_TICK = 6.0; final Timer timer = new Timer(20,this); BufferStrategy bs; double ballX, ballY, ballDeltaX, ballDeltaY; double velocity; double paddleX, paddleY; boolean leftKeyIsPressed, rightKeyIsPressed; final Ellipse2D.Double ball = new Ellipse2D.Double(); final Rectangle2D.Double paddle = new Rectangle2D.Double(); public Pong2() { setIgnoreRepaint(true); addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent ke) { int keyCode = ke.getKeyCode(); if (keyCode == KeyEvent.VK_LEFT) leftKeyIsPressed = true; else if (keyCode == KeyEvent.VK_RIGHT) rightKeyIsPressed = true; else if (keyCode == KeyEvent.VK_SPACE) { velocity = PIXELS_PER_TICK; ballX = getWidth() / 2.0; ballY = BALL_RADIUS; ballDeltaX = 0.0; ballDeltaY = velocity; } } public void keyReleased(KeyEvent ke) { int keyCode = ke.getKeyCode(); if (keyCode == KeyEvent.VK_LEFT) leftKeyIsPressed = false; else if (keyCode == KeyEvent.VK_RIGHT) rightKeyIsPressed = false; } }); } public void start() { createBufferStrategy(2); bs = getBufferStrategy(); ballX = paddleX = getWidth() / 2.0; // center paddle ++paddleX; // put paddle very slightly off center ballY = BALL_RADIUS; velocity = PIXELS_PER_TICK; timer.start(); requestFocus(); } public void actionPerformed(ActionEvent ae) { calculate(); render(); } public void stop() { timer.stop(); } void calculate() { // get a little faster each time positions are calculated velocity += 0.003; // move the paddle if (leftKeyIsPressed && paddleX > PADDLE_WIDTH / 2.0) paddleX -= 8.0; if (rightKeyIsPressed && paddleX < getWidth() - PADDLE_WIDTH / 2.0) paddleX += 8.0; paddle.setFrame(paddleX - PADDLE_WIDTH / 2.0,getHeight() - 20.0, PADDLE_WIDTH,PADDLE_HEIGHT); // move the ball ballX += ballDeltaX; ballY += ballDeltaY; ball.setFrame(ballX - BALL_RADIUS,ballY - BALL_RADIUS, BALL_DIAMETER,BALL_DIAMETER); // check for edges if (ballX <= BALL_RADIUS || ballX + BALL_RADIUS >= getWidth()) { ballDeltaX = -ballDeltaX; playSound("sounds/bink.wav"); } if (ballY < BALL_RADIUS) { ballDeltaY = -ballDeltaY; playSound("sounds/bink.wav"); } // if center of ball is below paddle face if (ballY > getHeight() - 20) { ballX = getWidth() / 2.0; ballY = BALL_RADIUS; ballDeltaX = 0.0; ballDeltaY = 0.0; velocity = PIXELS_PER_TICK; playSound("sounds/buhh.wav"); return; } // check for ball hits on the top edge of paddle if (paddle.intersects(ball.getBounds2D())) { ballDeltaY = -ballDeltaY; // add a little angle for off center hits on paddle double arcTan = Math.atan2(ballDeltaY,ballDeltaX); double angle = (ballX - paddleX) / 720.0 * TWOPI; ballDeltaX = velocity * Math.cos(arcTan + angle); ballDeltaY = velocity * Math.sin(arcTan + angle); playSound("sounds/bonk.wav"); } } void render() { do { do { Graphics2D g = (Graphics2D)bs.getDrawGraphics(); // anti-alias the drawing g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // draw the background g.setColor(Color.BLACK); g.fillRect(0,0,getWidth(),getHeight()); // draw the ball and paddle g.setColor(Color.WHITE); g.fill(ball); g.fill(paddle); g.dispose(); } while (bs.contentsRestored()) ; bs.show(); } while (bs.contentsLost()) ; } void playSound(final String fname) { Runnable r = new Runnable() { public void run() { try { URL url = getClass().getResource(fname); AudioInputStream ais = AudioSystem.getAudioInputStream(url); AudioFormat af = ais.getFormat(); SourceDataLine line = AudioSystem.getSourceDataLine(af); line.open(af); line.start(); byte[] buf = new byte[1024]; int bytesRead; while ((bytesRead = ais.read(buf,0,buf.length)) != -1) line.write(buf,0,bytesRead); line.drain(); line.stop(); line.close(); } catch (Exception e) { System.out.println(e); } } }; new Thread(r).start(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { final Frame f = new Frame("Pong2 - A Java Active Rendering Example"); final Pong2 p2 = new Pong2(); p2.setPreferredSize(new Dimension(600,450)); f.addWindowListener(new WindowAdapter() { public void windowOpened(WindowEvent we) { p2.start(); } public void windowClosing(WindowEvent we) { p2.stop(); f.dispose(); } }); f.add(p2,BorderLayout.CENTER); f.pack(); f.setVisible(true); } }); } }