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

📄 ch12.htm

📁 Java游戏开发
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void init() {<BR>
&nbsp;&nbsp;// Load and track the images<BR>
&nbsp;&nbsp;tracker = new MediaTracker(this);<BR>
&nbsp;&nbsp;Eyes.initResources(this, tracker, 0);<BR>
<BR>
&nbsp;&nbsp;// Load the audio clips<BR>
&nbsp;&nbsp;clip[0] = getAudioClip(getCodeBase(), &quot;Res/Crow.au&quot;);
<BR>
&nbsp;&nbsp;clip[1] = getAudioClip(getCodeBase(), &quot;Res/Hyena.au&quot;);
<BR>
&nbsp;&nbsp;clip[2] = getAudioClip(getCodeBase(), &quot;Res/Monkey.au&quot;);
<BR>
&nbsp;&nbsp;clip[3] = getAudioClip(getCodeBase(), &quot;Res/Tiger.au&quot;);
<BR>
&nbsp;&nbsp;clip[4] = getAudioClip(getCodeBase(), &quot;Res/Wolf.au&quot;);
<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
After the audio clips are initialized in <TT><FONT FACE="Courier">init</FONT></TT>
using <TT><FONT FACE="Courier">getAudioClip</FONT></TT>, they
are ready to be played.
<P>
The eyes you see in the applet are implemented as sprites, which
you'll learn about later in today's lesson. These sprites are
created in the <TT><FONT FACE="Courier">run</FONT></TT> method,
which also creates and initializes the sprite list. Listing 12.2
contains the source code for the run method.
<HR>
<BLOCKQUOTE>
<B>Listing 12.2. The </B><TT><B><FONT FACE="Courier">WildAnimals</FONT></B></TT><B>
class's </B><TT><B><FONT FACE="Courier">run</FONT></B></TT><B>
method.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public void run() {<BR>
&nbsp;&nbsp;try {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;tracker.waitForID(0);<BR>
&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;catch (InterruptedException e) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;// Create and add the sprites<BR>
&nbsp;&nbsp;sv = new SpriteVector(new ColorBackground(this, Color.black));
<BR>
&nbsp;&nbsp;for (int i = 0; i &lt; 8; i++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;sv.add(new Eyes(this, new Point(Math.abs(rand.nextInt()
%<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size().width), Math.abs(rand.nextInt()
% size().width)),<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i % 2, Math.abs(rand.nextInt()
% 200)));<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;// Update everything<BR>
&nbsp;&nbsp;long t = System.currentTimeMillis();<BR>
&nbsp;&nbsp;while (Thread.currentThread() == animate) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;// Update the animations<BR>
&nbsp;&nbsp;&nbsp;&nbsp;sv.update();<BR>
&nbsp;&nbsp;&nbsp;&nbsp;repaint();<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;// Play an animal sound<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if ((rand.nextInt() % 15) == 0)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clip[Math.abs(rand.nextInt()
% 5)].play();<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;try {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t += delay;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(Math.max(0, t
- System.currentTimeMillis()));<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;catch (InterruptedException e) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Beyond creating the sprites for WildAnimals, the <TT><FONT FACE="Courier">run</FONT></TT>
method also handles playing the random animal sounds. This is
carried out by using the <TT><FONT FACE="Courier">nextInt</FONT></TT>
method of the <TT><FONT FACE="Courier">Random</FONT></TT> object
to get a random number between <TT><FONT FACE="Courier">-15</FONT></TT>
and <TT><FONT FACE="Courier">15</FONT></TT>. This random number
is checked to see whether it is equal to <TT><FONT FACE="Courier">0</FONT></TT>,
in which case a sound is played. This creates a 1-in-31 chance
of a sound being played each time through the update loop. There
is no magic surrounding the range of the random numbers; it was
determined by trying out different values. When a sound is to
be played, <TT><FONT FACE="Courier">nextInt</FONT></TT> is used
again to randomly select which sound to play. That's all there
is to playing the random sounds.
<P>
That covers all the unique aspects of the <TT><FONT FACE="Courier">WildAnimals</FONT></TT>
class. However, you still haven't seen how the eye sprites are
implemented. The <TT><FONT FACE="Courier">Eye</FONT></TT> class
implements a blinking eye sprite that can be either small or large.
It uses a static two-dimensional array of <TT><FONT FACE="Courier">Image</FONT></TT>
objects to store the frame animations for the blinking eye in
each size. Like all derived <TT><FONT FACE="Courier">Sprite</FONT></TT>
classes you've seen, the images are initialized in the <TT><FONT FACE="Courier">initResources</FONT></TT>
method:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public static void initResources(Applet
app, MediaTracker tracker, int id) {<BR>
&nbsp;&nbsp;for (int i = 0; i &lt; 4; i++) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;image[0][i] = app.getImage(app.getCodeBase(),
&quot;Res/SmEye&quot; + i + &quot;.gif&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;tracker.addImage(image[0][i], id);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;image[1][i] = app.getImage(app.getCodeBase(),
&quot;Res/LgEye&quot; + i + &quot;.gif&quot;);<BR>
&nbsp;&nbsp;&nbsp;&nbsp;tracker.addImage(image[1][i], id);<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
Figure 12.2 shows what the animation images for the eye look like.
<P>
<A HREF="f12-2.gif" ><B>Figure 12.2 : </B><I>The images used by the Eye class.</I></A>
<P>
The <TT><FONT FACE="Courier">Eye</FONT></TT> class contains two
member variables, <TT><FONT FACE="Courier">blinkDelay</FONT></TT>
and <TT><FONT FACE="Courier">blinkTrigger</FONT></TT>, for managing
the rate at which it blinks:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">protected int blinkDelay,<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;blinkTrigger;</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">blinkDelay</FONT></TT> determines how
long the eye waits until it blinks again, and <TT><FONT FACE="Courier">blinkTrigger</FONT></TT>
is the counter used to carry out the wait. They are both initialized
to the blink delay parameter passed into the constructor of <TT><FONT FACE="Courier">Eye</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">public Eyes(Component comp, Point pos,
int i, int bd) {<BR>
&nbsp;&nbsp;super(comp, image[i], 0, 1, 2, pos, new Point(0, 0),
0, Sprite.BA_WRAP);<BR>
&nbsp;&nbsp;blinkTrigger = blinkDelay = bd;<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
The only overridden method in <TT><FONT FACE="Courier">Eye</FONT></TT>
is <TT><FONT FACE="Courier">incFrame</FONT></TT>, which handles
incrementing the animation frame:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">protected void incFrame() {<BR>
&nbsp;&nbsp;if ((frameDelay &gt; 0) &amp;&amp; (--frameTrigger
&lt;= 0) &amp;&amp;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;(--blinkTrigger &lt;= 0)) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;// Reset the frame trigger<BR>
&nbsp;&nbsp;&nbsp;&nbsp;frameTrigger = frameDelay;<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;// Increment the frame<BR>
&nbsp;&nbsp;&nbsp;&nbsp;frame += frameInc;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;if (frame &gt;= 4) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame = 3;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frameInc = -1;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;&nbsp;&nbsp;else if (frame &lt;= 0) {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame = 0;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frameInc = 1;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;blinkTrigger = blinkDelay;
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;}<BR>
&nbsp;&nbsp;}<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
It is necessary to override <TT><FONT FACE="Courier">incFrame</FONT></TT>
so that you can add the blinking functionality. This is done by
decrementing <TT><FONT FACE="Courier">blinkTrigger</FONT></TT>
and seeing whether it has reached zero. If so, it's time to blink!
Notice that the blink is still dependent on the frame delay, which
is very important. This is important because you don't want an
added feature, such as blinking, to interrupt a basic function
of the sprite, such as the frame delay.
<P>
The <TT><FONT FACE="Courier">incFrame</FONT></TT> method does
one other thing worth pointing out. If you think about it, a blink
must consist of going through the frame animations forward (to
close the eye) and then backward (to open the eye again). The
standard implementation of <TT><FONT FACE="Courier">incFrame</FONT></TT>
in <TT><FONT FACE="Courier">Sprite</FONT></TT>, which you saw
last week, always goes in a constant direction-that is, forward
or backward as determined by the sign of the <TT><FONT FACE="Courier">frameInc</FONT></TT>
member variable. In <TT><FONT FACE="Courier">Eye</FONT></TT>'s
<TT><FONT FACE="Courier">incFrame</FONT></TT>, you want the frame
animations to go forward and then backward without having to fool
with <TT><FONT FACE="Courier">frameInc</FONT></TT>. The <TT><FONT FACE="Courier">if-else</FONT></TT>
clause in <TT><FONT FACE="Courier">incFrame</FONT></TT> solves
this problem beautifully.
<P>
That finishes up the WildAnimals sample applet. It proves that
sound in Java is not only fun, but it is also easy to implement!
<H2><A NAME="Summary"><B><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></B></A>
</H2>
<P>
Today you learned all about how sound is used in Java. You started
off by learning how Java supports sound through the <TT><FONT FACE="Courier">AudioClip</FONT></TT>
class and a few methods in the <TT><FONT FACE="Courier">Applet</FONT></TT>
class. You then progressed to building a complete applet using
sound to create somewhat of a virtual wilderness at night. It
showed you how easy it is to add sound to Java applets. It also
was a good example of how the sprite classes can be used in new
and creative ways.
<P>
You now have all the background necessary to add sound to any
Java applet you write, including games. Speaking of games, it's
almost time for you to write another one. But that will have to
wait until tomorrow!
<H2><A NAME="QA"><B><FONT SIZE=5 COLOR=#FF0000>Q&amp;A</FONT></B></A>
<BR>
</H2>

<TABLE>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>Do I have to do anything special to mix sounds in Java?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>No. The Java sound support automatically handles mixing sounds that are being played at the same time. This might seem trivial, but it is actually a very nice feature.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>How do I play MIDI music in Java?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Right now, you can't. The current version of Java (1.0) doesn't provide any support for MIDI, but hopefully it will appear in a later release. Sun has promised more extensive multimedia features in the near 
future. For now, you can record music as an audio clip and then loop it; more on this tomorrow.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>In the WildAnimals applet, how can I make the eyes blink faster?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Decrease the blink delay parameter passed into the constructor. More specifically, decrease the number used in the modulus operation after the call to <TT><FONT FACE="Courier">nextInt</FONT></TT>.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>How can I add more animals to the WildAnimals applet?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>The first step is to record or find more animal sounds and copy them to the <TT><FONT FACE="Courier">Res</FONT></TT> directory. You then need to increase the size of the <TT><FONT FACE="Courier">clip</FONT></TT> 
array of <TT><FONT FACE="Courier">AudioClip</FONT></TT> objects and load the new sounds in <TT><FONT FACE="Courier">init</FONT></TT> using the <TT><FONT FACE="Courier">getAudioClip</FONT></TT> method. Finally, in the call to <TT><FONT 
FACE="Courier">play</FONT></TT>  in the <TT><FONT FACE="Courier">run</FONT></TT> method, increase the number used to index into the <TT><FONT FACE="Courier">clip</FONT></TT> array (it is currently <TT><FONT FACE="Courier">5</FONT></TT>).
</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 think about 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>Are any other sound formats supported by Java besides the
AU format?
<LI>Why should you use the <TT><FONT FACE="Courier">getCodeBase</FONT></TT>
method to get a base URL for a sound rather than the <TT><FONT FACE="Courier">getDocumentBase</FONT></TT>
method?
<LI>When would you need to use an <TT><FONT FACE="Courier">AudioClip</FONT></TT>
object rather than the <TT><FONT FACE="Courier">play</FONT></TT>
method in the <TT><FONT FACE="Courier">Applet</FONT></TT> class?
<LI>How do you stop a looped sound after it has started playing?
</OL>
<H3><A NAME="Exercises"><B>Exercises</B></A></H3>
<OL>
<LI>Draw or find an image containing some animals and use it as
the background. Hint: Use the <TT><FONT FACE="Courier">ImageBackground</FONT></TT>
class instead of the <TT><FONT FACE="Courier">ColorBackground</FONT></TT>
class when creating the <TT><FONT FACE="Courier">SpriteVector</FONT></TT>.
<LI>Try out different values for the blink delay of the eyes.
<LI>Add more animal sounds.
<LI>Modify the <TT><FONT FACE="Courier">Eye</FONT></TT> class
so that the eyes look like the animals are walking around.
</OL>
<P>
<HR WIDTH="100%"></P>

<CENTER><P><A HREF="ch11.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="ch13.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 + -