📄 075-079.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:Using Objects for Animations</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=2//-->
<!--PAGES=075-079//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="071-075.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="079-082.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
</P>
<P>The dance motion is also implemented by overriding the danceStep() method inherited from the superclass, as you will see in Listing 2-6.
</P>
<P><B>Listing 2-6</B> WaltzRect.java</P>
<!-- CODE //-->
<PRE>
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// WaltzRect also inherits from DancingRect
class WaltzRect extends DancingRect {
byte state;
static final byte SE = 0; // going southeast
static final byte NE = 1; // going northeast
static final byte W = 2; // going west
int bottom_x; // the x coordinate of
// bottom pt of the waltz
int right_x; // the x coordinate of
// right pt of the waltz
int left_x; // the x coordinate of
// left pt of the waltz
/////////////////////////////////////////////////////////////////
public WaltzRect(int x,int y,int w,int h,Color c) {
super(x,y,w,h,c); // call superclass constructor
bottom_x = locx + 17;
right_x = bottom_x + 17;
left_x = locx;
}
// override danceStep()
public void danceStep() {
switch (state) {
case SE:
locx++;
locy++;
if (locx == bottom_x) {
state = NE;
}
break;
case NE:
locx++;
locy--;
if (locx == right_x) {
state = W;
}
break;
case W:
locx-- ;
if (locx == left_x) {
state = SE;
}
break;
}
}
}
</PRE>
<!-- END CODE //-->
<P>The WaltzRect and BoogieRect constructors illustrate the use of <I>super</I> to invoke the superclass constructor. For example, the first line of WaltzRect’s<I> </I>constructor is</P>
<!-- CODE SNIP //-->
<PRE>
super(x,y,w,h,c); // call superclass constructor
</PRE>
<!-- END CODE SNIP //-->
<P>which calls the constructor of DancingRect.
</P>
<P>You are almost ready to put the dancing rectangle classes on stage! Before you do, there’s one more feature of object-oriented programming left to discuss, called <I>dynamic method binding</I>.</P>
<H3><A NAME="Heading26"></A><FONT COLOR="#000077">Using Dynamic Method Binding</FONT></H3>
<P>Dynamic method binding is the last key to object-oriented programming that we’ll discuss. It corresponds to using virtual functions in C++, and it is best illustrated by an example. This example serves simply as an introduction to dynamic method binding. In the following section, you will see how it is applied in greater detail.
</P>
<P>Consider two classes, A and B, where A is a subclass of B. Class A is also a <I>subtype</I> of B. This means that any variable of type B can be assigned a value of type A. For example:</P>
<!-- CODE SNIP //-->
<PRE>
B x; // x is a variable of type B
A a = new A(); // a refers to an object of type A
x = a; // Assigns x to a
</PRE>
<!-- END CODE SNIP //-->
<P>The last line assigns variable <I>x</I>, which is of type B, to <I>a</I>, which is type A. This assignment is legal because A is a subtype of B.</P>
<P>Now let’s say that A overrides the method foo() in B, so that instances of A have a different foo() than instances of B, as you saw in the section on inheritance. Consider the following code:</P>
<!-- CODE SNIP //-->
<PRE>
B x; // x is a variable of type B
A a = new A(); // a refers to an object of type A
B b = new B(); // b refers to an object of type B
x = b; // assign b to x
x.foo(); // which foo() method is called?
</PRE>
<!-- END CODE SNIP //-->
<P>x.foo() calls the foo() method of B, as you would expect. However, this code produces a different result:
</P>
<!-- CODE SNIP //-->
<PRE>
x = a; // assign a to x
x.foo(); // which foo() method is called?
</PRE>
<!-- END CODE SNIP //-->
<P>In the last line, x.foo() calls the foo() method in A! So the method foo() isn’t bound until runtime, which is why this feature is called “dynamic” method binding. In Java, instance methods are bound dynamically <I>by default</I>. Final and static methods are not bound dynamically.</P>
<P>This is all pretty abstract, and the next section shows how it’s used in practice.</P>
<H3><A NAME="Heading27"></A><FONT COLOR="#000077">Putting It Together</FONT></H3>
<P>Let’s create an applet called Woogie that will extend the rebuilt Mondrian applet to animate multiple dancing rectangles. Woogie sets all three types of dancing rectangles on the screen. You’ll see how the investment that we made in the last few sections pays off in terms of clean, understandable, extensible code.
</P>
<P>Let’s discuss some highlights of Woogie.</P>
<P>First, all the dancing rectangles are allocated in initRectangles():</P>
<!-- CODE //-->
<PRE>
public void initRectangles() {
// allocate dancing rectangles
r = new DancingRect[NUM_RECTS];
r[0] = new DancingRect(0,0,90,90,Color.yellow);
r[1] = new BoogieRect(250,0,40,190,Color.yellow);
r[2] = new WaltzRect(200,55,60,135,Color.yellow);
r[3] = new BoogieRect(80,200,220,90,Color.blue);
r[4] = new WaltzRect(100,10,90,80,Color.blue);
r[5] = new BoogieRect(80,100,110,90,Color.lightGray);
r[6] = new WaltzRect(200,0,45,45,Color.red);
r[7] = new WaltzRect(0,100,70,200,Color.red);
r[8] = new BoogieRect(200,55,60,135,Color.magenta);
}
</PRE>
<!-- END CODE //-->
<P>The array <I>r</I> points to each rectangle. Since WaltzRect and BoogieRect are subtypes of DancingRect, the assignments don’t cause type errors.</P>
<P>Next, the loop in run() is modified slightly, but it still resembles the Universal Animation Loop:</P>
<!-- CODE //-->
<PRE>
public void run() {
while (true) {
repaint();
updateRectangles();
try { // pause for REFRESH_RATE ms
Thread.sleep (REFRESH_RATE);
} catch (Exception exc) { };
}
}
</PRE>
<!-- END CODE //-->
<P>run() calls updateRectangles(), which tells each rectangle to dance. This is where dynamic method binding is used to provide the desired behavior for each rectangle:
</P>
<!-- CODE SNIP //-->
<PRE>
public void updateRectangles() {
for (int i=0; i<NUM_RECTS; i++) {
r[i].danceStep(); // each rectangles dance step
}
}
</PRE>
<!-- END CODE SNIP //-->
<P>Finally, the paint() method cycles through all the rectangles, telling each to draw itself. Double-buffering is implemented by passing the offscreen buffer to the paint() method of each rectangle.
</P>
<!-- CODE //-->
<PRE>
public void paint(Graphics g) {
offscreen.setColor(Color.black);
offscreen.fillRect(0,0,300,300); // clear buffer
for (int i=0; i<NUM_RECTS; i++) {
r[i].paint(offscreen); // paint each rectangle
}
g.drawImage(image,0,0,this);
}
</PRE>
<!-- END CODE //-->
<P>Now take a look at the full listing of Woogie.java, shown in Listing 2-7. You’ll agree that it’s quite easy to understand and modify, which will be your homework assignment for tonight!
</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="071-075.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="079-082.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -