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

📄 ch10.htm

📁 对于程序员来说可以利用JAVA来开发网络游戏!
💻 HTM
📖 第 1 页 / 共 4 页
字号:
&nbsp;&nbsp;public static Image[] image;<BR>
<BR>
&nbsp;&nbsp;public GilaMonster(Component comp) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;super(comp, image, 0, 1, 4, new Point(comp.size().width
-<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image[0].getWidth(comp), 45),
new Point(-1, 0), 30,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sprite.BA_WRAP);<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public static void initResources(Applet app, MediaTracker
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;tracker, int id) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;image = new Image[2];<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; 2; i++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image[i] = app.getImage(app.getCodeBase(),
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Res/GilaMon&quot;
+ i + &quot;.gif&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tracker.addImage(image[i],
id);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;protected void setCollision() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;collision = new Rectangle(position.x +
3, position.y + 3,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position.width - 6, position.height
- 6);<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">GilaMonster</FONT></TT> class uses
two images to show a simple animation of a Gila monster kicking
its legs. The constructor specifies a fixed horizontal velocity
that, when combined with the frame animation, gives the effect
of the Gila monster walking. Admittedly, having only two frame
animations creates some limitation in how effective the illusion
of walking is in this case. But remember that you're trying to
avoid using tons of graphics that take up precious time loading
over the Internet.
<P>
The three other predator classes (<TT><FONT FACE="Courier">Scorpion</FONT></TT>,
<TT><FONT FACE="Courier">Rattler</FONT></TT>, and <TT><FONT FACE="Courier">Tarantula</FONT></TT>)
are almost identical to <TT><FONT FACE="Courier">GilaMonster</FONT></TT>,
with the changes being the velocities, the images loaded in <TT><FONT FACE="Courier">initResources</FONT></TT>,
and the amount that the collision rectangle is shrunken. Based
on the code for <TT><FONT FACE="Courier">GilaMonster</FONT></TT>,
you might be wondering why it's even implemented as a derived
sprite class. It doesn't really add any new functionality; you
could just as easily create a Gila monster using the <TT><FONT FACE="Courier">Sprite</FONT></TT>
class. The truth is that all the predator classes are created
as more of a convenience than a necessity. Allowing the classes
to manage their own image resources via <TT><FONT FACE="Courier">initResources</FONT></TT>,
as well as having self-contained constructors that don't take
a bunch of parameters, improves organization.
<P>
This goes against typical object-oriented design because the classes
don't technically add any new functionality. However, the clean
packaging of the classes and their improved ease of use makes
them justifiable in this case. You might think that I'm taking
a lot of liberties by encouraging you to break the rules that
are so crucial in object-oriented languages such as Java. That's
not entirely true. The real skill in object-oriented programming
is in knowing when to apply OOP techniques and when to leverage
them against more simple solutions, as you've done here.
<P>
The <TT><FONT FACE="Courier">Rock</FONT></TT> class is the last
of the <TT><FONT FACE="Courier">Sprite</FONT></TT> derived classes
used in Traveling Gecko. Listing 10.4 contains the source code
for the <TT><FONT FACE="Courier">Rock</FONT></TT> class.
<HR>
<BLOCKQUOTE>
<B>Listing 10.4. The </B><TT><B><FONT FACE="Courier">Rock</FONT></B></TT><B>
class<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public class Rock extends Sprite {<BR>
&nbsp;&nbsp;public static Image[] image;<BR>
<BR>
&nbsp;&nbsp;public Rock(Component comp, int i) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;super(comp, image, i, 0, 0, new Point((i
% 2 == 0) ? 0 :<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;comp.size().width - image[i].getWidth(comp),
(i &lt; 2) ?<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 : comp.size().height - image[i].getHeight(comp)),
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Point(0, 0), 40, Sprite.BA_STOP);
<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public static void initResources(Applet app, MediaTracker
tracker,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;int id) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;image = new Image[4];<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; 4; i++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image[i] = app.getImage(app.getCodeBase(),
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Res/Rock&quot;
+ i + &quot;.gif&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tracker.addImage(image[i],
id);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public BitSet update() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return (new BitSet());<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">Rock</FONT></TT> class is somewhat
similar to the predator classes in that it doesn't add much functionality.
However, you have a very useful reason for creating a <TT><FONT FACE="Courier">Rock</FONT></TT>
class, as opposed to just creating rocks as <TT><FONT FACE="Courier">Sprite</FONT></TT>
objects. That reason has to do with an optimization related to
the <TT><FONT FACE="Courier">update</FONT></TT> method. If you
recall, the <TT><FONT FACE="Courier">update</FONT></TT> method
is called for every sprite in the sprite list to allow the animation
frame and position to be updated. Rocks have no animation frames
and the positions are fixed. Therefore, you can speed things up
a little by overriding <TT><FONT FACE="Courier">update</FONT></TT>
with a &quot;do nothing&quot; version. Because speed is a crucial
issue in games, especially Java games, seemingly small optimizations
like this can add up in the end.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
The trick that is used to help improve speed in the <TT><FONT FACE="Courier">Rock</FONT></TT> class's <TT><FONT FACE="Courier">update</FONT></TT> method brings up a good point in regard to game programming: Don't be afraid to override unneeded methods with 
&quot;do nothing&quot; versions. Every little bit of execution overhead that you can eliminate will ultimately improve the performance of a game. If you see a way to cut a corner in a derived class simply by overriding a parent class method, go for it! 
Just remember to wait and look for these types of shortcuts after the code is already working.
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<P>
The only other sprite-related class to deal with in regard to
Traveling Gecko is the derived <TT><FONT FACE="Courier">SpriteVector</FONT></TT>
class, <TT><FONT FACE="Courier">TGVector</FONT></TT>. You need
the <TT><FONT FACE="Courier">TGVector</FONT></TT> class to handle
the collisions between the sprites. Listing 10.5 contains the
source code for the <TT><FONT FACE="Courier">TGVector</FONT></TT>
class.
<HR>
<BLOCKQUOTE>
<B>Listing 10.5. The </B><TT><B><FONT FACE="Courier">TGVector</FONT></B></TT><B>
class.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public class TGVector extends SpriteVector
{<BR>
&nbsp;&nbsp;private Component component;<BR>
<BR>
&nbsp;&nbsp;public TGVector(Background back, Component comp) {
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;super(back);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;component = comp;<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;protected boolean collision(int i, int iHit) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;Sprite s = (Sprite)elementAt(i);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;Sprite sHit = (Sprite)elementAt(iHit);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (sHit.getClass().getName().equals(&quot;Rock&quot;))
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Collided with rock, so
stay put<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else if (sHit.getClass().getName().equals(&quot;Geckocide&quot;))
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Collided with geckocide,
so do nothing<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else if (s.getClass().getName().equals(&quot;Gecko&quot;))
{<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Kill or reposition it<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point pos = new Point(s.getPosition().x,
s.getPosition().y);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (--TravelingGecko.lives
&lt;= 0)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;removeElementAt(i--);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.setPosition(new
Point(42, 232));<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Collided with bad guy,
so add geckocide<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (add(new Geckocide(component,
pos)) &lt;= i)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return false;<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
As you can see, the only overridden method in <TT><FONT FACE="Courier">TGVector</FONT></TT>
is <TT><FONT FACE="Courier">collision</FONT></TT>, which is called
when a collision occurs between two sprites. The sprite hit in
the collision is first checked to see whether it is a <TT><FONT FACE="Courier">Rock</FONT></TT>
object. If so, <TT><FONT FACE="Courier">true</FONT></TT> is returned,
which causes the sprite that is doing the hitting to stay where
it is and not use its updated position. This results in the gecko
being stopped when he runs into a rock.
<P>
The sprite being hit is then checked to see whether it is a <TT><FONT FACE="Courier">Geckocide</FONT></TT>
object, in which case <TT><FONT FACE="Courier">collision</FONT></TT>
returns <TT><FONT FACE="Courier">false</FONT></TT>. This results
in allowing the sprite that is doing the hitting to continue on
its course, and basically results in a null collision. The purpose
of this code is to make sure that <TT><FONT FACE="Courier">Geckocide</FONT></TT>
objects don't interfere with any other objects; they are effectively
ignored by the collision detection routine.
<P>
The real work begins when the hitting sprite is checked to see
whether it is a <TT><FONT FACE="Courier">Gecko</FONT></TT> object.
If so, you know that the gecko has collided with a predator, so
the number of lives is decremented. The <TT><FONT FACE="Courier">lives</FONT></TT>
variable is like <TT><FONT FACE="Courier">score</FONT></TT> because
it is a public static member of the <TT><FONT FACE="Courier">TravelingGecko</FONT></TT>
applet class. If <TT><FONT FACE="Courier">lives</FONT></TT> is
less than or equal to zero, the game is over and the <TT><FONT FACE="Courier">Gecko</FONT></TT>
object is removed from the sprite list. If <TT><FONT FACE="Courier">lives</FONT></TT>
is greater than zero, the gecko is repositioned back at the starting
position. To the player, it appears as if a new gecko has been
created, but you're really just moving the old one. Because a
gecko has died in either case, a <TT><FONT FACE="Courier">Geckocide</FONT></TT>
object is created.
<P>
At this point, you've seen all the supporting sprite classes required
of Traveling Gecko. The last step is to see what tasks the applet
class itself is responsible for.
<H3><A NAME="TheTravelingGeckoClass"><B>The </B><TT><B><FONT SIZE=4 FACE="Courier">TravelingGecko</FONT></B></TT><B><FONT SIZE=4>
Class</FONT></B></A></H3>
<P>
The <TT><FONT FACE="Courier">TravelingGecko</FONT></TT> class
drives the applet and takes care of higher-level issues such as
dealing with user input. Much of this class consists of animation
overhead that you're already familiar with, so let's skip ahead
to the more interesting aspects of <TT><FONT FACE="Courier">TravelingGecko</FONT></TT>.
<P>
The <TT><FONT FACE="Courier">init</FONT></TT> method adds a new
twist by creating the New Game button. It also handles initializing
all the resources for the different sprites. The code for the
<TT><FONT FACE="Courier">init</FONT></TT> method is shown in Listing
10.6.
<HR>
<BLOCKQUOTE>
<B>Listing 10.6. The </B><TT><B><FONT FACE="Courier">TravelingGecko</FONT></B></TT><B>
class's </B><TT><B><FONT FACE="Courier">init</FONT></B></TT><B>
method.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void init() {<BR>

⌨️ 快捷键说明

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