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
|
package gjt.animation;
import java.awt.*;
import java.util.Enumeration;
import java.util.Vector;
import gjt.Util;
/**
* A surface upon which Sprites are animated. Playfields are
* responsible for animating the sprites.<p>
*
* Each Playfield comes complete with two collision detectors:
* an edge collision detector and a sprite collision detector.
*
* Playfield is an abstract class: extensions must implement
* the following methods:
* <dl>
* <dd> void paintBackground(Graphics)
* <dd> void void spriteCollision(Sprite sprite, Sprite other)
* <dd> void void edgeCollision (Sprite sprite, Sprite other)
* </dl>
*
* @version 1.0, Apr 1 1996
* @author David Geary
* @see CollisionArena
* @see Sprite
* @see SpriteCollisionDetector
* @see EdgeCollisionDetector
* @see gjt.test.SimpleAnimationTest
* @see gjt.test.BumpAnimationTest
* @see gjt.test.TwoDrinkersAnimationTest
*/
public abstract class Playfield extends Canvas
implements Runnable,
CollisionArena {
protected Vector sprites = new Vector();
private boolean running = false;
private Insets insets = new Insets(0,0,0,0);
private Thread animationThread;
private Image bgoffscreen,
workplaceBuffer;
private Dimension offscreenSize;
private EdgeCollisionDetector edgeCollisionDetector;
private SpriteCollisionDetector spriteCollisionDetector;
abstract public void paintBackground(Graphics g);
public Playfield() {
edgeCollisionDetector =
new EdgeCollisionDetector(this);
spriteCollisionDetector =
new SpriteCollisionDetector(this);
}
public void stop () { running = false; }
public boolean running () { return running; }
public Dimension getSize () { return size(); }
public Insets getInsets () { return insets; }
public Vector getSprites() { return sprites; }
public void addSprite(Sprite sprite) {
sprites.addElement(sprite);
}
public void setInsets(Insets insets) {
this.insets = insets;
}
public void start() {
animationThread = new Thread(this);
running = true;
animationThread.start();
}
public void paint(Graphics g) {
if(needNewOffscreenBuffer()) {
workplaceBuffer = createOffscreenImage(size());
bgoffscreen = createOffscreenImage(size());
paintBackground(bgoffscreen.getGraphics());
}
g.drawImage(bgoffscreen, 0, 0, this);
paintSprites();
}
public void reshape(int x, int y, int w, int h) {
super.reshape(x,y,w,h);
repaint();
}
public void run() {
while(running == true) {
edgeCollisionDetector.detectCollisions ();
spriteCollisionDetector.detectCollisions();
animateSprites();
Thread.currentThread().yield();
}
animationThread = null;
}
private boolean needNewOffscreenBuffer() {
return (workplaceBuffer == null ||
bgoffscreen == null ||
size().width != offscreenSize.width ||
size().height != offscreenSize.height);
}
private Image createOffscreenImage(Dimension size) {
Image image = createImage(size.width, size.height);
Util.waitForImage(this, image);
offscreenSize = size;
return image;
}
protected void animateSprites() {
Sprite nextSprite;
Enumeration e = sprites.elements();
while(e.hasMoreElements()) {
nextSprite = (Sprite)e.nextElement();
nextSprite.animate();
}
}
protected void paintSprites() {
Sprite nextSprite;
Enumeration e = sprites.elements();
while(e.hasMoreElements()) {
nextSprite = (Sprite)e.nextElement();
paintSprite(nextSprite);
}
}
protected void paintSprite(Sprite sprite) {
Graphics g = getGraphics();
Graphics wpg = workplaceBuffer.getGraphics();
Rectangle clip = sprite.clipRect();
wpg.clipRect(clip.x, clip.y, clip.width, clip.height);
wpg.drawImage(bgoffscreen, 0, 0, this);
sprite.paint(wpg);
g.clipRect (clip.x, clip.y, clip.width, clip.height);
g.drawImage(workplaceBuffer, 0, 0, this);
g.dispose();
wpg.dispose();
}
}
|