📄 052-056.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=052-056//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="045-052.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="056-060.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P>To run this applet, update the Mondrian.html file from Chapter 1 with the following applet tag. (In future applets, we’ll assume that you know how to create the applet tag in the HTML file.)
</P>
<!-- CODE SNIP //-->
<PRE>
<applet code="Broadway.class" width=300 height=300>
</PRE>
<!-- END CODE SNIP //-->
<P>Compile the source and run it with appletviewer or a Web browser.
</P>
<P>Although this applet is a bit more complex than its predecessor, it has methods that you learned about in Chapter 1—init(), start(), paint(), and stop()—that are called at various stages in the applet’s lifetime. Broadway.java has one extra method, run(). Can you guess what it does before reading on?</P>
<H4 ALIGN="LEFT"><A NAME="Heading4"></A><FONT COLOR="#000077">Using the Universal Animation Loop</FONT></H4>
<P>The run() method should look familiar. It is a Java version of the Universal Animation Loop, so it draws the current frame, updates the center rectangle for the next frame, and pauses before looping back to the top. Let’s examine the loop in more detail.
</P>
<P>The first line of run() is a call to repaint(), which is defined in the Applet class. Remember that Broadway is a subclass of Applet, so it inherits all of Applet’s methods. The method repaint() is one of these, and calling it has two effects:</P>
<DL>
<DD><B>1.</B> It clears the screen.
<DD><B>2.</B> It draws the current frame of the animation, by calling paint().
</DL>
<P>Thus, paint() is the Applet method that actually draws to the screen; repaint() redraws the screen by calling paint().
</P>
<P>The second method of run() is called updateRectangle(), which computes the newest location of the center rectangle and stores it in the variables <I>locx</I> and <I>locy</I>, which mark the rectangle’s upper-left corner. This has the effect of moving the rectangle for the next animation frame.</P>
<P>The last line of run() causes a delay of 100 milliseconds (.1 seconds) before looping back to the top and repeating the entire process, for a frame rate of around 10 fps. <I>Thread.sleep()</I> refers to the static method of the Thread class named sleep(); recall that static methods are invoked by prefixing the method name with the class name and a dot.</P>
<P>The run() method has its name for a particular reason. Take a look at the first line of Broadway:</P>
<!-- CODE SNIP //-->
<PRE>
public class Broadway extends Applet implements Runnable {
...
</PRE>
<!-- END CODE SNIP //-->
<P>Not only does Broadway extend Applet (meaning that it’s a subclass of Applet), but it <I>implements</I> Runnable as well. Runnable is an <I>interface</I>, which means that it specifies a set of methods that must be implemented by Broadway. run() is an example of such a method. You’ll learn more about interfaces in the next chapter; for now, remember that a class that <I>implements</I> an interface supplies the needed methods, whereas a class that <I>inherits</I> a method gets it for free!</P>
<P>Now let’s trace the execution of Broadway to see how it reaches the run() method.</P>
<H4 ALIGN="LEFT"><A NAME="Heading5"></A><FONT COLOR="#000077">Tracing the Applet’s Execution Path</FONT></H4>
<P>The execution path of Broadway is a bit complex. As you will recall, init() is called to initialize the applet, and then start() is called:
</P>
<!-- CODE SNIP //-->
<PRE>
public void start() {
System.out.println(">> start <<");
animation = new Thread(this);
if (animation != null) {
animation.start();
}
}
</PRE>
<!-- END CODE SNIP //-->
<P>start() does two things:
</P>
<DL>
<DD><B>1.</B> It creates a new thread called <I>animation.</I> (You’ll learn what the <I>this</I> keyword is, in the Using Objects section below.)
<DD><B>2.</B> It tells the <I>animation</I> thread to start executing the code in run(), by calling animation.start().
</DL>
<P>In effect, another thread of execution is created to execute the animation loop in run(). Figure 2-3 shows how the execution path of Broadway splits into two separate paths once the new thread is started.
</P>
<P><A NAME="Fig3"></A><A HREF="javascript:displayWindow('images/02-03.jpg',467,400 )"><IMG SRC="images/02-03t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/02-03.jpg',467,400)"><FONT COLOR="#000077"><B>Figure 2-3</B></FONT></A> Broadway execution path</P>
<P>The <I>animation</I> thread operates independently once its start() method is called, and stops executing in response to stop(). And while the <I>animation</I> thread is running, it causes the rectangle to jiggle around.</P>
<P>Why is all this code needed to create a simple animation? For example, why could you not just put the animation loop in the start() method, like this:</P>
<!-- CODE SNIP //-->
<PRE>
public void start() {
while (true) {
repaint();
updateRectangle();
try {
Thread.sleep (REFRESH_RATE);
} catch (Exception exc) { };
}
</PRE>
<!-- END CODE SNIP //-->
<P>As an experiment, try running Broadway with this rogue start() method. It won’t work, and the screen will stay blank! The reason is that the code you write in an applet works in conjunction with a lot of other code that you’ve inherited. If your start() method loops forever, instructions after the start() method are never executed. The result is that the screen stays blank! Figure 2-4 makes this clear. It shows what happens when you use the infinitely looping start() method, instead of the start() method that creates another thread of execution.
</P>
<P><A NAME="Fig4"></A><A HREF="javascript:displayWindow('images/02-04.jpg',316,249 )"><IMG SRC="images/02-04t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/02-04.jpg',316,249)"><FONT COLOR="#000077"><B>Figure 2-4</B></FONT></A> Broadway execution path with infinitely looping start() method</P>
<P>This should illustrate another point of creating graphics with Java: when paint() is called, the painting doesn’t occur simultaneously, but usually a short while later. If you call paint() too many times per second, Java can’t keep up, and it executes the most recent paint() to catch up (ignoring the previous paint() requests). As a result, there’s a limit on how fast a frame rate you can achieve; beyond that, the quality of the animation suffers. You can test the limits of your particular machine by setting the frame rate to a really high number and seeing what happens. (Try a pausing interval of less than 5 milli-seconds.)
</P>
<P>Even with the frame rate at a reasonable number, say 10–15 fps, you’ll notice an annoying flicker that mars the animation. Let’s find out how to get rid of it and improve animation performance by using two techniques: double-buffering and clipping.</P>
<H3><A NAME="Heading6"></A><FONT COLOR="#000077">Improving Animation Quality</FONT></H3>
<P>In this section, you’ll learn the cause of animation flicker and how to use double-buffering and clipping to improve the quality of your animations. We will use the Broadway Boogie Woogie applet as our example.
</P>
<P>First, let’s find out what’s causing flicker in the animation.</P>
<H4 ALIGN="LEFT"><A NAME="Heading7"></A><FONT COLOR="#000077">Understanding Animation Flicker</FONT></H4>
<P>Why does the screen flicker when Broadway is running? The answer is in a method, update(), that Broadway inherits from the Applet class. Every time you use repaint(), it actually calls update() to do the dirty work of clearing the screen and calling paint(). Here is the update() method that your applet inherits:
</P>
<!-- CODE SNIP //-->
<PRE>
public void update(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, width, height);
g.setColor(getForeground());
paint(g)
}
</PRE>
<!-- END CODE SNIP //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="045-052.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="056-060.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -