📄 ch7.htm
字号:
// Add spider?<BR>
if (action.get(Tarantula.SA_ADDTARANTULA))<BR>
return new Tarantula(component, new Point(position.x,
position.y));<BR>
return null;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">addSprite</FONT></TT> checks for the
<TT><FONT FACE="Courier">SA_ADDTARANTULA</FONT></TT> action flag
and creates the new tarantula if it is set. The newly created
<TT><FONT FACE="Courier">Tarantula</FONT></TT> object is then
returned so that it can be added to the sprite list.
<P>
The next extended sprite class used in Sim Tarantula is the <TT><FONT FACE="Courier">Tarantula</FONT></TT>
class, which you might have suspected models a tarantula. The
following are the member variables defined in the <TT><FONT FACE="Courier">Tarantula</FONT></TT>
class:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public static final int SA_ADDTARANTULA
= 3,<BR>
SA_ADDSPIDERLING
= 4,<BR>
SA_ADDSPIDERCIDE
= 5;<BR>
public static Image[][] image;<BR>
protected static Random rand = new Random(<BR>
System.currentTimeMillis());</FONT></TT>
</BLOCKQUOTE>
<P>
Probably the most important aspect of the <TT><FONT FACE="Courier">Tarantula</FONT></TT>
class is the addition of the custom sprite actions. These three
actions define a mechanism to add <TT><FONT FACE="Courier">Tarantula</FONT></TT>,
<TT><FONT FACE="Courier">Spiderling</FONT></TT>, and <TT><FONT FACE="Courier">Spidercide</FONT></TT>
objects. Notice that the actions are assigned increasing integer
values beginning with <TT><FONT FACE="Courier">3</FONT></TT>.
This is extremely important because the standard sprite actions
defined in the <TT><FONT FACE="Courier">Sprite</FONT></TT> class
are already assigned the values <TT><FONT FACE="Courier">0</FONT></TT>,
<TT><FONT FACE="Courier">1</FONT></TT>, and <TT><FONT FACE="Courier">2</FONT></TT>.
If you recall, the sprite actions are actually flags used in a
<TT><FONT FACE="Courier">BitSet</FONT></TT> object to pass actions
back and forth between individual sprites and the sprite list.
<P>
The <TT><FONT FACE="Courier">Image</FONT></TT> member variable,
<TT><FONT FACE="Courier">image</FONT></TT>, is simply used to
hold the array of images for the sprite. The <TT><FONT FACE="Courier">Tarantula</FONT></TT>
class also contains a <TT><FONT FACE="Courier">Random</FONT></TT>
object member variable, <TT><FONT FACE="Courier">rand</FONT></TT>.
This member variable is defined as static and is used to provide
random numbers for all <TT><FONT FACE="Courier">Tarantula</FONT></TT>
objects. It is seeded with the current system time, which is a
useful way to help guarantee randomness.
<P>
The constructor for <TT><FONT FACE="Courier">Tarantula</FONT></TT>
is very simple and alleviates having to pass a bunch of specific
parameters:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public Tarantula(Component comp, Point
pos) {<BR>
super(comp, image, 0, 1, 2, pos, new Point(1, 1),
50,<BR>
Sprite.BA_WRAP, 0);<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The tarantula is given a bounds action of <TT><FONT FACE="Courier">BA_WRAP</FONT></TT>,
which means that it can roam off one side of the applet window
and back onto the other side.
<P>
Similar to the one in <TT><FONT FACE="Courier">Spiderling</FONT></TT>,
the <TT><FONT FACE="Courier">initResources</FONT></TT> method
for <TT><FONT FACE="Courier">Tarantula</FONT></TT> loads all the
images used by the class:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public static void initResources(Applet
app, MediaTracker tracker,<BR>
int id) {<BR>
image = new Image[8][2];<BR>
for (int i = 0; i < 8; i++) {<BR>
for (int j = 0; j < 2; j++) {<BR>
image[i][j] = app.getImage(app.getCodeBase(),
<BR>
"Res/Tarant"
+ i + j + ".gif");<BR>
tracker.addImage(image[i][j],
id);<BR>
}<BR>
}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">update</FONT></TT> method is where
most of the action takes place in <TT><FONT FACE="Courier">Tarantula</FONT></TT>.
Listing 7.1 shows the source code for the <TT><FONT FACE="Courier">update</FONT></TT>
method.
<HR>
<BLOCKQUOTE>
<B>Listing 7.1. The </B><TT><B><FONT FACE="Courier">Tarantula</FONT></B></TT><B>
class's </B><TT><B><FONT FACE="Courier">update</FONT></B></TT><B>
method.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public BitSet update() {<BR>
// Randomly change direction<BR>
if ((rand.nextInt() % 10) == 0) {<BR>
velocity.x = velocity.y =
1;<BR>
setDirection(direction + rand.nextInt()
% 2);<BR>
}<BR>
<BR>
// Call parent's update()<BR>
BitSet action = super.update();<BR>
<BR>
// Give birth?<BR>
if (rand.nextInt() % 250 == 0) {<BR>
action.set(Sprite.SA_ADDSPRITE);
<BR>
action.set(Tarantula.SA_ADDSPIDERLING);
<BR>
}<BR>
<BR>
// Die?<BR>
if (rand.nextInt() % 250 == 0) {<BR>
action.set(Sprite.SA_KILL);
<BR>
action.set(Sprite.SA_ADDSPRITE);
<BR>
action.set(Tarantula.SA_ADDSPIDERCIDE);
<BR>
}<BR>
<BR>
return action;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">update</FONT></TT> method first handles
giving the tarantula its ability to roam by randomly altering
the direction. The superclass <TT><FONT FACE="Courier">update</FONT></TT>
method is then called so that all the default handling can take
place. The <TT><FONT FACE="Courier">update</FONT></TT> method
then randomly decides whether a new <TT><FONT FACE="Courier">Spiderling</FONT></TT>
object should be created. If so, the <TT><FONT FACE="Courier">SA_ADDSPRITE</FONT></TT>
and <TT><FONT FACE="Courier">SA_ADDSPIDERLING</FONT></TT> flags
are set. Similarly, <TT><FONT FACE="Courier">update</FONT></TT>
randomly decides whether a <TT><FONT FACE="Courier">Spidercide</FONT></TT>
object should be created. If so, the <TT><FONT FACE="Courier">SA_KILL</FONT></TT>,
<TT><FONT FACE="Courier">SA_ADDSPRITE</FONT></TT>, and <TT><FONT FACE="Courier">SA_ADDSPIDERCIDE</FONT></TT>
flags are set. The <TT><FONT FACE="Courier">SA_KILL</FONT></TT>
flag takes care of killing the <TT><FONT FACE="Courier">Tarantula</FONT></TT>
object itself, while the other two cause the new <TT><FONT FACE="Courier">Spidercide</FONT></TT>
object to be created.
<P>
The last method in <TT><FONT FACE="Courier">Tarantula</FONT></TT>
is <TT><FONT FACE="Courier">addSprite</FONT></TT>, which handles
creating <TT><FONT FACE="Courier">Spiderling</FONT></TT> and <TT><FONT FACE="Courier">Spidercide</FONT></TT>
objects that are to be added to the sprite list:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">protected Sprite addSprite(BitSet action)
{<BR>
// Add spiderling?<BR>
if (action.get(Tarantula.SA_ADDSPIDERLING))<BR>
return new Spiderling(component, new Point(position.x,
<BR>
position.y));<BR>
<BR>
// Add spidercide?<BR>
else if (action.get(Tarantula.SA_ADDSPIDERCIDE))<BR>
return new Spidercide(component, new Point(position.x,
<BR>
position.y));<BR>
<BR>
return null;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">addSprite</FONT></TT> method checks
the sprite action flags and creates a new sprite, if necessary.
<TT><FONT FACE="Courier">addSprite</FONT></TT> then makes sure
to return the newly created sprite so that it can be added to
the sprite list.
<P>
Last but not least is the <TT><FONT FACE="Courier">Spidercide</FONT></TT>
class, which models a dying tarantula with a simple frame animation.
The <TT><FONT FACE="Courier">Spidercide</FONT></TT> class is very
similar to <TT><FONT FACE="Courier">Spiderling</FONT></TT>, because
they both act effectively as temporary animations. Listing 7.2
contains the source code for the <TT><FONT FACE="Courier">Spidercide</FONT></TT>
class.
<HR>
<BLOCKQUOTE>
<B>Listing 7.2. The </B><TT><B><FONT FACE="Courier">Spidercide</FONT></B></TT><B>
class.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public class Spidercide extends Sprite
{<BR>
protected static Image[] image = new Image[4];<BR>
<BR>
public Spidercide(Component comp, Point pos) {<BR>
super(comp, image, 0, 1, 20, pos, new
Point(0, 0), 30,<BR>
Sprite.BA_DIE);<BR>
}<BR>
<BR>
public static void initResources(Applet app, MediaTracker
tracker,<BR>
int id) {<BR>
for (int i = 0; i < 4; i++) {<BR>
image[i] = app.getImage(app.getCodeBase(),
"Res/Spcide" +<BR>
i + ".gif");
<BR>
tracker.addImage(image[i],
id);<BR>
}<BR>
}<BR>
<BR>
public BitSet update() {<BR>
BitSet action = new BitSet();<BR>
<BR>
// Die?<BR>
if (frame >= 3) {<BR>
action.set(Sprite.SA_KILL);
<BR>
return action;<BR>
}<BR>
<BR>
// Increment the frame<BR>
incFrame();<BR>
<BR>
return action;<BR>
}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
You can undoubtedly see a lot of similarities between <TT><FONT FACE="Courier">Spidercide</FONT></TT>
and <TT><FONT FACE="Courier">Spiderling</FONT></TT>. As a matter
of fact, the only significant difference between the two is that
the <TT><FONT FACE="Courier">Spidercide</FONT></TT> class doesn't
add new sprites. Of course, it also provides its own unique frame
images. Otherwise, you've seen all this code before in the <TT><FONT FACE="Courier">Spiderling</FONT></TT>
class, so I won't go over it again.
<P>
There is actually one other sprite-related class in Sim Tarantula
that you need to learn about before moving on to the applet class.
I'm referring to the <TT><FONT FACE="Courier">TarantulaVector</FONT></TT>
class, which is derived from <TT><FONT FACE="Courier">SpriteVector</FONT></TT>
and provides features specific to the Sim Tarantula sprite classes.
Listing 7.3 contains the source code for <TT><FONT FACE="Courier">TarantulaVector</FONT></TT>.
<HR>
<BLOCKQUOTE>
<B>Listing 7.3. The </B><TT><B><FONT FACE="Courier">TarantulaVector</FONT></B></TT><B>
class.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public class TarantulaVector extends
SpriteVector {<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -