📄 809-812.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1571690433"><META name=vstitle content="Black Art of Java Game Programming"><META name=vsauthor content="Joel Fan"><META name=vsimprint content="Sams"><META name=vspublisher content="Macmillan Computer Publishing"><META name=vspubdate content="11/01/96"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Black Art of Java Game Programming:The Game of Worm</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><script><!--function displayWindow(url, width, height) { var Win = window.open(url,"displayWindow",'width=' + width +',height=' + height + ',resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></script><SCRIPT><!--function popUp(url) { var Win = window.open(url,"displayWindow",'width=400,height=300,resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></SCRIPT><script language="JavaScript1.2"><!--function checkForQuery(fm) { /* get the query value */ var i = escape(fm.query.value); if (i == "") { alert('Please enter a search word or phrase'); return false; } /* query is blank, dont run the .jsp file */ else return true; /* execute the .jsp file */}//--></script></HEAD><BODY>
<TABLE border=0 cellspacing=0 cellpadding=0>
<tr>
<td width=75 valign=top>
<img src="../1571690433.gif" width=60 height=73 alt="Black Art of Java Game Programming" border="1">
</td>
<td align="left">
<font face="arial, helvetica" size="-1" color="#336633"><b>Black Art of Java Game Programming</b></font>
<br>
<font face="arial, helvetica" size="-1"><i>by Joel Fan</i>
<br>
Sams, Macmillan Computer Publishing
<br>
<b>ISBN:</b> 1571690433<b> Pub Date:</b> 11/01/96</font>
</td>
</tr>
</table>
<P>
<!--ISBN=1571690433//-->
<!--TITLE=Black Art of Java Game Programming//-->
<!--AUTHOR=Joel Fan//-->
<!--AUTHOR=Eric Ries//-->
<!--AUTHOR=Calin Tenitchi//-->
<!--PUBLISHER=Macmillan Computer Publishing//-->
<!--IMPRINT=Sams//-->
<!--CHAPTER=20//-->
<!--PAGES=809-812//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="806-809.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="813-814.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="LEFT"><A NAME="Heading34"></A><FONT COLOR="#000077">Putting It All Together in the WormBin</FONT></H4>
<P>The WormBin class is derived from Java’s Applet class and implements Runnable, which allows easier control of real-time gaming action. The Next() function is called often and at regular intervals to move objects on the playing surface. Between calls to Next(), the thread is paused for a short period of time to give the illusion of smooth motion. WormBin’s Next() function calls SessionManager’s Next() function but also handles drawing new head segments and erasing tail segments. Listing 20-10 shows that the SessionManager’s Next() function is called first, and <I>true</I> is returned on collision. SessionManager remembers if a treat was eaten, and IsNewTreat() is called to allow drawing of the new treat. Because only the class WormBin is allowed to draw to the playing surface, additional code must be added to query the SessionManager for points to draw, and so on.</P>
<P><B>Listing 20-10</B> WormBin’s Next() function, which handles segment drawing and clearing</P>
<!-- CODE //-->
<PRE>
private boolean Next(Graphics g)
{
// call the session manager to get the next
// worm location. if true returned, we had a collision
if (smgr.Next()) {
if(hitsoundData != null)
hitsoundData.play();
return true;
}
// check if we just ate a treat and created a new
// one, if yes, we need to draw the new treat
if (smgr.IsNewTreat()) {
if(atesoundData != null)
atesoundData.play();
try {
Thread.sleep(100);
} catch (InterruptedException e)
{
}
DrawTreat(g);
}
// erase the tail segment(s)
if (smgr.IsFirstDropped()) {
do {
g.setColor(Color.black);
DrawSegment(g, smgr.CurrDroppedPoint());
} while (smgr.IsNextDropped());
}
// draw the head segment(s)
if (smgr.IsFirstAdded()) {
do {
g.setColor(smgr.CurrAddedColor());
DrawSegment(g, smgr.CurrAddedPoint());
} while (smgr.IsNextAdded());
}
// write out score only once in a while to avoid
// too much flicker
if (smgr.IsDisplayScore())
WriteScore();
return false;
}
</PRE>
<!-- END CODE //-->
<P>The iterators IsFirstDropped() and IsNextDropped() iterate over all worms with tail segments that have been dropped for this call of Next(). The tails must be erased before the new heads are drawn; otherwise, holes can appear in worm bodies under special circumstances. Notice that the color black is used to erase the worm segments. Drawing head segments are handled by equivalent IsFirstAdded() and IsNextAdded() functions. Finally, the SessionManager is queried if it is appropriate to draw a new score.
</P>
<P>The run() function is overridden in WormBin from the Applet class and has control of game play. Listing 20-11 shows the entire run() function. A double-buffer is created for drawing. The playing surface is cleared and a static worm and a treat are drawn and then displayed using the PaintWorm() function. The thread is paused until the user starts the game, at which point the game enters an infinite loop until the game ends. The normal sequence includes calling the Next() function to move the worms, calling the repaint() function to copy the hidden drawing buffer to the screen, and finally calling Thread.sleep() to stop the game for about 100 milliseconds. This sequence is repeated until the player’s worm collides with an object, then the Next() function repaints any new collision information and pauses the game until the player starts up a new game.</P>
<P><B>Listing 20-11</B> The applet thread run() function</P>
<!-- CODE //-->
<PRE>
public void run()
{
int delay;
if (kicker != null) {
// create a hidden buffer and clear it
wormimage = createImage(
smgr.GetPixelWidth(WORMSCALE) +
BORDERPAD,
smgr.GetPixelHeight(WORMSCALE) +
BORDERPAD);
// get context
wormgraphics = wormimage.getGraphics();
wormgraphics.setFont(getFont());
wormgraphics.setColor(Color.black);
wormgraphics.fillRect(0, 0,
smgr.GetPixelWidth(WORMSCALE) +
BORDERPAD,
smgr.GetPixelHeight(WORMSCALE) +
BORDERPAD);
// reset all variables to beginning,
// create new worm
Reset();
// draw current game status and paint to applet
// client area
PaintWorm(wormgraphics,false);
repaint();
ThreadPause("Start");
// loop until system terminates us
while (kicker != null) {
// loop while not minimized and have valid
// worker thread
while ( size().width > 0 &&
size().height > 0 &&
kicker != null) {
// get next worm position
if (Next(wormgraphics)) {
// worm collided,
// redraw all new entities
PaintWorm(wormgraphics,true);
repaint();
// stop game until user presses
// mouse button or hits a key
ThreadPause("Start");
// reset all variables to beginning,
// create new worm
Reset();
// draw current game status and paint
// to applet client area
PaintWorm(wormgraphics,false);
repaint();
break;
}
// repaint from hidden area to visible area
repaint();
// sleep for a very short time to make the
// game playable on fast computers
delay = smgr.GetDelay();
if (delay > 0)
try {
Thread.sleep(delay);
} catch (InterruptedException e)
{
}
}
}
}
}
</PRE>
<!-- END CODE //-->
<H3><A NAME="Heading35"></A><FONT COLOR="#000077">Adding Autonomous Worms</FONT></H3>
<P>A true test of Worm’s object-oriented design is to see if the Worm object can be easily adapted to support multiple instances and accept autonomous control. This simply means that additional worms should move around the playing surface under their own control. The term a<I>utonomous</I> means self-guiding and independent of user control and implies the worm will avoid collisions.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="806-809.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="813-814.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -