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

📄 ch6.htm

📁 21天学会用java开发网络游戏
💻 HTM
📖 第 1 页 / 共 5 页
字号:
sort of like another dimension-like a Z axis. You can think of
sprites moving around on the screen in the XY axis. Similarly,
the Z axis can be thought of as another axis projected into the
screen that determines how the sprites overlap each other. To
put it another way, Z-order determines a sprite's depth within
the screen. By making use of a Z axis, you might think that Z-ordered
sprites are 3D. The truth is that Z-ordered sprites can't be considered
3D because the Z axis is a hypothetical axis that is only used
to determine how sprite objects hide each other.
<P>
Just to make sure that you get a clear picture of how Z-order
works, let's go back for a moment to the good old days of traditional
animation. Traditional animators, such as those at Disney, used
celluloid sheets to draw animated objects. They drew on celluloid
sheets because the sheets could be overlaid on a background image
and moved independently. This was known as <I>cel animation</I>
and should sound vaguely familiar. (Cel animation is an early
version of sprite animation.) Each cel sheet corresponds to a
unique Z-order value, determined by where in the pile of sheets
the sheet is located. If a sprite near the top of the pile happens
to be in the same location on the cel sheet as any lower sprites,
it conceals them. The location of each sprite in the stack of
cel sheets is its Z-order, which determines its visibility precedence.
The same thing applies to sprites in cast-based animations, except
that the Z-order is determined by the order in which the sprites
are drawn, rather than the cel sheet location. This concept of
a pile of cel sheets representing all the sprites in a sprite
system will be useful later today when you develop the sprite
classes.
<H4><B>Collision Detection</B></H4>
<P>
No discussion of animation as it applies to games would be complete
without covering collision detection. <I>Collision detection</I>
is simply the method of determining whether sprites have collided
with each other. Although collision detection doesn't directly
play a role in creating the illusion of movement, it is tightly
linked to sprite animation and extremely crucial in games.
<P>
<I>Collision detection</I> is the process of determining whether
sprites have collided with each other.
<P>
Collision detection is used to determine when sprites physically
interact with each other. In an Asteroids game, for example, if
the ship sprite collides with an asteroid sprite, the ship is
destroyed. Collision detection is the mechanism employed to find
out whether the ship collided with the asteroid. This might not
sound like a big deal; just compare their positions and see whether
they overlap, right? Correct, but consider how many comparisons
must take place when lots of sprites are moving around; each sprite
must be compared to every other sprite in the system. It's not
hard to see how the overhead of effective collision detection
can become difficult to manage.
<P>
Not surprisingly, there are many approaches to handling collision
detection. The most simple approach is to compare the bounding
rectangles of each sprite with the bounding rectangles of all
the other sprites. This method is very efficient, but if you have
objects that are not rectangular, a certain degree of error occurs
when the objects brush by each other. This is because the corners
might overlap and indicate a collision when really only the transparent
areas are overlapping. The more irregular the shape of the sprites,
the more error typically occurs. Figure 6.1 shows how simple rectangle
collision works.
<P>
<A HREF="f6-1.gif" ><B>Figure 6.1 : </B><I>Collision detection using simple rectangle collision.</I></A>
<P>
In Figure 6.1, the areas determining the collision detection are
shaded. You can see how simple rectangle collision detection isn't
very accurate, unless you're dealing with sprites that are rectangular
in shape. An improvement on this technique is to shrink the collision
rectangles a little, which reduces the corner error. This method
improves things a little, but it has the potential of causing
error in the reverse direction by allowing sprites to overlap
in some cases without signaling a collision. Figure 6.2 shows
how shrinking the collision rectangles can improve the error on
simple rectangle collision detection. Shrunken rectangle collision
is just as efficient as simple rectangle collision because all
you are doing is comparing rectangles for intersection.
<P>
<A HREF="f6-2.gif" ><B>Figure 6.2 : </B><I>Collision detection using shrunken rectangle collision.</I></A>
<P>
The most accurate collision detection technique is to detect collision
based on the sprite image data, which involves actually checking
to see whether transparent parts of the sprite or the sprite images
themselves are overlapping. In this case, you get a collision
only if the actual sprite images are overlapping. This is the
ideal technique for detecting collisions because it is exact and
allows objects of any shape to move by each other without error.
Figure 6.3 shows collision detection using the sprite image data.
<P>
<A HREF="f6-3.gif" ><B>Figure 6.3 : </B><I>Collision detection using sprite image data.</I></A>
<P>
Unfortunately, the technique shown in Figure 6.3 requires far
more overhead than rectangle collision detection and is often
a major bottleneck in performance. Furthermore, implementing image
data for collision detection can get very messy. Considering these
facts, it's safe to say that you won't be worrying about image
data collision detection in this book. It might be an avenue worth
considering in the future if the just-in-time Java compilers can
squeeze enough additional performance out of Java, and if you
are willing to dig into the programming complexities involved
in pulling it off.
<H2><A NAME="ImplementingSpriteAnimation"><B><FONT SIZE=5 COLOR=#FF0000>Implementing
Sprite Animation</FONT></B></A></H2>
<P>
As you learned earlier in today's lesson, sprite animation involves
the movement of individual graphic objects called sprites. Unlike
simple frame animation, sprite animation involves considerably
more overhead. More specifically, it is necessary to develop not
only a sprite class, but also a sprite management class for keeping
up with all the sprites in the system. This is necessary because
sprites need to be able to interact with each other through a
common mechanism. Furthermore, it is useful to extract the background
behind the sprites into a class of its own.
<P>
In this section, you learn how to implement sprite animation in
Java by creating a suite of sprite classes. The primary sprite
classes are <TT><FONT FACE="Courier">Sprite</FONT></TT> and <TT><FONT FACE="Courier">SpriteVector</FONT></TT>.
However, there are also a few support classes that you will learn
about as you get into the details of these two primary classes.
The <TT><FONT FACE="Courier">Sprite</FONT></TT> class models a
single sprite and contains all the information and methods necessary
to get a single sprite up and running. However, the real power
of sprite animation is harnessed by combining the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class with the <TT><FONT FACE="Courier">SpriteVector</FONT></TT>
class, which is a container class that manages multiple sprites
and their interaction with each other.
<H3><A NAME="TheSpriteClass"><B>The </B><TT><B><FONT SIZE=4 FACE="Courier">Sprite</FONT></B></TT><B><FONT SIZE=4>
Class</FONT></B></A></H3>
<P>
Although sprites can be implemented simply as moveable graphical
objects, you saw earlier that the sprite class developed here
will also contain support for frame animation. A frame- animated
sprite is basically a sprite with multiple frame images that can
be displayed in succession. The <TT><FONT FACE="Courier">Sprite</FONT></TT>
class you are about to see supports frame animation in the form
of an array of frame images and some methods for setting the current
frame image. Using this approach, you end up with a <TT><FONT FACE="Courier">Sprite</FONT></TT>
class that supports both fundamental types of animation and is
much more suitable for Java games.
<P>
Before jumping into the details of how the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class is implemented, take a moment to think about the different
pieces of information that a sprite must keep up with. When you
understand the components of a sprite at a conceptual level, it
will be much easier to understand the Java code. So, exactly what
information should a <TT><FONT FACE="Courier">Sprite</FONT></TT>
class maintain? The following list contains the key information
that the <TT><FONT FACE="Courier">Sprite</FONT></TT> class needs
to include:
<UL>
<LI>Array of frame images
<LI>Current frame
<LI>XY position
<LI>Velocity
<LI>Z-order
<LI>Boundary
</UL>
<P>
The first component, an array of frame images, is necessary to
carry out the frame animations. Even though this sounds like you
are forcing a sprite to have multiple animation frames, a sprite
can also use a single image. In this way, the frame animation
aspects of the sprite are optional. The current frame keeps up
with the current frame of animation. In a typical frame- animated
sprite, the current frame is incremented to the next frame when
the sprite is updated.
<P>
The XY position stores the position of the sprite. You can move
the sprite simply by altering this position. Alternatively, you
can set the velocity and let the sprite alter its position internally.
<P>
The Z-order represents the depth of the sprite in relation to
other sprites. Ultimately, the Z-order of a sprite determines
its drawing order (more on that a little later).
<P>
Finally, the boundary of a sprite refers to the bounded region
in which the sprite can move. All sprites are bound by some region-usually
the size of the applet window. The sprite boundary is important
because it determines the limits of a sprite's movement.
<P>
Now that you understand the core information required by the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class, it's time to get into the specific Java implementation.
Keep in mind that the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class contains all the features necessary to implement sprites
in the sample games throughout the rest of the book. Let's begin
with the <TT><FONT FACE="Courier">Sprite</FONT></TT> class's member
variables, which follow:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public static final int&nbsp;SA_KILL
= 0,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SA_RESTOREPOS
= 1,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SA_ADDSPRITE
= 2;<BR>
public static final int&nbsp;BA_STOP = 0,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BA_WRAP
= 1,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BA_BOUncE
= 2,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BA_DIE
= 3;<BR>
protected Component&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;component;<BR>
protected Image[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image;
<BR>
protected int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame,
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frameInc,
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frameDelay,
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frameTrigger;
<BR>
protected Rectangle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;collision;
<BR>
protected int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zOrder;
<BR>
protected Point&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;velocity;
<BR>
protected Rectangle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bounds;<BR>
protected int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boundsAction;
<BR>
protected boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hidden
= false;</FONT></TT>
</BLOCKQUOTE>
<P>
The member variables include the important sprite information
mentioned earlier, along with some other useful information. Most
notably, you are probably curious about the static final members
at the beginning of the listing. These members are constant identifiers
that define actions for the sprite. Two different types of actions
are supported by <TT><FONT FACE="Courier">Sprite</FONT></TT>:
sprite actions and bounds actions. <I>Sprite actions</I> are general
actions that a sprite can perform, such as killing itself or adding
another sprite. <I>Bounds actions</I> are actions that a sprite
takes in response to reaching a boundary, such as wrapping to
the other side or bouncing. Unlike sprite actions, bounds actions
are mutually exclusive, meaning that only one can be set at a
time.
<P>
After the actions, the <TT><FONT FACE="Courier">Component</FONT></TT>
member variable is the next member variable that you might be
curious about. It is necessary because an <TT><FONT FACE="Courier">ImageObserver</FONT></TT>
object is required to retrieve information about an image. But
what does <TT><FONT FACE="Courier">Component</FONT></TT> have
to do with <TT><FONT FACE="Courier">ImageObserver</FONT></TT>?
The <TT><FONT FACE="Courier">Component</FONT></TT> class implements
the <TT><FONT FACE="Courier">ImageObserver</FONT></TT> interface,
and the <TT><FONT FACE="Courier">Applet</FONT></TT> class is derived
from <TT><FONT FACE="Courier">Component</FONT></TT>. So, a <TT><FONT FACE="Courier">Sprite</FONT></TT>
object gets its image information from the Java applet itself,
which is used to initialize the <TT><FONT FACE="Courier">Component</FONT></TT>
member variable.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">ImageObserver</FONT></TT> is an interface defined in the <TT><FONT FACE="Courier">java.awt.image</FONT></TT> package that provides a means for receiving information about an image.
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<P>

⌨️ 快捷键说明

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