📄 179-185.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:Building a Video Game</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=5//-->
<!--PAGES=179-185//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="177-179.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="185-188.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">Transitioning Between States</FONT></H4>
<P>The best way to illustrate how the UFO goes from one state, or behavior, to another is with a transition diagram, in which the circles represent the four possible states, and the arrows indicate allowable transitions, as shown in Figure 5-14.
</P>
<P><A NAME="Fig14"></A><A HREF="javascript:displayWindow('images/05-14.jpg',560,381 )"><IMG SRC="images/05-14t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/05-14.jpg',560,381)"><FONT COLOR="#000077"><B>Figure 5-14</B></FONT></A> UFO transition diagram</P>
<P>Now, the UFO moves from state to state depending on random numbers generated by the static random() method in java.lang.Math:
</P>
<!-- CODE SNIP //-->
<PRE>
double x = Math.random(); // x is assigned a random
// double from 0.0 to 1.0
</PRE>
<!-- END CODE SNIP //-->
<P>If the random number is higher than these following constants, the UFO exits the corresponding state:
</P>
<!-- CODE SNIP //-->
<PRE>
// probability of state transitions
static final double STANDBY_EXIT = .95;
static final double ATTACK_EXIT = .95;
static final double RETREAT_EXIT = .95;
static final double LAND_EXIT = .95;
</PRE>
<!-- END CODE SNIP //-->
<P>Thus, the pattern of UFO behavior is unpredictable, and you can customize it by changing the probabilities.
</P>
<P>The UFO’s update() method first checks to see if a collision has occurred with the missile gun. GunSprite implements Intersect, so it can be a target of the UFO sprite:</P>
<!-- CODE //-->
<PRE>
// this implements the state machine
public void update() {
// if alien hits target
// gun_y contains the y-coordinate of the top of
// the gun. The first test is done to quickly
// eliminate those cases with no chance of
// intersection with the gun.
if ((locy + height >= gun_y) &&
target.intersect(locx,locy,locx+width,locy+height)) {
target.hit();
suspend();
return;
}
</PRE>
<!-- END CODE //-->
<P>If no collision occurs with the gun, the UFO executes behaviors according to its state. Let’s examine the Standby state:
</P>
<!-- CODE //-->
<PRE>
double r1 = Math.random(); // pick random nums
double r2 = Math.random();
switch (state) {
case STANDBY:
if (r1 > STANDBY_EXIT) {
if (r2 > 0.5) {
startAttack();
}
else {
startLand();
}
}
</PRE>
<!-- END CODE //-->
<P>Depending on the random numbers, the UFO can go to the Attack state or the Land state. The methods startAttack() and startLand() set the UFO’s velocity for those states.
</P>
<P>If a state transition doesn’t occur, the UFO continues with the Standby update, which reverses the UFO’s direction if it strays too close to the edges of the screen, or if the random number is above a threshold:</P>
<!-- CODE SNIP //-->
<PRE>
else if ((locx < width) || (locx > max_x - width) ||
(r2 > FLIP_X)) {
vx = -vx;
}
break;
</PRE>
<!-- END CODE SNIP //-->
<H4 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Implementing the UFO Sprite Class</FONT></H4>
<P>Now take a look, in Listing 5-11, at the complete UFO sprite class, and the update() method in particular.
</P>
<P><B>Listing 5-11</B> UFO class</P>
<!-- CODE //-->
<PRE>
public class UFO extends BitmapLoop implements Intersect {
byte state;
// UFO states
static final byte STANDBY = 0;
static final byte ATTACK = 1;
static final byte RETREAT = 2;
static final byte LAND = 3;
// probability of state transitions
static final double STANDBY_EXIT = .95;
static final double ATTACK_EXIT = .95;
static final double RETREAT_EXIT = .95;
static final double LAND_EXIT = .95;
static final double FLIP_X = 0.9;
static final int RETREAT_Y = 17;
int max_x, max_y; // max coords of this UFO
static Intersect target; // refers to the gun
static int gun_y; // the y-coord of gun
public UFO(Image ufoImages[],int max_x,int max_y,
Applet a) {
super(0,0,null,ufoImages,a);
this.max_x = max_x;
this.max_y = max_y;
currentImage = getRand(5); // start at random image
startStandby();
}
// finish initializing info about the player's gun
static public void initialize(GunManager gm) {
target = gm.getGun(); // refers to gun sprite
gun_y = gm.getGunY(); // get gun y-coordinate
}
// implement Intersect interface:
public boolean intersect(int x1,int y1,int x2,int y2) {
return visible && (x2 >= locx) && (locx+width >= x1)
&& (y2 >= locy) && (locy+height >= y1);
}
public void hit() {
// alien is invulnerable when it's attacking
// otherwise, suspend the sprite
if (state != ATTACK) {
suspend();
}
}
// this implements the state machine
public void update() {
// if alien hits target
if ((locy + height >= gun_y) &&
target.intersect(locx,locy,locx+width,locy+height)) {
target.hit();
suspend();
return;
}
// otherwise, update alien state
double r1 = Math.random(); // pick random nums
double r2 = Math.random();
switch (state) {
case STANDBY:
if (r1 > STANDBY_EXIT) {
if (r2 > 0.5) {
startAttack();
}
else {
startLand();
}
}
// else change the direction by flipping
// the x-velocity. Net result: ufo moves
// from side to side. And if the ufo gets close to
// the left or right side of screen, it always changes
// direction.
else if ((locx < width) || (locx > max_x - width) ||
(r2 > FLIP_X)) {
vx = -vx;
}
break;
case ATTACK:
// retreat if the alien flies too close to
// the ground
if ((r1 > ATTACK_EXIT) || (locy > gun_y - 17)) {
startRetreat();
}
// flip x-direction if it gets too close to edges
else if ((locx < width) || (locx > max_x - width) ||
(r2 > FLIP_X)) {
vx = -vx;
}
break;
case RETREAT:
if (r1 > RETREAT_EXIT) {
if (r2 > 0.5) {
startAttack();
}
else {
startStandby();
}
}
// stop retreat if ufo goes too close
// to top of screen
else if (locy < RETREAT_Y) {
startStandby();
}
break;
case LAND:
if (r1 > LAND_EXIT) {
startStandby();
}
// if the ufo is low enough,
// start the landing procedure
else if (locy >= max_y-height) {
landingRoutine();
}
break;
}
super.update(); // BitmapLoop update draws the
// appropriate image
}
protected void landingRoutine() {
System.out.println("ufo landed") ;
suspend();
}
protected void startStandby() {
vx = getRand(8)-4 ;
vy = 0;
state = STANDBY;
}
protected void startAttack() {
vx = getRand(10)-5;
vy = getRand(5)+4;
state = ATTACK;
}
protected void startRetreat() {
vx = 0;
vy = -getRand(3) - 2;
state = RETREAT;
}
protected void startLand() {
vx = 0;
vy = getRand(3) + 2;
state = LAND;
}
static public int getRand(int x) {
return (int)(x * Math.random());
}
}
</PRE>
<!-- END CODE //-->
<P>The UFO class is the most complex of this entire chapter, and you can use it as a template for enemies in your own games.
</P>
<P>Now let’s discuss the UFOManager class.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="177-179.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="185-188.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -