⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch7.htm

📁 21天学会用JAVA开发网络游戏,这是一本英文书
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<HTML>

<HEAD>
   <TITLE>Chapter 7 -- Sim Tarantulas Creepy Crawly Sprites</TITLE>
   <META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 7</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Sim Tarantulas Creepy Crawly Sprites</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>

<UL>
<LI><A HREF="#ExtendingtheSpriteClass" >Extending the Sprite Class</A>
<UL>
<LI><A HREF="#DesigningaDirectionalSprite" >Designing a Directional Sprite</A>
<LI><A HREF="#TheDirectionalSpriteClass" >The DirectionalSprite Class</A>
</UL>
<LI><A HREF="#DesigningSimTarantula" >Designing Sim Tarantula</A>
<LI><A HREF="#SampleAppletSimTarantula" >Sample Applet: Sim Tarantula</A>
<UL>
<LI><A HREF="#TheSpriteClasses" >The Sprite Classes</A>
<LI><A HREF="#TheSimTarantulaClass" >The SimTarantula Class</A>
</UL>
<LI><A HREF="#Summary" >Summary</A>
<LI><A HREF="#QA" >Q&amp;A</A>
<LI><A HREF="#Workshop" >Workshop</A>
<UL>
<LI><A HREF="#Quiz" >Quiz</A>
<LI><A HREF="#Exercises" >Exercises</A>
</UL>
</UL>
<HR>
<P>
On <A HREF="ch6.htm" >Day 6</A>, you developed a suite of very
powerful and easy to use sprite classes. You saw them in action
in an applet that demonstrated their basic functionality. Today,
you expand on that knowledge by extending the sprite classes to
fit a more applied sample applet. More specifically, you derive
new sprite classes to help build a tarantula simulation applet.
<P>
Today's lesson is completely devoted to the development of this
applet, which makes great use of the sprite classes. You learn
all about sprite actions and how to use them to add new sprites
and kill existing sprites. You also learn how to incorporate multiple
frame animation images into derived sprites to give them a sense
of direction.
<P>
More than anything, you learn how to apply the sprite classes
to problems requiring unique solutions. This is the one skill
that is essential in creating Java games. So let's get busy!
<H2><A NAME="ExtendingtheSpriteClass"><B><FONT SIZE=5 COLOR=#FF0000>Extending
the </FONT></B><TT><B><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">Sprite</FONT></B></TT><B><FONT SIZE=5 COLOR=#FF0000>
Class</FONT></B></A></H2>
<P>
The concept of extending the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class to fit a particular situation is crucial in Java game development.
It is also important from an object-oriented design point of view
and will ultimately save you a great deal of time and code testing.
When you derive sprites from the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class, you can reuse all the code in <TT><FONT FACE="Courier">Sprite</FONT></TT>,
while adding additional code to carry out more specific chores.
<P>
However, not all sprites derived from <TT><FONT FACE="Courier">Sprite</FONT></TT>
have to be specific to a particular game. You might need some
functionality that is not included in <TT><FONT FACE="Courier">Sprite</FONT></TT>
and that might be needed by various other sprite objects in a
more general sense. In this case, you are better off to create
an intermediate class that is derived from <TT><FONT FACE="Courier">Sprite</FONT></TT>.
You can then derive game-specific classes from this class.
<P>
An example of this idea is a directional sprite. The <TT><FONT FACE="Courier">Sprite</FONT></TT>
class, although feature packed, includes no support for a sprite
having direction. Some examples of sprites that would require
direction are tanks and monsters-basically, anything that has
a distinguishable front, back, and sides. If you were to use the
<TT><FONT FACE="Courier">Sprite</FONT></TT> class to create a
monster, you would be able to move the monster and even give it
a frame animation, but you would have no way to show it facing
the direction it is moving in. Clearly, this would look pretty
strange.
<P>
The solution is to derive a directional sprite that adds the functionality
necessary to provide a sense of direction. Then you can derive
the monster sprite from the directional sprite and instantly give
it direction. From then on, any other game-specific directional
sprites can simply be derived from the generic directional sprite
class and gain all the same benefits. This is object-oriented
programming at its best!
<H3><A NAME="DesigningaDirectionalSprite"><B>Designing a Directional
Sprite</B></A></H3>
<P>
Because you'll need it for the Sim Tarantula applet later in today's
lesson, go ahead and design a directional sprite class. The directional
sprite class needs to encapsulate all the behavior necessary to
provide a direction of movement.
<P>
The first step in designing the directional sprite is to determine
how to model the different directions. Because you won't attempt
to render the sprite image at different directions on the fly,
it's important to realize that each direction requires its own
image. In the case of a frame-animated directional sprite, each
direction requires an array of images. You have to decide on a
limited set of directions that the sprite can have, because it
would be very costly in terms of resources to provide images for
the sprite at many different directions. Figure 7.1 shows a discrete
set of directions that apply well to directional sprites.
<P>
<A HREF="f7-1.gif" ><B>Figure 7.1 : </B><I>Discrete directions for a directional sprite.</I></A>
<P>
Of course, providing more directions would yield smoother rotating
effects for the sprite. However, it would also up the ante a great
deal in terms of resources. Remember that each direction brings
with it the overhead of an image or array of images. And all those
images must be transferred over a potentially low-bandwidth Internet
connection. In Java programming, you must always think about the
fact that the applet and resources have to be transmitted over
the Internet to the user's computer. At times like this, you need
to look at the design from the game player's perspective: Are
smoother directional sprites worth waiting 10 minutes for the
images to transfer? I seriously doubt it!
<P>
Now that you've settled on a workable set of directions for the
directional sprite, you need to consider what aspects of the original
<TT><FONT FACE="Courier">Sprite</FONT></TT> class are affected
by the addition of directions. Probably the most obvious change
has to do with the sprite image. Now, instead of a single image,
you must provide an image for each possible direction. In the
case of a frame-animated directional sprite, you must provide
an array of images for each direction.
<P>
The other major change brought on by the directional sprite relates
to velocity. The velocity of a directional sprite is tightly linked
to the direction because the sprite must be facing the direction
it is traveling. This means that you need to alter the velocity
whenever you change the direction, and vice versa. You'll see
that this is not a problem, because you can just override the
method that deals with setting the velocity.
<H3><A NAME="TheDirectionalSpriteClass"><B>The </B><TT><B><FONT SIZE=4 FACE="Courier">DirectionalSprite</FONT></B></TT><B><FONT SIZE=4>
Class</FONT></B></A></H3>
<P>
With all the design issues laid out, it's time to move on to the
Java implementation of the <TT><FONT FACE="Courier">DirectionalSprite</FONT></TT>
class. The following are the member variables defined in <TT><FONT FACE="Courier">DirectionalSprite</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">protected static final int[][] velDirs
= {<BR>
&nbsp;&nbsp;{0, -1}, {1, -1}, {1, 0}, {1, 1},<BR>
&nbsp;&nbsp;{0, 1}, {-1, 1}, {-1, 0}, {-1, -1} };<BR>
protected Image[][] image;<BR>
protected int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;direction;</FONT></TT>
</BLOCKQUOTE>
<P>
The first member variable, <TT><FONT FACE="Courier">velDirs</FONT></TT>,
is a two-dimensional array of integers. This array holds values
that are used to calculate the sprite's velocity based on a given
direction. When the direction of the sprite is changed, the velocity
is multiplied by an X and Y component from the <TT><FONT FACE="Courier">velDirs</FONT></TT>
array. Figure 7.2 shows how the X and Y multiplier values in <TT><FONT FACE="Courier">velDirs</FONT></TT>
correspond to the different directions of the sprite.
<P>
<A HREF="f7-2.gif" ><B>Figure 7.2 : </B><I>Velocity multipliers for the different sprite directions.</I></A>
<P>
The other two member variables in <TT><FONT FACE="Courier">DirectionalSprite</FONT></TT>,
<TT><FONT FACE="Courier">image</FONT></TT> and <TT><FONT FACE="Courier">direction</FONT></TT>,
are storage members for the directional images and the current
direction. Notice that <TT><FONT FACE="Courier">image</FONT></TT>
is a two-dimensional array of <TT><FONT FACE="Courier">Image</FONT></TT>
objects, which reflects the frame animation support in <TT><FONT FACE="Courier">DirectionalSprite</FONT></TT>.
<P>
<TT><FONT FACE="Courier">DirectionalSprite</FONT></TT> has two
constructors, similar to the original <TT><FONT FACE="Courier">Sprite</FONT></TT>
class:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public DirectionalSprite(Component comp,
Image[] img, Point pos,<BR>
&nbsp;&nbsp;Point vel, int z, int ba, int d) {<BR>
&nbsp;&nbsp;super(comp, img[d], pos, vel, z, ba);<BR>
&nbsp;&nbsp;image[0] = img;<BR>
&nbsp;&nbsp;setDirection(d);<BR>
}<BR>
<BR>
public DirectionalSprite(Component comp, Image[][] img, int f,
<BR>
&nbsp;&nbsp;int fi, int fd, Point pos, Point vel, int z, int ba,
int d) {<BR>
&nbsp;&nbsp;super(comp, img[d], f, fi, fd, pos, vel, z, ba);<BR>
&nbsp;&nbsp;image = img;<BR>
&nbsp;&nbsp;setDirection(d);<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The first constructor creates a directional sprite without frame
animation, and the second constructor supports frame animation,
as is evident by the extra parameters. Notice that the <TT><FONT FACE="Courier">setDirection</FONT></TT>
method is called to initialize the direction of the sprite, rather
than a simple assignment being made to the <TT><FONT FACE="Courier">direction</FONT></TT>
member variable. This is because the direction impacts both the
velocity and image of the sprite. You see how this works later
in today's lesson when you get into the <TT><FONT FACE="Courier">setDirection</FONT></TT>
method.
<P>
The <TT><FONT FACE="Courier">getDirection</FONT></TT> method is
a simple access method that returns the current direction:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public int getDirection() {<BR>
&nbsp;&nbsp;return direction;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">setDirection</FONT></TT> method involves
a little more work, as the following code shows:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void setDirection(int dir) {<BR>
&nbsp;&nbsp;// Set the direction<BR>
&nbsp;&nbsp;if (dir &lt; 0)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;dir = 7;<BR>
&nbsp;&nbsp;else if (dir &gt; 7)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;dir = 0;<BR>
&nbsp;&nbsp;direction = dir;<BR>
<BR>
&nbsp;&nbsp;// Change the velocity<BR>
&nbsp;&nbsp;velocity.x *= velDirs[dir][0];<BR>
&nbsp;&nbsp;velocity.y *= velDirs[dir][1];<BR>
<BR>
&nbsp;&nbsp;// Set the image<BR>
&nbsp;&nbsp;setImage(image[dir]);<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">setDirection</FONT></TT> first ensures
that the direction is within the directional bounds (<TT><FONT FACE="Courier">0</FONT></TT>
to <TT><FONT FACE="Courier">7</FONT></TT>). Notice that <TT><FONT FACE="Courier">setDirection</FONT></TT>
takes care to wrap the direction around if it goes beyond a boundary;
this gives the sprite the capability to rotate freely. The velocity
is then modified using the <TT><FONT FACE="Courier">velDirs</FONT></TT>
directional velocity multipliers. Finally, the new direction image
is set with a call to <TT><FONT FACE="Courier">setImage</FONT></TT>.
<P>
The <TT><FONT FACE="Courier">setVelocity</FONT></TT> method is
overridden in <TT><FONT FACE="Courier">DirectionalSprite</FONT></TT>
because changing the velocity should cause a change in the direction.
Check out the following code:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void setVelocity(Point vel) {
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;velocity = vel;<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;// Change the direction<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (vel.x == 0 &amp;&amp; vel.y == 0)
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (vel.x == 0)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;direction = (vel.y + 1) *
2;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else if (vel.x == 1)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;direction = vel.y + 1;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else if (vel.x == -1)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;direction = -vel.y + 6;<BR>
&nbsp;&nbsp;}</FONT></TT>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -