1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
BallApplet.java
import java.awt.*;
import java.applet.*;
public class BallApplet extends Applet implements Runnable {
public static final int ANIMATION_SPEED = 10;
public static final String IMAGE_NAME_PARAM = "imageName";
private int mBallX, mBallY, mBallSpeedX, mBallSpeedY;
private Image mBallImage;
private Image mImageBuffer;
private Graphics mImageBufferGraphics;
private Thread mAnimationThread;
private boolean mAnimationThreadInterrupted = false;
/**
* Applet's init() method. Makes some initializations
* and loads the ball image. This method is called before
* creating the animation thread so no synchronization
* is needed.
*/
public void init() {
// Load the ball image from the server
String imageName = getParameter(IMAGE_NAME_PARAM);
if (imageName == null) {
System.err.println("Applet parameter " +
IMAGE_NAME_PARAM + " is missing.");
System.exit(-1);
}
mBallImage = getImage(getCodeBase(), imageName);
// Wait for the image to load completely
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(mBallImage,0);
try {
tracker.waitForAll();
} catch (InterruptedException ie) { }
if (tracker.statusAll(true) != MediaTracker.COMPLETE) {
System.err.println("Can not load " + imageName);
System.exit(-1);
}
// Initialize the ball image coordinates and speed
mBallX = 1;
mBallY = 1;
mBallSpeedX = 1;
mBallSpeedY = 1;
// Create an image buffer for the animation
mImageBuffer = createImage(
getSize().width, getSize().height);
mImageBufferGraphics = mImageBuffer.getGraphics();
}
/**
* Applet's paint() method. Draws the ball on its current
* position. This method can be called in the same time
* from both the applet's thread and from the animation
* thread so it should be thread safe (synchronized).
*/
public void paint(Graphics aGraphics) {
synchronized (this) {
if (mAnimationThread != null) {
// Paint in the buffer
mImageBufferGraphics.fillRect(
0, 0, getSize().width, getSize().height);
mImageBufferGraphics.drawImage(
mBallImage, mBallX, mBallY, this);
// Copy the buffer contents to the screen
aGraphics.drawImage(mImageBuffer, 0, 0, this);
}
}
}
/**
* Applet's start() method. Creates the animation thread
* and starts it if it is not already running. This method
* can be called only from the applet's thread so it does
* not require synchronization.
*/
public void start() {
if (mAnimationThread == null) {
mAnimationThreadInterrupted = false;
mAnimationThread = new Thread(this);
mAnimationThread.start();
}
}
/**
* Applet's stop() method. Asks the animation thread to
* stop its execution and waits until it is really stopped.
* This method is called only from the applet's thread so
* it does not need synchronization except when accessing
* the variable mAnimationThreadInterrupted that is common
* for applet's thread and animation thread.
*/
public void stop() {
synchronized (this) {
mAnimationThreadInterrupted = true;
}
try {
mAnimationThread.join();
} catch (InterruptedException ie) { }
mAnimationThread = null;
}
/**
* Animation thread's run() method. Continuously changes
* the ball position and redraws it and thus an animation
* effect is achived. This method runs in a separate thread
* that is especially created for the animation. A
* synchronization is needed only when accessing variables
* that are common for the applet's thread and animation
* thread.
*/
public void run() {
// Calculate the animation area size
int maxX, maxY;
synchronized (this) {
maxX = this.getSize().width -
mBallImage.getWidth(this);
maxY = this.getSize().height -
mBallImage.getHeight(this);
}
// Perform continuously animation
while (true) {
synchronized (this) {
// Check if the thread should stop
if (mAnimationThreadInterrupted)
break;
// Calculate the new ball coordinates
if ((mBallX >= maxX) || (mBallX <= 0))
mBallSpeedX = -mBallSpeedX;
mBallX = mBallX + mBallSpeedX;
if ((mBallY >= maxY) || (mBallY <= 0))
mBallSpeedY = -mBallSpeedY;
mBallY = mBallY + mBallSpeedY;
}
// Redraw the applet contents
paint(getGraphics());
// Wait some time to slow down the animation speed
try {
Thread.sleep(ANIMATION_SPEED);
} catch (Exception ex) {}
}
}
} |