📄 167-171.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=167-171//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="161-167.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="171-177.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="CENTER"><A NAME="Heading14"></A><FONT COLOR="#000077">Determining Intersections with Bounding Boxes</FONT></H4>
<P>The easiest way to determine if two sprites intersect is by comparing their <I>bounding</I> <I>boxes</I>. A bounding box is the smallest rectangle, with edges parallel to the x and y coordinates, that contains the entire sprite. For example, Figure 5-10 shows the bounding boxes for the alien bitmap.</P>
<P><A NAME="Fig10"></A><A HREF="javascript:displayWindow('images/05-10.jpg',117,119 )"><IMG SRC="images/05-10t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/05-10.jpg',117,119)"><FONT COLOR="#000077"><B>Figure 5-10</B></FONT></A> Bounding box for alien</P>
<P>Here’s a simple formula for determining if two sprites intersect. Let’s say that the smallest pair of coordinates of box 1 is (x1,y1), and the largest pair is (x2,y2). Similarly, box 2’s smallest coordinates are (x3,y3), and the largest are (x4,y4). Figure 5-11 shows these two boxes in the applet coordinate system. Box 1 intersects with box 2 if and only if the following condition is true:
</P>
<!-- CODE SNIP //-->
<PRE>
(x2 >= x3) && (x4 >= x1) && // x-extents overlap
(y2 >= y3) && (y4 >= y1) // y-extents overlap
</PRE>
<!-- END CODE SNIP //-->
<P><A NAME="Fig11"></A><A HREF="javascript:displayWindow('images/05-11.jpg',561,382 )"><IMG SRC="images/05-11t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/05-11.jpg',561,382)"><FONT COLOR="#000077"><B>Figure 5-11</B></FONT></A> Determining bounding box intersection</P>
<P>Here’s another way of describing this equation. The x extent of a box is the range of x coordinates that the box occupies; y extents are defined analogously for y coordinates. The two boxes intersect if both their x extents and their y extents overlap. You can extend this intersection formula to three dimensions by testing whether the z extents also overlap.
</P>
<P>This intersection formula trades simplicity and speed for accuracy, since parts of the bounding box are outside the sprite, as you see for the alien in Figure 5-10. For video games, that’s a tradeoff that we will make. If you’re concerned by the occasional error, shrink the bounding boxes by a few pixels before performing the intersection routine. Now, let’s translate this intersection formula into the Java code used by GunSprite:</P>
<!-- CODE SNIP //-->
<PRE>
// compare bounding boxes
public boolean intersect(int x1,int y1,int x2,int y2) {
return visible && (x2 >= locx) && (locx+width >= x1)
&& (y2 >= locy) && (locy+height >= y1);
}
</PRE>
<!-- END CODE SNIP //-->
<P>This routine checks if the sprite at <I>(locx,locy)</I>, with the given <I>width</I> and <I>height</I>, intersects the bounding box between the coordinates <I>(x1,y1)</I> and <I>(x2,y2).</I> And if the sprite is not visible, it won’t overlap another sprite.</P>
<H4 ALIGN="CENTER"><A NAME="Heading15"></A><FONT COLOR="#000077">Implementing GunSprite</FONT></H4>
<P>Let’s put this together, into the definition of GunSprite, shown in Listing 5-6.
</P>
<P><B>Listing 5-6</B> GunSprite class</P>
<!-- CODE //-->
<PRE>
class GunSprite extends BitmapSprite
implements Moveable,Intersect {
public GunSprite(Image i, Applet a) {
super(i,a);
}
// the following methods implement Moveable:
public void setPosition(int x,int y) {
locx = x;
locy = y;
}
public void setVelocity(int x,int y) {
}
public void updatePosition() {
}
// the following methods implement Intersect:
// compare bounding boxes
public boolean intersect(int x1,int y1,int x2,int y2) {
return visible && (x2 >= locx) && (locx+width >= x1)
&& (y2 >= locy) && (locy+height >= y1);
}
// echo to stdout
public void hit() {
System.out.println("HIT!");
}
}
</PRE>
<!-- END CODE //-->
<P>As you see, the hit() method just echoes to the standard output stream, for now. (In the next chapter we will make an explosion.)
</P>
<P>Now let’s move on to the missile!</P>
<H4 ALIGN="LEFT"><A NAME="Heading16"></A><FONT COLOR="#000077">MissileSprite</FONT></H4>
<P>The missile will be a long, thin rectangle that moves vertically. It will derive from the RectSprite class that we first defined back in Chapter 3, Animating Sprites.
</P>
<H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">The RectSprite Class</FONT></H4>
<P>This version of RectSprite, shown in Listing 5-7, adds an additional constructor to the Chapter 3 version.
</P>
<P><B>Listing 5-7</B> RectSprite class</P>
<!-- CODE //-->
<PRE>
class RectSprite extends Sprite2D {
protected int width, height; // dimensions of rectangle
public RectSprite(int w,int h,Color c) {
locx = 0;
locy = 0;
width = w;
height = h;
color = c;
restore();
}
public RectSprite(int x,int y,int w,int h,Color c) {
locx = x;
locy = y;
width = w;
height = h;
color = c;
fill = false; // default: don't fill
restore(); // restore the sprite
}
// provide implementation of abstract methods:
public void update() {
// does nothing
}
// check if sprite's visible before painting
public void paint(Graphics g) {
if (visible) {
g.setColor(color);
if (fill) {
g.fillRect(locx,locy,width,height);
}
else {
g.drawRect(locx,locy,width,height);
}
}
}
}
</PRE>
<!-- END CODE //-->
<P>MissileSprite overrides RectSprite’s update() method to provide the missile behavior. First, the missile moves upward by updating <I>locy</I> with the y velocity, <I>vy</I>. If it passes the top boundary, stored in <I>stop</I>_<I>y</I>, the MissileSprite suspends, and the missile disappears from the screen:</P>
<!-- CODE SNIP //-->
<PRE>
// move missile
locy += vy;
if (locy < stop_y) {
suspend();
}
</PRE>
<!-- END CODE SNIP //-->
<H4 ALIGN="CENTER"><A NAME="Heading18"></A><FONT COLOR="#000077">Incorporating the Intersect Interface</FONT></H4>
<P>After moving, the missile checks to see whether it has collided with any targets. By using the Intersect interface, the missile object passes its bounding box to the potential victims, who are in the <I>target</I> array. If an intersection happens, the missile notifies the victim using the hit() method, and the missile sprite suspends:</P>
<!-- CODE //-->
<PRE>
Intersect target[]; // array of targets
...
for (int i=0; i<target.length; i++) {
if (target[i].intersect(locx,locy,
locx+width,locy+height)) {
target[i].hit(); // tell target it's been hit
suspend();
break;
}
}
</PRE>
<!-- END CODE //-->
<P>As you see, the missile can interact with any object that implements the Intersect interface. If we had hardcoded the class of the target sprite into this code (say UFO), then the missile would only be able to interact with UFOs and their subclasses. By using an interface, the MissileSprite can communicate with all target classes that implement Intersect, and this makes our game more extendable.
</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="161-167.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="171-177.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -