⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch5.htm

📁 对于程序员来说可以利用JAVA来开发网络游戏!
💻 HTM
📖 第 1 页 / 共 4 页
字号:
in this section. The <TT><FONT FACE="Courier">isErrorID</FONT></TT>
and <TT><FONT FACE="Courier">isErrorAny</FONT></TT> methods check
the error status of images being tracked. The only difference
between the two is that <TT><FONT FACE="Courier">isErrorID</FONT></TT>
checks on images with a certain identifier, whereas <TT><FONT FACE="Courier">isErrorAny</FONT></TT>
checks on all images. Both of these methods basically check the
status of each image for the <TT><FONT FACE="Courier">ERRORED</FONT></TT>
flag. Note that both methods will return <TT><FONT FACE="Courier">true</FONT></TT>
if any of the images have errors; it's up to you to determine
which specific images had errors.
<P>
If you use <TT><FONT FACE="Courier">isErrorID</FONT></TT> or <TT><FONT FACE="Courier">isErrorAny</FONT></TT>
and find out that there are load errors, you need to find out
which images have errors. You do this by using the <TT><FONT FACE="Courier">getErrorsID</FONT></TT>
and <TT><FONT FACE="Courier">getErrorsAny</FONT></TT> methods.
These two methods both return an array of <TT><FONT FACE="Courier">Object</FONT></TT>s
containing the media objects that have load errors. In the current
implementation of the <TT><FONT FACE="Courier">MediaTracker</FONT></TT>
class, this array is always filled with <TT><FONT FACE="Courier">Image</FONT></TT>
objects. If there are no errors, these methods return <TT><FONT FACE="Courier">null</FONT></TT>.
Similar to the <TT><FONT FACE="Courier">isErrorID</FONT></TT>
and <TT><FONT FACE="Courier">isErrorAny</FONT></TT> methods, <TT><FONT FACE="Courier">getErrorsID</FONT></TT>
and <TT><FONT FACE="Courier">getErrorsAny</FONT></TT> differ only
by the images that they check; <TT><FONT FACE="Courier">getErrorsID</FONT></TT>
returns errored images matching the passed identifier, and <TT><FONT FACE="Courier">getErrorsAny</FONT></TT>
returns all errored images.
<P>
That wraps up the description of the <TT><FONT FACE="Courier">MediaTracker</FONT></TT>
class. Now that you understand what the class is all about, you're
probably ready to see it in action. Read on!
<H3><A NAME="UsingtheMediaTracker"><B>Using the Media Tracker</B></A>
</H3>
<P>
With the media tracker, you know exactly when certain images have
been transferred and are ready to use. This enables you to display
alternative output based on whether or not images have finished
transferring. The Tarantulas sample applet, which is located on
the accompanying CD-ROM, demonstrates how to use the media tracker
to track the loading of multiple images and display them only
when they have all finished transferring. Figure 5.9 shows the
Tarantulas applet while the images are still being loaded.
<P>
<A HREF="f5-9.gif" ><B>Figure 5.9 : </B><I>The Tarantulas applet with images partially loaded.</I></A>
<P>
As you can see, none of the images are displayed until they have
all been successfully transferred. While they are loading, a text
message is displayed informing the user that the images are still
in the process of loading. This is a pretty simple enhancement
to the applet, but one that makes the applet look much more professional.
By displaying a simple message while media objects are loading,
you solve the problem of drawing partially transferred images,
and more important, the problem of displaying animations with
missing images. The source code for Tarantulas is shown in Listing
5.3.
<HR>
<BLOCKQUOTE>
<B>Listing 5.3. The Tarantulas sample applet.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">import java.applet.*;<BR>
import java.awt.*;<BR>
<BR>
public class Tarantulas extends Applet implements Runnable {<BR>
&nbsp;&nbsp;Image&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img[]
= new Image[8];<BR>
&nbsp;&nbsp;Thread&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread;
<BR>
&nbsp;&nbsp;MediaTracker&nbsp;&nbsp;tracker;<BR>
<BR>
&nbsp;&nbsp;public void init() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;tracker = new MediaTracker(this);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; 8; i++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img[i] = getImage(getDocumentBase(),
&quot;Res/Tarant&quot; + i + &quot;.gif&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tracker.addImage(img[i], 0);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public void start() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;thread = new Thread(this);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;thread.start();<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public void stop() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;thread.stop();<BR>
&nbsp;&nbsp;&nbsp;&nbsp;thread = null;<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public void run() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;try {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tracker.waitForID(0);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;catch (InterruptedException e) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;repaint();<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public void paint(Graphics g) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if ((tracker.statusID(0, true) &amp; MediaTracker.ERRORED)
!= 0) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(Color.red);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(0, 0, size().width,
size().height);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if ((tracker.statusID(0, true) &amp; MediaTracker.COMPLETE)
!= 0) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; 8;
i++)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.drawImage(img[i],
i * img[i].getWidth(this), 0, this);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Font&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font
= new Font(&quot;Helvetica&quot;, Font.PLAIN, 18);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontMetrics fm = g.getFontMetrics(font);
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str
= new String(&quot;Loading images...&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setFont(font);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.drawString(str, (size().width
- fm.stringWidth(str)) / 2,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((size().height
- fm.getHeight()) / 2) + fm.getAscent());<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}</FONT></TT>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Begin examining the Tarantulas sample applet by looking at the
member variables. The <TT><FONT FACE="Courier">thread</FONT></TT>
member is a <TT><FONT FACE="Courier">Thread</FONT></TT> object
that is used by the media tracker to wait for the images to load.
The <TT><FONT FACE="Courier">tracker</FONT></TT> member is the
<TT><FONT FACE="Courier">MediaTracker</FONT></TT> object used
to track the images.
<P>
In the <TT><FONT FACE="Courier">init</FONT></TT> method, the <TT><FONT FACE="Courier">MediaTracker</FONT></TT>
object is created by passing <TT><FONT FACE="Courier">this</FONT></TT>
as the only parameter to its constructor. Because the <TT><FONT FACE="Courier">init</FONT></TT>
method is a member of the applet class, <TT><FONT FACE="Courier">Tarantulas</FONT></TT>,
<TT><FONT FACE="Courier">this</FONT></TT> refers to the applet
object. If you recall from the discussion of the <TT><FONT FACE="Courier">MediaTracker</FONT></TT>
class earlier in this chapter, the sole constructor parameter
is of type <TT><FONT FACE="Courier">Component</FONT></TT> and
represents the component on which the tracked images will be drawn.
All <TT><FONT FACE="Courier">Applet</FONT></TT> objects are derived
from <TT><FONT FACE="Courier">Component</FONT></TT>, so passing
the <TT><FONT FACE="Courier">Applet</FONT></TT> object (<TT><FONT FACE="Courier">this</FONT></TT>)
correctly initializes the media tracker.
<P>
Also notice that the images are added to the media tracker in
the <TT><FONT FACE="Courier">init</FONT></TT> method. You do this
by calling the <TT><FONT FACE="Courier">addImage</FONT></TT> method
of <TT><FONT FACE="Courier">MediaTracker</FONT></TT> and passing
the <TT><FONT FACE="Courier">Image</FONT></TT> object and an identifier.
Notice that <TT><FONT FACE="Courier">0</FONT></TT> is passed as
the identifier for all the images. This means that you are tracking
them as a group using <TT><FONT FACE="Courier">0</FONT></TT> to
uniquely identify them.
<P>
The <TT><FONT FACE="Courier">start</FONT></TT> and <TT><FONT FACE="Courier">stop</FONT></TT>
methods are used to manage the creation and destruction of the
<TT><FONT FACE="Courier">Thread</FONT></TT> member object. These
are pretty standard implementations for adding basic multithreading
support to an applet. You'll see these methods several times throughout
the book because most of the sample applets use threads extensively.
<P>
The tracking actually starts taking place with the <TT><FONT FACE="Courier">run</FONT></TT>
method. The <TT><FONT FACE="Courier">waitForID</FONT></TT> method
of <TT><FONT FACE="Courier">MediaTracker</FONT></TT> is called
within a <TT><FONT FACE="Courier">try</FONT></TT>-<TT><FONT FACE="Courier">catch</FONT></TT>
clause. It must be placed in this exception-handling clause because
an <TT><FONT FACE="Courier">InterruptedException</FONT></TT> will
be thrown if another thread interrupts this thread. Recall that
<TT><FONT FACE="Courier">waitForID</FONT></TT> is synchronous,
meaning that it won't return until all the images with the specified
identifier have been loaded. This means that the call to <TT><FONT FACE="Courier">repaint</FONT></TT>
will not occur until the images have all been loaded.
<P>
To understand why this works, you need to look at the last method
in Tarantulas, <TT><FONT FACE="Courier">paint</FONT></TT>. The
<TT><FONT FACE="Courier">paint</FONT></TT> method begins by checking
to see whether an error has occurred in loading the images. It
does this by calling <TT><FONT FACE="Courier">statusID</FONT></TT>
and checking the result against the <TT><FONT FACE="Courier">ERRORED</FONT></TT>
flag. If an error has occurred, <TT><FONT FACE="Courier">paint</FONT></TT>
fills the applet window with the color red to indicate an error.
Figure 5.10 shows what Tarantulas looks like when an error occurs.
<P>
<A HREF="f5-10.gif" ><B>Figure 5.10 : </B><I>The Tarantulas applet with an error loading the images.</I></A>
<P>
The next check performed by <TT><FONT FACE="Courier">paint</FONT></TT>
is to see whether the images have finished loading. It does this
by calling <TT><FONT FACE="Courier">statusID</FONT></TT> and comparing
the result with the <TT><FONT FACE="Courier">COMPLETE</FONT></TT>
flag. If the images have finished loading, the image array is
iterated through and each image is drawn on the applet window.
If the images have not finished loading, the text message <TT><FONT FACE="Courier">Loading
images...</FONT></TT> is displayed. Figure 5.11 shows the Tarantulas
applet with all the images successfully loaded.
<P>
<A HREF="f5-11.gif" ><B>Figure 5.11 : </B><I>The Tarantulas applet with all the images loaded.</I></A>
<P>
That's all there is to tracking images. Too bad all of Java game
programming isn't this easy-actually, it almost is!
<H2><A NAME="Summary"><B><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></B></A>
</H2>
<P>
Today you were bombarded with a lot of information about the graphics
support in Java. Most of it was centered around the <TT><FONT FACE="Courier">Graphics</FONT></TT>
object, which is fortunately pretty straightforward to use. You
began by learning about color and what it means in the context
of Java. You then moved on to drawing graphics primitives, text,
and images. The lesson concluded with a detailed look at how images
are tracked and managed using the Java media tracker.
<P>
Today marked your first major foray into real Java coding for
games. Even though no game-specific code was developed, you learned
a great deal about the Java graphics system, which is used extensively
in games. If you're still hungry for more, don't worry, because
tomorrow's lesson picks up where you left off and dives into animation.
If you think you learned a lot today, you better brace yourself
for tomorrow!
<H2><A NAME="QA"><B><FONT SIZE=5 COLOR=#FF0000>Q&amp;A</FONT></B></A>
<BR>
</H2>
<P>
<TABLE>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>If the <TT><B><FONT FACE="Courier">Color</FONT></B></TT> class already contains predefined colors, why does it still have a constructor that accepts the three primary colors?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Because there might be times when you want to use a color that isn't defined in the <TT><FONT FACE="Courier">Color</FONT></TT> class, in which case you would create a <TT><FONT FACE="Courier">Color</FONT></TT> 
object using the desired levels of red, green, and blue.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>Why are graphics primitives not as important as images in regard to game graphics?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Because most games take advantage of the high level of realism afforded by images, and therefore rely heavily on images rather than primitive graphics types. However, there are exceptions to this rule; for 
example, vector games are made up entirely of lines, and some 3-D games are made up entirely of polygons.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>When exactly is the <TT><B><FONT FACE="Courier">paint</FONT></B></TT> method called, and why?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>The <TT><FONT FACE="Courier">paint</FONT></TT> method is called any time a portion of a component, such as the applet window, needs to be updated. For example, if a dialog pops up on top of the applet and then 
disappears, the applet needs to be updated, so <TT><FONT FACE="Courier">paint</FONT></TT> is called. You can force a call to <TT><FONT FACE="Courier">paint</FONT></TT> by calling the <TT><FONT FACE="Courier">repaint</FONT></TT> method; you did this very 
thing in the Tarantulas applet to update the status of the loading images.
</TD></TR>
</TABLE>
<P>
<H2><A NAME="Workshop"><B><FONT SIZE=5 COLOR=#FF0000>Workshop</FONT></B></A>
</H2>
<P>
The Workshop section provides questions and exercises to help
you get a better feel for the material you learned today. Try
to answer the questions and at least study the exercises before
moving on to tomorrow's lesson. You'll find the answers to the
questions in appendix A, &quot;Quiz Answers.&quot;
<H3><A NAME="Quiz"><B>Quiz</B></A></H3>
<OL>
<LI>What are the four components of a 32-bit Java color?
<LI>What is a graphics context?
<LI>What class provides information about fonts and enables you
to fine-tune the placement of text?
<LI>What is the purpose of the media tracker?
</OL>
<H3><A NAME="Exercises"><B>Exercises</B></A></H3>
<OL>
<LI>Study the Java Developer's Kit documentation and try out some
of the other graphics primitives not demonstrated in today's lesson.
<LI>Modify the Drawtext applet to draw a different string and
make sure the centering code works correctly.
<LI>Modify the Tarantulas applet to run without the media tracker
and notice the change in behavior.
</OL>
<P>
<HR WIDTH="100%"></P>

<CENTER><P><A HREF="ch4.htm"><IMG SRC="pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm"><IMG SRC="hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch6.htm"><IMG 
SRC="nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A></P></CENTER>

<P>
<HR WIDTH="100%"></P>

</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -