import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; // Dilip Barman November 22, 1997 // file AnimationObject.java // 3rd java homework assignment to play with multimedia and double buffering. // This is the class used by the main class, DilipsAnimationApplet public class AnimationObject extends Thread // Each object runs as a thread { // *********** Debug Variables *********** static DebugWindow debugWindow = new DebugWindow("AnimationObject"); private boolean debugMode = true; // set to true to enable debug window msgs // can use statements like this in code: // if (debugMode) { debugWindow.print("Just created frame"); } // *********** Constants *********** // *********** Class Variables *********** // *********** Instance Variables *********** Graphics g; Dimension outareaSize; Applet parentApplet; // passed in - what applet we're coming from int delay; static Random random = new Random(); // static Image bikeImage = Toolkit.getDefaultToolkit().getImage // ("images/bikeFridayLogo3.gif"); int xPos, yPos; // Object location long incr, xincr, yincr, theta; // Movement increments and angle int boundaryLeft, boundaryRight, boundaryTop, boundaryBottom; // output boundary box Color myColor; // Object color int myWidth; // Object width String myType; // Object type - circle, square // *********** Constructor and Destructor Methods *********** // AnimationObject ( Graphics graphicsContext, Dimension frameSize ) // { super (); g = graphicsContext; outareaSize= frameSize; init (); } // Store graphics context, drawing dimensions, and parent applet AnimationObject ( Graphics graphicsContext, Dimension frameSize, Applet callingApplet ) { super (); if (debugMode) { debugWindow.print("Entering constructor with parent Applet:"); debugWindow.print (" '" + callingApplet + "'"); } g = graphicsContext; outareaSize= frameSize; parentApplet = callingApplet; init (); if (debugMode) { debugWindow.print("Exiting constructor"); } } // end constructor // Destructor - to kill debug window if it exists; I couldn't figure out how to // make it a class method that I could call, so I must call it as a message to // an instance. public void quit() { if (debugMode) { debugWindow.print("About to quit"); debugWindow.setVisible (false); } } //protected void finalize() // { // if (debugMode) // { // debugWindow.print("About to quit"); // debugWindow.setVisible (false); // } // } // *********** run() Method for Thread *********** public void run () { try { while ( true ) { // White(=background)-out old position, get new (x,y) coordinates, // and draw object in its new position synchronized ( g ) { g.setColor ( Color.white ); if (myType == "circle") { g.fillOval ( xPos, yPos, myWidth, myWidth ); } else { g.fillRect ( xPos, yPos, myWidth, myWidth ); } moveObject (); g.setColor ( myColor ); if (myType == "circle") { g.fillOval ( xPos, yPos, myWidth, myWidth ); } else { g.fillRect ( xPos, yPos, myWidth, myWidth ); } // g.drawImage(bikeImage, xPos, yPos, parentApplet); } // end synchronized sleep ( delay ); } // end while } // end try catch ( InterruptedException except) { System.out.println ( "Interrupt in AnimationObject" ); return; } // end catch } // end run // *********** Methods to Initialize and Delete Objects *********** private void init () { if (debugMode) { debugWindow.print("Initializing object in init()"); } myWidth = 40; // size of object; we'll use 80% for squares incr = 3; delay = 15 - (int) (10 * random.nextFloat() ); // Assign object type at random if (random.nextFloat() <= .5) { myType = "circle"; } else { myType = "square"; myWidth = 32; } boundaryLeft = 0; boundaryRight = outareaSize.width - myWidth; boundaryTop = 0; boundaryBottom = outareaSize.height - myWidth ; boolean test = true; while ( test ) { // Pick random (x,y) in bounds, subtracting space object occupies xPos = (int)( (outareaSize.width - myWidth) * random.nextFloat () ); yPos = (int)( (outareaSize.height - myWidth) * random.nextFloat () ); if ( ( xPos > 5 ) && ( yPos > 5 ) ) test = false; } test = true; while ( test ) { theta = (long)( 360 * random.nextFloat () ); // choose rnd angle xincr = (long)(incr * Math.cos ( theta ) ); // calc (x,y) displacements yincr = (long)(incr * Math.sin ( theta ) ); // in that direction if ( (Math.abs(xincr) > 1 ) && (Math.abs(yincr) > 1) ) test = false; } // end while // Choose random color int colorR = (int)( 255 * random.nextFloat () ); int colorG = (int)( 255 * random.nextFloat () ); int colorB = (int)( 255 * random.nextFloat () ); myColor = new Color ( colorR, colorG, colorB ); if (debugMode) { debugWindow.print("Done creating " + myType + " of width " + myWidth + " at (" + xPos + "," + yPos + ") and angle " + theta + "deg and of color R=" + colorR + " G=" + colorG + " B=" + colorB + "."); } } // end init public void delete () { if (debugMode) { debugWindow.print("AnimationObject: deleting object in delete()"); } g.setColor ( Color.white ); if (myType == "circle") { g.fillOval ( xPos, yPos, myWidth, myWidth ); } else // square { g.fillRect (xPos, yPos, myWidth, myWidth); } } // *********** Methods to Move Object an Increment *********** private void moveObject () // Move -- set xPos and yPos -- as per xincr and yincr increments; if // this would go past the boundary, "bounce" by reversing direction { if ( (int)(xPos + xincr) > boundaryRight || (int)(xPos + xincr) < boundaryLeft ) { xincr = -1 * xincr; } else xPos = (int)(xPos + xincr); if ( (int)(yPos + yincr) > boundaryBottom || (int)(yPos + yincr) < boundaryTop ) { yincr = -1 * yincr; } else yPos = (int)(yPos + yincr); } } // end AnimationObject class definition