📄 526-530.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 the JAVAroids 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=13//-->
<!--PAGES=526-530//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="522-526.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="530-533.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="LEFT"><A NAME="Heading12"></A><FONT COLOR="#000077">The RotateablePolygon Class</FONT></H4>
<P>Making our polygons rotate is going to take just a little more effort than making them move. Implementing rotation according to the equations above requires computing the polar form of the offset vectors.
</P>
<P>Here are the instance variables in class RotateablePolygon that will store the polar coordinates:</P>
<!-- CODE SNIP //-->
<PRE>
protected float magnitude[]; // magnitudes of vectors
protected int angle[]; // angles of vectors
</PRE>
<!-- END CODE SNIP //-->
<P>The magnitudes of the offset vectors are stored in float <I>magnitude[]</I>, and the angles in int <I>angle[].</I> The <I>magnitude[]</I> and <I>angle[]</I> arrays are computed in the constructor for RotateablePolygon, which is shown in Listing 13-7.</P>
<P><B>Listing 13-7</B> RotateablePolygon class</P>
<!-- CODE //-->
<PRE>
/////////////////////////////////////////////////////////////////
//
// RotateablePolygon: encapsulates a MoveablePolygon that also
// rotates
/////////////////////////////////////////////////////////////////
class RotateablePolygon extends MoveablePolygon {
// variables:
protected float magnitude[]; // magnitudes of vectors
protected int theta = 0; // current angle of
// orientation
protected int angle[]; // angles of vectors
// (offset from theta)
protected int rate = 0; // rate of rotation
// methods:
/////////////////////////////////////////////////////////////////
// Constructor: take local vectors, center,color,screen bounds,
// and approximate max radius of polygon
/////////////////////////////////////////////////////////////////
public RotateablePolygon(int tx[], int ty[], int n,
int centerx, int centery, Color c,
int w, int h, int r) {
super(tx,ty,n,centerx,centery,c,w,h,r);
magnitude = new float[n];
angle = new int[n];
// compute magnitude and angle for each local vector
// this is the Cartesian ==> Polar coordinate transformation
for (int i=0; i<n; i++) {
magnitude[i] =
(float)GameMath.computeMagnitude(tx[i],ty[i]);
angle[i] =
(int)Math.round(GameMath.computeAngle(tx[i],ty[i]));
}
}
</PRE>
<!-- END CODE //-->
<P>Now, we want these polygons to rotate on their own, with each call to update(). The variable <I>theta</I> represents the current angle of orientation. Figure 13-10 illustrates a polygon at various orientations of <I>theta</I>.</P>
<P><A NAME="Fig10"></A><A HREF="javascript:displayWindow('images/13-10.jpg',600,411 )"><IMG SRC="images/13-10t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/13-10.jpg',600,411)"><FONT COLOR="#000077"><B>Figure 13-10</B></FONT></A> Polygon at different values of <I>theta</I>
</P>
<P>The variable <I>rate</I> supplies the rotation rate of the polygon, in degrees per update() call. Here are a few methods that enable other classes to access <I>theta</I> and <I>rate</I>:</P>
<!-- CODE //-->
<PRE>
/////////////////////////////////////////////////////////////////
// set the angle of orientation
/////////////////////////////////////////////////////////////////
public void setAngle(int a) {
theta = a;
}
/////////////////////////////////////////////////////////////////
// set rate (in degrees) for continuous rotation
/////////////////////////////////////////////////////////////////
public void setRotationRate(int r) {
rate = r;
}
/////////////////////////////////////////////////////////////////
// update the angle of orientation by the rotation rate
/////////////////////////////////////////////////////////////////
public void updateAngle() {
theta = checkAngleBounds(theta + rate);
}
/////////////////////////////////////////////////////////////////
// update the angle of orientation with a parameter
/////////////////////////////////////////////////////////////////
public void updateAngle(int a) {
theta = checkAngleBounds(theta + a);
}
/////////////////////////////////////////////////////////////////
// check that th is between 0 to 359
/////////////////////////////////////////////////////////////////
public int checkAngleBounds(int th) {
if (th >= 360)
th -= 360;
else if (th < 0)
th += 360;
return th;
}
</PRE>
<!-- END CODE //-->
<P>Rotation of the sprite is performed by the rotate() method. Each vector’s angle, stored in array <I>angle[],</I> is added to the current amount of rotation stored in <I>theta</I>. Then, the rotated vector, oriented at this new angle, is transformed to screen coordinates and stored in the Polygon <I>p.</I> One subtlety: using Math.round() to round doubles before casting to ints really improves the appearance of the rotating polygon.</P>
<!-- CODE //-->
<PRE>
/////////////////////////////////////////////////////////////////
// rotate polygon by 'a' degrees.
// this is accomplished by using the polar representation
// of the polygon, then converting back to Cartesian coordinates
/////////////////////////////////////////////////////////////////
public void rotate(int a) {
// compute new angle of orientation
theta = checkAngleBounds(theta + a);
// for each offset vector,
// compute the new angle that its facing
// compute the coords associated with this angle
// update the polygon representation
for (int i=0; i<p.npoints; i++) {
double tempx, tempy;
tempx = (magnitude[i]*GameMath.cos(theta)) ;
tempy = (magnitude[i]*GameMath.sin(theta)) ;
tx[i] = (int)Math.round(tempx);
p.xpoints[i] = (int)Math.round(tempx + (double)locx);
ty[i] = (int)Math.round(tempy);
p.ypoints[i] = (int)Math.round(tempy + (double) locy);
}
}
</PRE>
<!-- END CODE //-->
<P>By precomputing and storing the polar coordinates, we’ve reduced the complexity of rotation to two multiplies per vector, and two more additions to translate the vector to screen coordinates.
</P>
<P>Finally, update() is just</P>
<!-- CODE //-->
<PRE>
/////////////////////////////////////////////////////////////////
// default update -- assumes continuous rotation //
/////////////////////////////////////////////////////////////////
public void update() {
updatePosition(); // update location of sprite
rotate(rate); // rotate the sprite
updateAngle(); // update the orientation
}
}
</PRE>
<!-- END CODE //-->
<P>As you can see, RotateablePolygon inherits several methods and instance variables from its superclasses. Inheritance lets you write code in an incremental, modular fashion, and allows you to easily extend the functionality of the graphics engine.
</P>
<P>Now it’s time to start building JAVAroids! We’re going to proceed incrementally, by building each sprite class that’s used in the game, and then defining the manager classes. First, it’s important to organize a strong overall structure before moving on to the details.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="522-526.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="530-533.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -