📄 676-679.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:WordQuest</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=16//-->
<!--PAGES=676-679//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="673-675.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="679-683.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="CENTER"><A NAME="Heading31"></A><FONT COLOR="#000077">The statusBar Class</FONT></H4>
<P>Even though we used ID constants to represent different kinds of Sprites, there are still some instances when extending the Sprite class is appropriate. One such instance is for the status bar that appears above the playing area. This is merely a Sprite that stays still, and whose data is comprised of several numeric variables. Instead of moving every time it is advanced, it recalculates the value of its data string. The status bar uses the MESSAGE ID in the Sprite class, so first we should add a case for MESSAGE to the generateImage() method:
</P>
<!-- CODE //-->
<PRE>
public synchronized void generateImage() {
...
case MESSAGE: {
blah.fillRect(0,0,bounds.width,bounds.height);
blah.setFont( new Font("Times New Roman",Font.BOLD,14));
blah.setColor(theColor);
blah.drawString(data,0,bounds.height);
break;
}
</PRE>
<!-- END CODE //-->
<P>Now we can create the statusBar class itself. There are four properties we need to track:
</P>
<DL>
<DD><B>•</B> int <I>score</I>. This represents the user’s score.
<DD><B>•</B> int <I>level.</I> This is the current “level” the user has attained.
<DD><B>•</B> int <I>lives.</I> This is the number of “lives” the user has left (number of times the user can die).
<DD><B>•</B> String <I>quest.</I> This is the text of the current question to be displayed.
</DL>
<P>In order to create the data string to be displayed, we must concatenate all of these values like this:
</P>
<!-- CODE SNIP //-->
<PRE>
data="Score: "+score+" Lives: "+lives+" Level: "+level+" "+quest;
</PRE>
<!-- END CODE SNIP //-->
<P>This is what happens every time the status bar is advanced. However, it is inefficient to do these calculations if nothing has changed since the last time they were performed, so we use a boolean variable to keep track of whether any change has occurred to any of the values that the status bar tracks. Here’s the first bit of code:
</P>
<!-- CODE //-->
<PRE>
import java.awt.*;
import Sprite;
public class statusBar extends Sprite {
String quest;
int score=0, lives=3, level=1;
boolean update=true;
statusBar(ThreadGroup tg, String d) {
super(tg,d);
data = null;
setID( MESSAGE );
theColor = Color.cyan;
advance();
}
}
</PRE>
<!-- END CODE //-->
<P>There’s nothing fancy here yet, but you’ll notice that we make a call to advance(), which is defined in Sprite, but which will only cause trouble if used as is. We had better override it:
</P>
<!-- CODE //-->
<PRE>
public void advance() {
if( !update)
return;
data="Score: "+score+" Lives: "+lives+" Level: "+level+" "+quest;
generateImage();
update=false;
}
</PRE>
<!-- END CODE //-->
<P>You see here how the update variable helps save time. However, this means that whenever a data variable is accessed, the update variable must get switched to <I>true</I>. Thus, no data variable can be accessed directly. Here are the wrapper functions that we will need:</P>
<!-- CODE //-->
<PRE>
public void addScore(int amt) {
score+=amt;
update=true;
}
public void addLives(int amt) {
lives+=amt;
update=true;
}
public void addLevel(int amt) {
level+=amt;
update=true;
}
public void setQuestion( String str) {
quest=str;
update=true;
}
</PRE>
<!-- END CODE //-->
<P>That’s all there is to this class. All other methods are taken care of by Sprite.
</P>
<H4 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">The userSprite Class</FONT></H4>
<P>There are several properties that we could decide to give the user’s object, but for now we just want to be sure that the user doesn’t try to leave the clipping Rectangle of the current Graphics context (which means we’d better be sure to clip it to the playing field):
</P>
<!-- CODE //-->
<PRE>
import Sprite;
import java.awt.*;
public class userSprite extends Sprite {
int WIDTH = 25;
int HEIGHT = 25;
userSprite(ThreadGroup tg, String name) {
super(tg,name);
setID(Sprite.USER);
data = null;
}
public void move( int x, int y) {
if( theG.getClipRect().inside(x,y))
super.move(x,y);
else
return;
}
}
</PRE>
<!-- END CODE //-->
<H3><A NAME="Heading33"></A><FONT COLOR="#000077">Writing WordQuest</FONT></H3>
<P>At long last, it is time to write the actual code for WordQuest. This is a long and arduous task, but if we don’t proceed, all of our efforts to date will have been for naught. Courage, my friends…
</P>
<H4 ALIGN="LEFT"><A NAME="Heading34"></A><FONT COLOR="#000077">Getting Started</FONT></H4>
<P>Let’s get all of our variables declared. WordQuest uses a very long list of variables, so let’s deal with them in small groups, based on what they’re used for. First, let’s get the importing done:
</P>
<!-- CODE //-->
<PRE>
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.net.*;
import java.io.*;
import Terrain;
import StarField;
import Sprite;
import userSprite;
import HighScoreManager;
public class WordQuest extends Applet implements Runnable {
}
</PRE>
<!-- END CODE //-->
<H4 ALIGN="CENTER"><A NAME="Heading35"></A><FONT COLOR="#000077">Variable Declarations</FONT></H4>
<P>Next, the Sprite variables:
</P>
<!-- CODE SNIP //-->
<PRE>
Thread kicker;
StarField SF=null;
Terrain T=null;
statusBar bar;
userSprite user;
</PRE>
<!-- END CODE SNIP //-->
<P>And then the ThreadGroups:
</P>
<!-- CODE SNIP //-->
<PRE>
ThreadGroup group,bullets,everything;
</PRE>
<!-- END CODE SNIP //-->
<P>The three groups are for the enemies, bullets, and the master group, respectively. Now the AWT variables:
</P>
<!-- CODE SNIP //-->
<PRE>
Rectangle SFrect, Trect,statRect;
Dimension d;
promptFrame PF;
Image im;
Graphics offScreenG;
</PRE>
<!-- END CODE SNIP //-->
<P>The three Rectangles are used to divide the screen into regions. The Graphics and Image are for doing offscreen double-buffered graphics stuff. The next few variables deal with Questions:
</P>
<!-- CODE SNIP //-->
<PRE>
Vector questions;
Question currentQ;
String name;
</PRE>
<!-- END CODE SNIP //-->
<P>And lastly, we use a boolean variable to keep track of whether the user is playing the game or looking at the high scores:
</P>
<!-- CODE SNIP //-->
<PRE>
boolean playing = false; // start with high scores
</PRE>
<!-- END CODE SNIP //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="673-675.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="679-683.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -