package redpong; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.Timer; import javax.swing.event.*; public class RedPongDisplay extends JPanel { public static final int WINDOW_WIDTH = 500; public static final int WINDOW_HEIGHT = 400; public static final int COURT_BORDER = 70; public static final int MS_PER_TICK = 50; private int courtWidth; private int courtHeight; private CourtPanel court; private RedPongLogic gamestate; private JLabel score; private JLabel rules; public int getWINDOW_WIDTH() { return WINDOW_WIDTH; } public int getWINDOW_HEIGHT() { return WINDOW_HEIGHT; } public RedPongDisplay() { courtWidth = WINDOW_WIDTH-2*COURT_BORDER; courtHeight = WINDOW_HEIGHT-2*COURT_BORDER; gamestate = new RedPongLogic(courtWidth, courtHeight, .05,// 1/20th of the height of the court .2, // 20% across the court .5, // halfway up the court 2.); // seconds to cross court setBackground(Color.blue); setLayout(new BorderLayout()); court = new CourtPanel(courtWidth, courtHeight, COURT_BORDER); court.setBackground(Color.red); add(court, BorderLayout.CENTER); JPanel rulesPanel = new JPanel(); rulesPanel.setBackground(Color.yellow); rulesPanel.setLayout(new BorderLayout()); rules = new JLabel(""); rulesPanel.add(rules, BorderLayout.CENTER); add(rulesPanel, BorderLayout.SOUTH); JPanel scorePanel = new JPanel(); scorePanel.setBackground(Color.yellow); scorePanel.setLayout(new BorderLayout()); score = new JLabel(""); scorePanel.add(score, BorderLayout.CENTER); add(scorePanel, BorderLayout.NORTH); ActionListener tlistener = new UpdateState(); Timer t = new Timer(MS_PER_TICK, tlistener); t.start(); } public void handleKeyCode(int keyCode) { if (keyCode == KeyEvent.VK_UP) { gamestate.movePlayer(-1); //court.updateCourt(gamestate); } else if (keyCode == KeyEvent.VK_DOWN) { gamestate.movePlayer(1); //court.updateCourt(gamestate); } // else we don't care about this key } private class UpdateState implements ActionListener { public void actionPerformed(ActionEvent event) { // Could be smarter to accommodate missed ticks... gamestate.tickUpdate(MS_PER_TICK); court.updateCourt(gamestate); score.setText("Computer Score: "+ gamestate.getComputerScore()+ " Your Score: "+ gamestate.getPlayerScore()); // This really doesn't belong here, but some weird bug was // causing it to disappear if you refreshed the applet. // This is a brute force workaround. rules.setText("Your paddle is on the right. "+ "Use up/down keys to move it."); } } } // A panel that draws a single-player pong court: class CourtPanel extends JPanel { private RedPongLogic gamestate; private double leftX; private double rightX; private double topY; private double bottomY; public CourtPanel(int courtWidth, int courtHeight, int border) { leftX = border; rightX = border+courtWidth; topY = border; bottomY = border+courtHeight; } private Point2D gameToScreen(double gX, double gY) { double sX = leftX + gX; double sY = topY + gY; return new Point2D.Double(sX, sY); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; // Draw the walls: //g2.draw(new Line2D.Double(leftX, topY, leftX, bottomY)); //g2.draw(new Line2D.Double(rightX,topY, rightX,bottomY)); g2.draw(new Line2D.Double(leftX, topY, rightX, topY)); g2.draw(new Line2D.Double(leftX, bottomY,rightX, bottomY)); /* debug int i; Rectangle2D blocks [] = gamestate.getBlocks(); for (i=0; i<6; i++) { g2.draw(blocks[i]); } */ Rectangle2D computerPaddle = new Rectangle2D.Double(leftX+0., topY+gamestate.getComputerPaddleTop(), gamestate.getPaddleWidth(), gamestate.getPaddleHeight()); g2.draw(computerPaddle); Rectangle2D playerPaddle = new Rectangle2D.Double(rightX-gamestate.getPaddleWidth(), topY+gamestate.getPlayerPaddleTop(), gamestate.getPaddleWidth(), gamestate.getPaddleHeight()); g2.draw(playerPaddle); Point2D ballLoc = gameToScreen(gamestate.getBallLocPixelsX(), gamestate.getBallLocPixelsY()); double screenBallX = ballLoc.getX(); double screenBallY = ballLoc.getY(); double ballRadius = gamestate.getBallRadiusPixels(); Ellipse2D ball = new Ellipse2D.Double(screenBallX-ballRadius, screenBallY-ballRadius, ballRadius*2., ballRadius*2.); g2.draw(ball); } public void updateCourt(RedPongLogic gs) { gamestate = gs; repaint(); } }