© 2000-2003 A-Square, Inc. Cambridge, MA
>
/*
* Banner1 applet Version 2.0
*
* Jan Aminoff , September 2000
* © A-Square 1997-2000.
*
*/
import java.awt.*;
import java.applet.Applet;
/**
* This Applet demonstrates the main components of successful animations
* including double buffering and simple user/applet interaction.
* It also introduces some of the main elements of Java syntax.
*
* author Jan Aminoff/ © A-Square 1997
* version 2.0, modified September 2000, for use at IEEE/A-Square
* Introduction to Java, tutorial.
*
* This version should compile and run under JDK 1.0.2
*/
public class Banner1 extends Applet implements Runnable {
///////////////////////////////////////////////////////////////////////////
// The Java coding conventions dictate that any Java class starts out by
// declaring the public methods, that is the methods whereby the outside
// world can use an instantiated class object.
//
// The Banner1 class declares the following public methods and no public
// variables: init, start, run, stop, mouseDown, and update.
///////////////////////////////////////////////////////////////////////////
/*
* The init() method is prescribed by the Applet class, or more
* precisely, the init() method here overrides a method in the
* Applet class that Banner1 extends. In what is typical for applets this
* method sets up the initial conditions from which the update or paint
* methods can start the action rolling.
*/
public void init() {
// Set maxx and maxy to the size of the applet window given in the
// applet tag,that is the html document initializing the applet.
maxx = size().width;
maxy = size().height;
/* The following is an example of exception handling, a real cool Java
* thing. In this case we attempt to create an offscreen graphics
* resource. If this is not possible, perhaps because we are running
* out of memory, the line that includes a call to the library method
* will generate an out of memory exception. Below, the catch clause is
* executed for any exception causing the gc graphics variable to have
* the value null.
*/
try {
// allocate an offscreen graphics
imagebuffer = createImage(maxx, maxy);
gc = imagebuffer.getGraphics();
// clear it
gc.setColor(Color.lightGray);
gc.fillRect(0, 0, maxx, maxy );
}
catch (Exception e) { gc = null; }
// The following gives initial values to position (x,y) and
// speed (dx, dy) of the Logo
x = 50 ;
y = maxy/2 ;
// Initial movement to NW
dx = -1;
dy = -1;
}
/* Normally private variables would be placed at the end of the class
* source. We are giving them here to allow them to be considered in the
* textual context where they are set initially.
*/
private Graphics gc; // used for drawing
private Image imagebuffer; // Used for drawing when double buffering
// The applet appears as a rectangle with upper left coordinates (0, 0)
// and lower right coordinates (maxx, maxy),.
private int maxx; // The right edge of the applet
private int maxy; // The lower edge of the applet
private int maxv =8; // Max speed of logo
private int x, y; // Position of Logo
private int dx, dy; // Speed of Logo
// End of init and declarations of private variables initiated in init.
/*
* The following three public methods: start, stop and run deal with a thread
* of execution. run() is prescribed by the Runnable Interface. The methods are
* useful to allow programs outside the Applet to control the animation.
*/
public void start() {
if (clock == null) {
clock = new Thread(this, "Banner");
clock.start();
}
}
/*
* The run method interupts execution for stime milliseconds between repaints.
* This is a crude way to get the applet to execute frames at a rate which is
* relatively independent of processor speed.
*/
public void run() {
while (clock != null) {
try {
clock.sleep(stime); //wait for stime milliseconds.
}
catch (InterruptedException e) {} //resume
repaint();
}
clock = null;
}
public void stop() {
if (clock != null) {
clock.stop();
clock = null;
}
}
private Thread clock = null; //A thread is a thread of execution
/* If dtime is 1000 milliseconds then stime is about 25 milliseconds which
* means there are about 40 frames in a second if the time to do the
* actual animation is ignored. This should give a smooth animation.
*/
private int dtime=1000;
private int stime=dtime/40;
// End of Runnable related methods and variables
/*
* mouseDown, Library method called when the user presses the mouse.
*
* The mouseDown method is now depreciated and replaced with more general
* but also more complex methods for event handling. However, we use the
* older method to be compatible with older browsers. The Java virtual
* machine automatically invokes the mouseDown method when the user
* presses the mouse button. In this case we are not intersted in
* xd and yd, which would give the coordinates for the mouse click.
*/
public boolean mouseDown(java.awt.Event evt, int xd, int yd) {
if (move){
dx1=dx;
dx=0;
dy1=dy;
dy=0;
}else{
dx=dx1;
dy=dy1;
}
move=!move;
return true;
}
private boolean move=true; // This variable says that the logo is moving
private int dx1, dy1; // Placeholders for speed component when not moving
// End of mouseDown method and related private variables
/*
* The update method is prescribed by the Applet.
*
* The update method is called periodically. It has two branches depending
* on wether or not we were succesfull in securing us a buffer for double
* buffering.
* If the imagebuffer is null we have to paint this applet directly
* on the graphichs context g.
*/
public void update(Graphics g)
{
if (imagebuffer != null) {
paintBanner(gc);
g.drawImage(imagebuffer, 0, 0, this);
}
else {
g.clearRect(0, 0, maxx, maxy);
paintBanner(g);
}
}
///////////////////////////////////////////////////////////////////////////
// Following the declarations of public methods and variables, the Java
// coding conventions require the positioning of private methods and
// variables. The Banner1 class has the following private methods:
// paintBanner, drawAsquare, and some private methods RND, ABS and
// printString which may be considered utility methods.
///////////////////////////////////////////////////////////////////////////
/*
* The paintBanner method paints the whole rectangle (0, 0, maxx, maxy)
* using the graphics context g. It starts by painting it all light gray.
* It then draws the Logo at x,y and draws the three strings s1, s2 and s3.
* It then moves the Logo and does the right thing if the center of the
* Logo should happen to hit any edge.
*/
private void paintBanner(Graphics g){
// This method paints the whole rectangle (0,0, maxx, maxy) starting
// with a blanked out rectangle:
g.setColor(Color.lightGray);
g.fillRect(0, 0, maxx, maxy); // Paint the screen light gray
drawAsquare(g, x, y, 35); // Draw A-Square logo
printString(g, s1, maxx,45 ,24);// Draw the three strings
printString(g, s2, maxx,70 ,12);
printString(g, s3,maxx,maxy-5,9);
//Move center of A-Square logo
x += dx;
y += dy;
// Check to see if the point hit the edge
// Check to see if the point hit the edge in the x-direction
if (x < 0 || x > maxx ) {
dx = (x < 0)? ABS(dx):-ABS(dx); //Point alwayas moves toward center
x += 2*dx; //Double back
do dy = maxv/2-RND(maxv); while (dy ==0); //change speed in y-direction
}
// Check to see if the point hit the edge in the y-direction
if (y < 0 || y > maxy ){
dy = (y < 0)? ABS(dy):-ABS(dy); //Point alwayas moves toward center
y += 2*dy; //Double back
do dx = maxv/2-RND(maxv); while (dx ==0); //change speed in x-direction
}
}
private String s1="Welcome to Introductory Java";
private String s2="Jan Aminoff, Instructor";
private String s3="Also inventor of RARTª, Random Art for the Internet";
// End of paintBanner and declarations of strings
/*
* drawAsquare
* Draws A-Square Logo with center at x,y and size s
* A fairly staightforward use of the drawing of rectangles
* in different colors. I have selected a Logo for A-Square, easy to draw!
*/
private void drawAsquare(Graphics g, int x,int y,int s)
{
int w=s;
int h=(int) (1.2*s);
g.setColor(Color.darkGray);
g.fillRect(x-w,y-h,2*w,2*h);
w=(int) (0.8*w);
h=(int) (0.8*h);
g.setColor(Color.yellow);
g.fillRect(x-w,y-h,2*w,2*h);
g.setColor(Color.red);
g.fillRect(x-w,y-h,w,h);
g.fillRect(x,y,w,h);
}
/* Standard methods
*
* The following three methods are standard methods used throughout Rart.
* The first two break the Java convention of having method names that
* consist of lowercase verb followed by capitalized noun.
* Better names would have been genRandom and takeAbs. However, I have kept
* these names in the Rart systems for historic reasons since they
* emulate the QuickBasic methods of the same names from long long ago.
*
* They are declared static which means that they exist regardless of the
* instantiation of any Banner1 object.
*/
// RND generates any of the integers in the interval 0 to max - 1.
private static int RND(int max){
return (int)(java.lang.Math.random() * max);
}
// ABS(x) returns the absolute value of the integer x
private static int ABS(int x){
return ((x>0)? x: -x);
}
// The following prints the String st using the color blue and the font
// Helvetica at pointsize s according to coordinates x and y.
// The text is centered between 0 and x
private static void printString(Graphics g, String st, int x, int y, int s){
Font Hel = new Font("Helvetica", Font.BOLD, s);
g.setFont(Hel);
FontMetrics fm = g.getFontMetrics(Hel);
int cx=fm.stringWidth(st);
cx=(x-cx)/2;
g.setColor(Color.blue);
g.drawString( st, cx, y );
} // End of standard methods
} // End of Banner1
>