[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Examples] [Book] [Tutorial] [API]
In this laboratory session, you will develop a number of applets that do simple animation, including an applet that places a bouncing ball on the screen and an applet that prints a message, part by part. The purposes of this lab session are to
Prerequisite skills:
Required Java files:
Required HTML files:
Most animations are done within applets because it is often simpler to animate with applets. We will focus on applet-based animation because it is also somewhat simpler than application-based animation.
For animations to work correctly, you need to create what is called a
thread of computation. In order to successfully do animation,
you often need to do a number of independent and simulataneous
computations. By using threads, you permit the computer to do multiple
things at once (in effect, the computer can alternate between threads of
computation). Importantly, you can tell a thread to pause temporarily
(using sleep). By pausing and then redrawing, you can
do both simple and complex animations.
In order to develop an animated applet, you'll need to indicate that
your applet can be turned into a thread. You do this by noting that
your class implements Runnable.
You will also need to create start and stop
methods. As you might guess, start starts your applet
running. There is a fairly standard structure for most
start methods. You create a new thread from the current
applet and you start that thread. Similarly, stop stops
your applet (most often, by telling the thread to stop).
Here is a sketch of an applet that does animation (although this one
doesn't do much because the paint method is empty).
However, it does illustrate all of the key components of an animated
applet. That is, one must create a thread. The applet runs by
repeatedly going to sleep for a small amount of time, updating its
state, and then redrawing itself.
import java.awt.*;
import java.applet.*;
import java.util.Random;
/**
* A simple framework for an applet that does animation.
*
* @author Samuel A. Rebelsky
* @version 1.1 of March 1999
*/
public class AnimationApplet
extends Applet
implements Runnable {
// +--------+--------------------------------------------------
// | Fields |
// +--------+
/** The thread corresponding to the current applet. */
protected Thread thread;
// +-------------------------+---------------------------------
// | Standard Applet Methods |
// +-------------------------+
/**
* Initialize the applet.
*/
public void init() {
} // init()
/**
* Paint the current "animation frame" on the screen.
*/
public void paint(Graphics g) {
} // paint(Graphics)
/**
* Run the thread.
*/
public void run() {
// It appears that we keep going forever. However, external
// things (that is, the web browser) control when we stop.
while (true) {
try {
thread.sleep(50);
}
catch (InterruptedException ie) {
// Do nothing
}
// Update information for the animation
updateInformation();
// And repaint
repaint();
} // while
} // run()
/**
* Start the thread.
*/
public void start() {
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
} // start()
/**
* Stop the thread.
*/
public void stop() {
thread.stop();
} // stop()
// +-------------------------+---------------------------------
// | Standard Applet Methods |
// +-------------------------+
/**
* Update information to support the next "frame" in the
* animation.
*/
public void updateInformation() {
} // updateInformation()
} // AnimationApplet
The first key part of this applet is the start
method. This creates a new thread corresponding to the current
object (the animation applet) and starts the thread. As this
suggests, Java does not automatically create threads for you;
you need to create them yourself (and keep track of them).
The more interesting part is the run method.
In this method, we repeatedly put the thread to sleep (basically,
pause between frames). When it wakes up, we update local
information and then repaint.
How does this provide animation? If we design the paint
method to paint one frame of animation, then we now have a situation
in which we get a frame every n milliseconds, which is what
happens in animation.
Here's how we might put this together to get a ``bouncing'' ball (or at least a bouncing circle). We need to keep track of the x and y positions of the ball. We can do that with two fields.
/** The current x position of the center of the ball. */ protected int xpos; /** The current y position of the center of the ball. */ protected int ypos;
At each step, we need to change those positions before painting the ball (Java handles the erasing for us, so we just have to paint). How do we know how to change them? We'll create two fields to keep track of the horizontal and vertical velocities.
When do we change these velocities? When it hits a wall. You should think about how one might determine that.
import java.awt.*;
import java.applet.*;
import java.util.Random;
/**
* A simple implementation of a bouncing ball.
* <p>
* Copyright (c) 1998 Samuel A. Rebelsky. All rights reserved.
*
* @author Samuel A. Rebelsky
* @version 1.1 of March 1999
*/
public class BallApplet
extends Applet
implements Runnable
{
// +------------+----------------------------------------------
// | Attributes |
// +------------+
/** The current x position of the center of the ball. */
protected int xpos;
/** The current y position of the center of the ball. */
protected int ypos;
/** The current radius of the ball. */
protected int radius;
/** The current horizontal velocity of the ball. */
protected int horizVelocity;
/** The current vertical velocity of the ball. */
protected int vertVelocity;
/** The color of the ball. */
protected Color color;
/** The thread that corresponds to the curent applet. */
protected Thread thread;
// +-------------------------+---------------------------------
// | Standard Applet Methods |
// +-------------------------+
/**
* Initialize the applet. Set up the color, position, velocity,
* and such.
*/
public void init() {
// To make things interesting, we might initialize some of the values
// randomly. This means that we'll need a random number generator.
Random generator = new Random();
// Pick a "reasonable" radius
radius = 10;
// Start at the upper left-hand-corner
xpos = 10;
ypos = 10;
// Start at a moderate velocity
horizVelocity = 5;
vertVelocity = 5;
// Pick a nice color
color = Color.blue;
} // init()
/**
* Paint the ball on the screen.
*/
public void paint(Graphics g) {
g.setColor(color);
g.fillOval(xpos-radius, ypos-radius, 2*radius, 2*radius);
} // paint(Graphics)
/**
* Run the thread.
*/
public void run() {
// It appears that we keep going forever. However, external
// things (that is, the web browser) control when we stop.
while (true) {
try {
thread.sleep(20);
}
catch (InterruptedException ie) {
// Do nothing
}
// Update the position of the ball
updatePosition();
// And repaint
repaint();
} // while
} // run()
/**
* Start the thread.
*/
public void start() {
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
} // start()
/**
* Stop the thread.
*/
public void stop() {
thread.stop();
} // stop()
// +--------------------+--------------------------------------
// | Additional Methods |
// +--------------------+
/**
* Update the position of the ball.
*/
public void updatePosition() {
// We'll need the dimensions of the current window to determine
// when we reach a wall.
Dimension dim = this.getSize();
// Update the x and y position
xpos = xpos + horizVelocity;
ypos = ypos + vertVelocity;
// If we've gone too far in one direction, reverse the ball
if (xpos+radius > dim.width) {
xpos = dim.width - (xpos + radius - dim.width);
horizVelocity = -horizVelocity;
}
else if (xpos-radius < 0) {
xpos = -(xpos - radius);
horizVelocity = -horizVelocity;
}
if (ypos+radius > dim.height) {
ypos = dim.height - (ypos + radius - dim.height);
vertVelocity = -vertVelocity;
}
else if (ypos-radius < 0) {
ypos = -(ypos - radius);
vertVelocity = -vertVelocity;
}
} // updatePosition()
} // BallApplet
Here's another way one might use animation. We'll gradually write
a short welcome message on the screen. We use a counter
(amt) to keep track of how much of the message
to write.
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
/**
* A simple applet that prints a string, piece by piece..
*
* @author Samuel A. Rebelsky
* @version 1.0 of November 1998
*/
public class AnimatedWelcome
extends Applet
implements Runnable
{
/** The message to print. */
String message;
/** The color of the message. */
Color color;
/** The portion of the message to print. */
int amt = 1;
/** The thread for the applet. */
Thread welcomeThread;
/**
* Set up the message to print.
*/
public void init() {
message = getParameter("Message");
if (message == null) { message = "A Sample Message"; }
color = Color.blue;
} // init()
/*
* Stop the thread.
*/
public void stop() {
welcomeThread = null;
}
/**
* Start up.
*/
public void start() {
if ((amt < message.length()) && (welcomeThread == null)) {
welcomeThread = new Thread(this);
}
welcomeThread.start();
} // start
/*
* Run the program (or the thread).
*/
public void run() {
//Remember which thread we are.
Thread currentThread = Thread.currentThread();
//This is the display loop.
while ( (currentThread == welcomeThread) &&
(amt <= message.length()) ) {
//Display it.
repaint();
// Pause
try {
Thread.sleep(200); // 1/5 of a second
} catch (InterruptedException e) { break; }
} // while
} // run
/*
* Paint part of the message.
*/
public void paint(Graphics g) {
g.setColor(color);
g.setFont(new Font("Times", Font.BOLD, 16));
g.drawString(message.substring(0,amt), 10, 16);
if (amt < message.length())
++amt;
else {
// Change the color.
if (color.equals(Color.blue))
color = Color.red;
else
color = Color.blue;
// Reset the amount
amt = 0;
}
} // paint(Graphics)
} // class AnimatedWelcome
You may notice some flickering. How to stop flickering is left as an issue for another day.
Name: ________________
ID:_______________
Possible ideas:
How do you add gravity? Change the vertical velocity each time.
[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Examples] [Book] [Tutorial] [API]
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
This page may be found at http://www.math.grin.edu/~rebelsky/Courses/CS152/99S/Labs/animation.html
Source text last modified Fri Mar 19 10:07:30 1999.
This page generated on Fri Mar 19 10:13:47 1999 by SiteWeaver. Validate this page's HTML.
Contact our webmaster at rebelsky@math.grin.edu