Chris Pollett > Old Classes > PIC20B ( Print View ) Enrollment info Course Info:
|
HW5 Solutions Page// // Interface Name: PongClientServerDefines // // Purpose: contains defines used by Pong client and server // public interface PongClientServerDefines { // // Defines concerning Pong Client Server communication // static int SERVERPORT=6542; static int ENDGAMECODE=7; static int ENDGAMELENGTH =0; static int ENDPOINTCODE=3; static int ENDPOINTLENGTH=30; static int STARTGAMECODE=5; static int STARTGAMELENGTH=10; static int STARTPOINTCODE = 6; static int STARTPOINTLENGTH = 0; static int PLAYINGCODE = 127; static int UPCODE = 0; static int DOWNCODE = 255; static int LPLAYER = 1; static int RPLAYER = 2; // // Defines for Initially Positioning Elements on // Pong Client Screens // static int PADDLE_WIDTH = 5; static int PADDLE_HEIGHT = 30; static int PREFERRED_WIDTH = 300; static int PREFERRED_HEIGHT = 200; static int BALL_RADIUS=5; static int BALLX = PREFERRED_WIDTH/2+4*BALL_RADIUS; static int BALLY = PREFERRED_HEIGHT/2; static int BALLXVEL = 2; static int BALLYVEL = 2; static int MAXBALLVEL = 5; static int MINBALLX = 10; static int MAXBALLX = PREFERRED_WIDTH-BALL_RADIUS-MINBALLX; static int MINBALLY = 10; static int MAXBALLY = PREFERRED_HEIGHT-BALL_RADIUS-MINBALLY; static int FUDGE = 10; static int LSCORE_X = PREFERRED_WIDTH/6; static int RSCORE_X = 5*LSCORE_X, SCORE_Y=25; static int TEXT_X = 40; static int TEXT_Y = PREFERRED_HEIGHT/2; static int LPADDLEX = PADDLE_WIDTH; static int RPADDLEX = PREFERRED_WIDTH-2*PADDLE_WIDTH; static int PADDLEY = (PREFERRED_HEIGHT-PADDLE_HEIGHT)/2; static int MAXPADDLEVEL =5; static int MINPADDLE = 10; static int MAXPADDLE = PREFERRED_HEIGHT-MINPADDLE-PADDLE_HEIGHT; static int MAXSCORE = 10; //score game ends at } /** * PongServer.java * * Title: PongServer * Description: This is the server for our Pong Game * @author cpollett * @version */ import java.io.*; import java.net.*; import java.awt.event.*; import javax.swing.*; public class PongServer implements PongClientServerDefines{ ServerSocket server; // TCP listener Socket pConnection[]; // connection for each player int pPort[]; // port player will listen to UDP on DatagramSocket transmitUDP; // used for sending UDP of positions of ball/players DatagramPacket packetUDP[]; // packet for sending; we reuse this a lot byte packetData[]; // array of data for packet DataInputStream pIn[]; // connection input output stream DataOutputStream pOut[]; int gamePhase; // gives current state of program int phaseCounter; // used to measure how long have been in current // state (multiple of 100ms) int whosePoint=0; // who scored the last point boolean ack[]; // in non playing phase we expect each player // to acknowledge our UDP transmissions // this var keeps track of whose done this Thread playerThread[]; //thread for managing each players comunication Timer timerUDP; // timer for UDP broadcasts int paddle[]; // y position for each player's paddle int paddleVel[]; // y velocity of each player's paddle int ballX; // ball x position int ballY; // ball y position int ballXVel; // ball X velocity int ballYVel; // ball Y velocity int lScore; // left player's score int rScore; // right player's score // // Constructor Name: PongServer // // Purpose: initializes threads, timers, and sockets used by our server // public PongServer() { try { server = new ServerSocket(SERVERPORT,2); transmitUDP = new DatagramSocket(); } catch(Exception se) { se.printStackTrace(); System.exit(1); } packetUDP = new DatagramPacket[2]; packetData = new byte[8]; pConnection = new Socket[2]; pIn = new DataInputStream[2]; pOut = new DataOutputStream[2]; pPort = new int[2]; ack = new boolean[2]; playerThread = new Thread[2]; paddle = new int[2]; paddleVel = new int[2]; playerThread[0]= new Thread(new Runnable() { public void run() { playerTCP(0); } } ); playerThread[0].start(); playerThread[1]= new Thread(new Runnable() { public void run() { playerTCP(1); } } ); playerThread[1].start(); timerUDP = new Timer( 100, new ActionListener() { public void actionPerformed(ActionEvent e) { broadcastUDP(); } } ); } // // Method Name: runServer // // Purpose: gets a connection from each player // sets up streams, finds out UDP port player is listening to, // tells player which paddle he is. // public void runServer() { int i; while(true) { System.out.println("Server: Waiting for connections..."); try { for (i=0; i<2; i++) { pConnection[i] = server.accept(); System.out.println("Server: Player"+i+" connected."); pIn[i] = new DataInputStream( pConnection[i].getInputStream()); pPort[i]=pIn[i].readInt(); packetUDP[i] = new DatagramPacket(packetData, packetData.length, pConnection[i].getInetAddress(), pPort[i] ); pOut[i] = new DataOutputStream( pConnection[i].getOutputStream()); pOut[i].flush(); System.out.println("Server: Player"+i+" streams set up."); } pOut[0].writeInt(LPLAYER); pOut[1].writeInt(RPLAYER); } catch(Exception e) { e.printStackTrace(); System.exit(1); } startGame(); //main thread now waits until it's time to play again try { synchronized(this) { wait(); } } catch(Exception e) { e.printStackTrace(); System.exit(1); } stopGame(); } } // // Method Name: startGame // // Purpose: sets up scores, ball, paddle locations as at start of game. // starts UDP broadcaster timer, tells player thread to process // to TCP messages. // public void startGame() { startPoint(); lScore = 0; rScore = 0; gamePhase = STARTGAMECODE; phaseCounter = 0; timerUDP.start(); // // Notify player threads that we are going to play a game // try { synchronized(this) { notifyAll(); } } catch(Exception e) { e.printStackTrace(); System.exit(1); } } // // Method Name: startGame // // Purpose: sets up ball, paddle locations as at start of round. // ball initial velocity random. // public void startPoint() { for(int i=0; i<2; i++) { paddle[i] = PADDLEY; paddleVel[i] = 0; ack[i] = false; } ballX = BALLX; ballY = BALLY; ballXVel = (Math.random() > .5)? BALLXVEL : -BALLXVEL; ballYVel = (Math.random() > .5)? BALLYVEL : -BALLYVEL; } // // Method Name: stopGame // // Purpose: stops UDP broadcaster thread. // public void stopGame() { timerUDP.stop(); } // // Method Name: broadcastUDP // // Purpose: main function for UDP broadcaster timer. // sends packets to client according to game phase. // public void broadcastUDP() { switch(gamePhase) { case STARTGAMECODE: phaseHandler(STARTGAMELENGTH, STARTPOINTCODE); break; case STARTPOINTCODE: if(phaseHandler(STARTPOINTLENGTH, PLAYINGCODE)) startPoint(); break; case ENDPOINTCODE: phaseHandler(ENDPOINTLENGTH, STARTPOINTCODE); break; case ENDGAMECODE: if(phaseHandler(ENDGAMELENGTH, STARTGAMECODE)) { try { synchronized(this) { notify(); // notify main thread game's over // main thread will stop game } } catch(Exception e) { e.printStackTrace(); System.exit(1); } } break; default: updateScreen(); } } // // Method Name: phaseHandler // // Purpose: for non playing game states write out appropriate // packet if haven't gotten an acknowledgement yet. // if both players have acknowledge than start counting // 100ms blocks for how long this phase is supposed to last // public boolean phaseHandler(int phaseLength, int nextPhase) { boolean flag =false; for(int j=0; j < 8; j++) packetData[j] = (new Integer(gamePhase)).byteValue(); for(int i=0; i < 2; i++) { if(!ack[i]) { try { transmitUDP.send(packetUDP[i]); } catch(Exception e) { e.printStackTrace(); } } } if(ack[0] && ack[1]) { if(phaseCounter < phaseLength) phaseCounter++; else { ack[0]=false; ack[1]=false; gamePhase = nextPhase; phaseCounter = 0; flag =true; } } return flag; } // // Method Name: updateScreen // // Purpose: games during playing state to update the positions of // ball/paddles on screen. Check to see if anything went of // bounds and does appropriate. If ball goes out of // bound the state is change to either end point or end game. // public void updateScreen() { ballX += ballXVel; ballY += ballYVel; if(ballY < MINBALLY) { ballYVel = -ballYVel; ballY = 10; } if(ballY > MAXBALLY) { ballYVel = -ballYVel; ballY = MAXBALLY; } if(ballX < MINBALLX+FUDGE && ballY > paddle[0] && ballY < paddle[0]+ PADDLE_HEIGHT) { ballXVel = -(ballXVel-1); ballYVel = (ballYVel + paddleVel[0])/2; } if(ballX > MAXBALLX-FUDGE && ballY > paddle[1] && ballY < paddle[1]+ PADDLE_HEIGHT) { ballXVel = -(ballXVel+1); ballYVel = (ballYVel + paddleVel[1])/2; } for(int i=0; i<2; i++) { paddle[i] += paddleVel[i]; if(paddle[i] < MINPADDLE) { paddle[i] = MINPADDLE; paddleVel[i] = 0; } if(paddle[i] > MAXPADDLE) { paddle[i] = MAXPADDLE; paddleVel[i] = 0; } } if(ballX <MINBALLX) { whosePoint = 2; rScore++; if(rScore < MAXSCORE) gamePhase = ENDPOINTCODE; else gamePhase = ENDGAMECODE; } if(ballX > MAXBALLX) { whosePoint = 1; lScore++; if(lScore < MAXSCORE) gamePhase = ENDPOINTCODE; else gamePhase = ENDGAMECODE; } sendCoords(); } // // Method Name: sendCoords // // Purpose: function used by updateScreen to convert // ball/paddle locations into UDP packet data and transmit. // // public void sendCoords() { // ball X ccord. packetData[0]= (new Integer(ballX >> 8)).byteValue(); packetData[1]= (new Integer(ballX & 255)).byteValue(); // ball Y coord packetData[2]= (new Integer(ballY >> 8)).byteValue(); packetData[3]= (new Integer(ballY & 255)).byteValue(); // left paddle Y packetData[4]= (new Integer(paddle[0] >> 8)).byteValue(); packetData[5]= (new Integer(paddle[0] & 255)).byteValue(); // right paddle Y packetData[6]= (new Integer(paddle[1] >> 8)).byteValue(); packetData[7]= (new Integer(paddle[1] & 255)).byteValue(); try { for(int i =0; i<2; i++) { transmitUDP.send(packetUDP[i]); } } catch(Exception e) { e.printStackTrace(); } } // // Method Name: playerTCP // // Purpose: function used by player thread used to // manage TCP communication with a player client. // if game not begun this function causes the thread to wait. // Once game started thread tries to read from input stream // In play state this info is used to move the player up or down. // In other states, the signal is compared to the current // game state and the game state is echoed to client so // client know is can ignore last UDP message. If signal // and game state are equal the appropriate action for that state is // taken. // public void playerTCP(int player) { int signal; while(true) { signal = STARTGAMECODE; try { synchronized(this) { wait(); } while(signal != ENDGAMECODE) { signal = pIn[player].readInt(); switch(signal) { case STARTGAMECODE: pOut[player].writeInt(gamePhase); if(gamePhase == signal) { ack[player] =true; } System.out.println("Player"+player+"acknowledges start game."); System.out.println(" Game Phase is "+gamePhase+"."); break; case STARTPOINTCODE: pOut[player].writeInt(gamePhase); if(gamePhase == signal) { ack[player] =true; } System.out.println("Player"+player+"acknowledges start point."); System.out.println(" Game Phase is "+gamePhase+"."); break; case ENDPOINTCODE: pOut[player].writeInt(gamePhase); if(gamePhase == signal) { pOut[player].writeInt(whosePoint); pOut[player].writeInt(lScore); pOut[player].writeInt(rScore); ack[player] =true; } System.out.println("Player"+player+"acknowledges end point."); System.out.println(" Game Phase is "+gamePhase+"."); break; case ENDGAMECODE: pOut[player].writeInt(gamePhase); System.out.println("Player"+player+"acknowledges end game."); System.out.println(" Game Phase is "+gamePhase+"."); if(gamePhase == ENDGAMECODE) { ack[player] =true; pOut[player].writeInt(whosePoint); pOut[player].writeInt(lScore); pOut[player].writeInt(rScore); pIn[player].close(); pOut[player].close(); pConnection[player].close(); System.out.println("Player"+player+"connection closed."); } break; case UPCODE: if( - MAXPADDLEVEL < paddleVel[player]) paddleVel[player]--; break; case DOWNCODE: if( paddleVel[player] < MAXPADDLEVEL) paddleVel[player]++; break; }// end switch }// end while signal } // end try catch(Exception e) { e.printStackTrace(); System.exit(1); } } // end while true } // Main entry point static public void main(String[] args) { PongServer app = new PongServer(); app.runServer(); } } /** * PongClient.java * * Title: Client For Pong Game * (most of work gets done in this classes frame) * Description: * @author cpollett * @version */ import PongFrame; public class PongClient { public PongClient() { try { PongFrame frame = new PongFrame(); frame.initComponents(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } // Main entry point static public void main(String[] args) { new PongClient(); } } /** * PongFrame.java * * Title: Client Frame For Pong Game * Description: * @author cpollett * @version */ import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; public class PongFrame extends java.awt.Frame implements PongClientServerDefines { boolean connectMode=false; //tells whether a connection has been established DatagramSocket listenerUDP; // used to listen for UDP packets DatagramPacket receivePacket; // reused to receive packets from listener Socket keySocket; // TCP socket used to send keystroke info to server DataInputStream in; // it input/output streams DataOutputStream out; int player; //holds which player client is. String msg; // holds message to be printed in PongScreen. int lScore; // left score to be printed in PongScreen int rScore; // right score to be printed in PongScreen int whosePoint; // who scored the last point int xBall; //ball position int yBall; int yL; //left paddle y int yR; //right paddle y Thread threadUDP; //thread for handling UDP packets Thread threadConnect; // auxiliary thread used by connect button // to do the actual connecting byte data[]; // IMPORTANT: Source code between BEGIN/END comment pair will be regenerated // every time the form is saved. All manual changes will be overwritten. // BEGIN GENERATED CODE // member declarations javax.swing.JButton connectButton = new javax.swing.JButton(); javax.swing.JTextField serverURLField = new javax.swing.JTextField(); javax.swing.JLabel serverLabel = new javax.swing.JLabel(); PongPanel pongPanel1 = new PongPanel(); // END GENERATED CODE // // Constructor Name: PongFrame // // Purpose: initializes threads, and sockets used by our client // public PongFrame() { try { listenerUDP = new DatagramSocket(); } catch(SocketException se) { se.printStackTrace(); System.exit(1); } data = new byte[ 8 ]; receivePacket = new DatagramPacket(data, data.length); threadUDP = new Thread(new Runnable() { public void run() { listenUDP(); } } ); threadUDP.start(); threadConnect = new Thread(new Runnable() { public void run() { listenConnect(); } } ); threadConnect.start(); } // // Method Name: initComponents // // Purpose: automatically generated function from CodeWarrior // It sets up all the GUI components of our client. // public void initComponents() throws Exception { // IMPORTANT: Source code between BEGIN/END comment pair will be regenerated // every time the form is saved. All manual changes will be overwritten. // BEGIN GENERATED CODE // the following code sets the frame's initial state connectButton.setSize(new java.awt.Dimension(100, 28)); connectButton.setLocation(new java.awt.Point(360, 40)); connectButton.setVisible(true); connectButton.setText("Connect"); serverURLField.setSize(new java.awt.Dimension(220, 30)); serverURLField.setLocation(new java.awt.Point(130, 40)); serverURLField.setVisible(true); serverLabel.setSize(new java.awt.Dimension(100, 30)); serverLabel.setLocation(new java.awt.Point(10, 40)); serverLabel.setVisible(true); serverLabel.setText("Server URL:"); pongPanel1.setSize(new java.awt.Dimension(300, 200)); pongPanel1.setLocation(new java.awt.Point(90, 90)); pongPanel1.setVisible(true); pongPanel1.setText("PongClient"); pongPanel1.setLayout(null); setLocation(new java.awt.Point(0, 0)); setSize(new java.awt.Dimension(511, 335)); setBackground(java.awt.Color.white); setLayout(null); setTitle("PongFrame"); add(connectButton); add(serverURLField); add(serverLabel); add(pongPanel1); connectButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { connectButtonActionPerformed(e); } }); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { thisWindowClosing(e); } }); addKeyListener(new java.awt.event.KeyAdapter() { public void keyTyped(java.awt.event.KeyEvent e) { thisKeyTyped(e); } }); // END GENERATED CODE } private boolean mShown = false; public void addNotify() { super.addNotify(); if (mShown) return; // move components to account for insets Insets insets = getInsets(); Component[] components = getComponents(); for (int i = 0; i < components.length; i++) { Point location = components[i].getLocation(); location.move(location.x, location.y + insets.top); components[i].setLocation(location); } mShown = true; } // Close the window when the close box is clicked void thisWindowClosing(java.awt.event.WindowEvent e) { setVisible(false); dispose(); System.exit(0); } // // Method Name: thisKeyTyped // // Purpose: called by our KeyListener. If in connected // writes to server either up or down if the appropriate key pressed // public void thisKeyTyped(java.awt.event.KeyEvent e) { if(connectMode==false) return; char key = e.getKeyChar(); int output = PLAYINGCODE; switch(player) { case LPLAYER: if( key == '1') output = UPCODE; if( key == '2') output = DOWNCODE; break; case RPLAYER: if( key == '9') output = UPCODE; if( key == '0') output = DOWNCODE; break; } try { out.writeInt(output); } catch(Exception ex) { ex.printStackTrace(); } } // // Method Name: connectButtonActionPerformed // // Purpose: called when connect button pressed to // try to establish a connection with a given // server. It works by notifying the auxiliary thread // threadConnect. Which continues executing listenConnect() // below. // public void connectButtonActionPerformed(java.awt.event.ActionEvent e) { if(connectMode==true) return; pongPanel1.setText("Connecting..."); pongPanel1.repaint(); try { synchronized(this) { notify(); } } catch(Exception ex) { ex.printStackTrace(); } } // // Method Name: listenUDP // // Purpose: main function executed by of UDP thread. // It mainly waits for packets. Then processes // the information contained in them // private void listenUDP() { while(true) { try { listenerUDP.receive(receivePacket); } catch(IOException io) { System.err.println(io.toString()); } if(connectMode == true) { if(!checkChangeMode()) getCoords(); updateScreen(); pongPanel1.repaint(); } } } // // Method Name: listenConnect // // Purpose: main function executed by our connect thread. // It excecutes if the mode is not connect mode // and the connect button has notified it. // It tries to establish a TCP connection // with the server in question and sends info // to server about which port to send packets to. // private void listenConnect() { while(true) { try { synchronized(this) { wait(); //for connect button } } catch(Exception io) { System.err.println(io.toString()); } if(connectMode == false) { String text = serverURLField.getText(); try { keySocket= new Socket(InetAddress.getByName(text),SERVERPORT); in = new DataInputStream(keySocket.getInputStream()); out = new DataOutputStream(keySocket.getOutputStream()); pongPanel1.setText("Connected."); pongPanel1.repaint(); out.flush(); out.writeInt(listenerUDP.getLocalPort()); pongPanel1.setText("Waiting for opponent."); pongPanel1.repaint(); player = in.readInt(); pongPanel1.setText("You are Player"+player+"."); pongPanel1.repaint(); connectMode = true; } catch(Exception ex) { ex.printStackTrace(); } } } } // // Method Name: checkChangeMode // // Purpose: checks if the packets just received contains // data that would cause a change of mode // if so acknowledge to server mode change. // and get any additional data from server. // private boolean checkChangeMode() { boolean endGame = true; boolean endPoint = true; boolean startGame = true; boolean startPoint = true; for(int i=0; i<7; i++) { if(data[i] != ENDGAMECODE) endGame = false; if(data[i] != ENDPOINTCODE) endPoint = false; if(data[i] != STARTGAMECODE) startGame = false; if(data[i] != STARTPOINTCODE) startPoint = false; } if(endGame) endGameHandler(); if(endPoint) endPointHandler(); if(startGame) startGameHandler(); if(startPoint) startPointHandler(); return endGame && endPoint && startGame && startPoint; } // // Method Name: getCoords // // Purpose: converts packets data to coordinates for each screen object // private void getCoords() { xBall = (data[0]<<8) + (data[1] & 255); //the & 255 is since byte is //otherwised signed. yBall = (data[2]<<8) + (data[3] & 255); yL = (data[4]<<8) + (data[5] & 255); yR = (data[6]<<8) + (data[7] & 255); } // // Method Name: updateScreen // // Purpose: used current data about object to update Pong Screen // private void updateScreen() { pongPanel1.setBallX(xBall); pongPanel1.setBallY(yBall); pongPanel1.setLPaddleY(yL); pongPanel1.setRPaddleY(yR); pongPanel1.setLScore(lScore); pongPanel1.setRScore(rScore); pongPanel1.setText(msg); pongPanel1.repaint(); } // // Switch phase handlers called by checkChangedMode // each handle the end of given named phase. // private void endGameHandler() { int signal; try { out.writeInt(ENDGAMECODE); signal = in.readInt(); if(signal == ENDGAMECODE) { whosePoint = in.readInt(); lScore = in.readInt(); rScore = in.readInt(); msg= "Player"+whosePoint+" wins!"; out.close(); in.close(); keySocket.close(); connectMode = false; } } catch(Exception e) { e.printStackTrace(); } } private void endPointHandler() { int signal; try { out.writeInt(ENDPOINTCODE); signal = in.readInt(); if(signal == ENDPOINTCODE) { whosePoint = in.readInt(); lScore = in.readInt(); rScore = in.readInt(); msg="Player"+whosePoint+" scores!"; } } catch(Exception e) { e.printStackTrace(); } } private void startGameHandler() { int signal; try { out.writeInt(STARTGAMECODE); signal = in.readInt(); if(signal == STARTGAMECODE) { msg="Start Game"; lScore = 0; rScore = 0; } } catch(Exception e) { e.printStackTrace(); } } private void startPointHandler() { int signal; try { out.writeInt(STARTPOINTCODE); signal = in.readInt(); if(signal == STARTPOINTCODE) { msg = ""; } } catch(Exception e) { e.printStackTrace(); } } } /** * PongPanel.java * * Description: panel used to draw the current screen of the pong game in the * client. At home this was a Java Bean * @author cpollett * @version */ import java.awt.*; import javax.swing.*; import PongClientServerDefines; public class PongPanel extends javax.swing.JPanel implements PongClientServerDefines { int lPaddleX, lPaddleY, lScore; int rPaddleX, rPaddleY, rScore; int ballX, ballY; String text; public PongPanel() { setBackground(Color.black); lPaddleX = LPADDLEX; lPaddleY = PADDLEY; lScore=0; rPaddleX = RPADDLEX; rPaddleY = PADDLEY; rScore=0; ballX = BALLX; ballY = BALLY; setText("PongClient"); } public void setText(String t) { text = t; } public String getText() { return text; } public void setLScore(int lS) { lScore = lS; } public int getLScore() { return lScore; } public void setRScore(int rS) { rScore = rS; } public int getRScore() { return rScore; } public void setLPaddleX(int x) { lPaddleX=x; } public int getLPaddleX() { return lPaddleX; } public void setLPaddleY(int y) { lPaddleY=y; } public int getLPaddleY() { return lPaddleY; } public void setRPaddleX(int x) { rPaddleX=x; } public int getRPaddleX() { return rPaddleX; } public void setRPaddleY(int y) { rPaddleY=y; } public int getRPaddleY() { return rPaddleY; } public void setBallX(int x) { ballX=x; } public int getBallX() { return ballX; } public void setBallY(int y) { ballY=y; } public int getBallY() { return ballY; } public void paintComponent( Graphics g) { int spacing = PREFERRED_HEIGHT/10, dash = 3*spacing/4; int center = (PREFERRED_WIDTH-PADDLE_WIDTH)/2; super.paintComponent(g); g.setColor(Color.white); g.setFont(new Font("Monospaced", Font.PLAIN, 24)); g.drawString(""+lScore, LSCORE_X, SCORE_Y); g.drawString(""+rScore, RSCORE_X, SCORE_Y); g.drawString(text, TEXT_X, TEXT_Y); g.fillRect(lPaddleX,lPaddleY, PADDLE_WIDTH, PADDLE_HEIGHT); g.fillRect(rPaddleX,rPaddleY, PADDLE_WIDTH, PADDLE_HEIGHT); g.fillOval(ballX, ballY, BALL_RADIUS, BALL_RADIUS); for( int i=0; i< 10;i++) { g.fillRect(center, i*spacing, PADDLE_WIDTH,dash); } } public Dimension getPreferredSize() { return new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT); } public Dimension getMinimumSize() { return getPreferredSize(); } } /* @(#)PongPanel.java */ |