/* Class: Lab2 extends Applet By: Leif Bjornsson, Tandem Computers Date: April 14, 1996 For: CSCI-397c OOP & Implementation Lab: Java lab 2. Descrption: This is the applet which contains the PING PONG game. It initiates and starts three threads. First, It initiates and starts the MyCanvas thread, and then the Ball thread. This applet is the monitor that synchronizes those two threads. It also contains the speed control, label, and some text. The applet has a syncrhonized put() method which is used by the Ball thread (which generates ball locations) to store the next ball location. The MyCanvas thread then retrieves the next location using the synchronized get() method. In addition the MyCanvas puts the mouse location in the Canvas in the synchronized putMousePos() method. The Ball thread then retrives that variable using synchronized getMousePos() when it needs to know the racket location (only when the ball is hitting the X axix. The introductory audio runs as a thread (introAudio) to prevent the sound to play from pausing the game. */ // Import stuff import java.awt.*; import java.applet.*; // // Class definition begins // public class Lab2 extends Applet { Thread threadCanvas, ball, introAudio; MyCanvas drawCanvas; Point next; boolean notGet, notPut; int mouse_x = 0, speed = 1; Label speedLabel; Panel p1; // // Init initializes the applet at startup (the longest method) // public void init() { // Set applet layout to flow having all objects centered setLayout(new FlowLayout(FlowLayout.CENTER,15,20)); // Set layout // Instanciate and add the MyCanvas to applet drawCanvas = new MyCanvas(Color.white, Color.blue, 300, 200, this); add(drawCanvas); // Set the font for the applet setFont(new Font("TimesRoman",Font.PLAIN,12)); // Create a new panel to store the controls and controls text p1 = new Panel(); // New panel p1.setLayout(new FlowLayout(FlowLayout.CENTER,2,15)); // Same layout p1.add(new Label("Use slidebar to control speed. ")); // Add text p1.add(new Scrollbar(Scrollbar.HORIZONTAL,1,0,1,5)); // Add scrollb. p1.add(new Label("Speed =")); // Add text // Speed displays the speed selected by the scrollbar speedLabel = new Label("1"); // Default speed is 1 speedLabel.setAlignment(Label.LEFT); // Left justify label text p1.add(speedLabel); // Add speed to control panel this.add(p1); // Add panel to applet next = new Point(0,0); // Instance that stores next ball loc. // Flags used for synchronizes put and get (see put() and get() notGet = false; // MyCanvas hasn't retrived a loc yet notPut = true; // Ball hasn't put a loc yet. introAudio = new PlayAudio(this,"hi.au", 2); // Intro audio } // End init() // // Overwrite insets() which creates a margin on the applet // public Insets insets() { return new Insets(30,20,20,20); // Margin (x1,y1,x2,y2) } // End insets() // // Start is run when the applet is displayed on screen. Will start threads // public void start() { introAudio.start(); // Start playing intro audio (thread) try {Thread.sleep(500); } // Sleep a little for user to get ready catch (InterruptedException e) {}; // to start game // If MyCanvas thread hasn't been created, do using threadCanvas name if (threadCanvas == null) threadCanvas = new Thread(drawCanvas); // Instanciate ball thread with music urls for hitting wall and missing if (ball == null) { ball = new Ball("Ball",25,this, getAudioClip(getDocumentBase(), "gong.au"), getAudioClip(getDocumentBase(), "Explosion-2.au")); // Give the ball a higher priority than MyCanvas ball.setPriority(threadCanvas.getPriority() + 1); // Start ball and threadCanvas (game starts) ball.start(); threadCanvas.start(); } } // End start() // // Stop is run if the applet leaves the screen. Stop all threads // public void stop() { // Stop the threadCanvas thread if (threadCanvas != null) { threadCanvas.stop(); threadCanvas = null; } // Stop the ball thread if (ball != null) { ball.stop(); ball = null; } } // End stop() // // Handes the scrollbar event. Will comunicate new speed to ball thread // public boolean handleEvent(Event evt) { Ball b; // Have to use because of necessary typecasting if (evt.target instanceof Scrollbar) { // If event scrollbar speed = ((Scrollbar)evt.target).getValue(); // Get scrollbar value speedLabel.setText(String.valueOf(speed)); // Set the display label b = (Ball) ball; // Typecast ball. Proved to be necessary b.setSpeed(speed); // Tell the ball thread about new speed } return true; } // End handleEvent() // // put() is called by thread Ball for the monitor to store a new ball location // If get hasn't retrived the previous put, put will wait until it does so. // public synchronized void put(int x, int y) { while ( notGet ) { // If last ball location hasn't been retrived try { wait(); } // by threadCanvas, wait for it to do so. catch(InterruptedException e) {} } next.setLocation(x,y); // Store new ball location notPut = false; // Set put is done flag to true notGet = true; // Set get is done to false notifyAll(); // Get get() out of wait if it is waiting } // End put() // // The get() method is called by threadCanvas to retrive new ball location. // If put() hasn't stored a new location, it will wait until put send a notify // public synchronized Point get() { Point tmp = null; // Temp var used for returning value while ( notPut ) { // If nothing to get try {wait(); } // Wait until notify signal from put catch(InterruptedException e) { return null;} } tmp = next; // Store new ball location in temp var notPut = true; // Set put is done flag to false notGet = false; // Set get is done flag to true notifyAll(); // Notify put if it is waiting return(tmp); // Return new ball location to threadCanvas } // End get() // // Returns the current racket location in canvas // The getMousePos() gets called by Ball if the ball is about to hit the x-axis. // It needs to know the racket location to determine if there was a miss or hit // public synchronized int getMousePos() { return(mouse_x); } // End getMousePos() // // Store the current racket location in canvas // This method gets called by threadCanvas to store the current racket loc. // The Ball thread retrives this value using getMousePos() when it needs it. // public synchronized void setMousePos(int x) { mouse_x = x; } // End putMousePos() // // Update calls paint. By overwring, no clearscreen -> flicker is reduced // public void update(Graphics g) { paint(g); } // // Paint the window. // public void paint(Graphics g) { // Only draws the intro text onto applet g.drawString("CSCI-397c. Java Lab II",140,12); g.drawString("Author: Leifur B. Bjornsson, Tandem Computers", 72,28); } // End paint() } // End class Lab2