📄 java游戏编程初步--英雄会之强强联手.htm
字号:
paint()方法完成实际绘制工作。paint、repaint、update 三个方法关系如图所示: <BR><BR><IMG
onerror="this.src='http://www.yesky.com/image20010518/49722.gif';" hspace=3
src="Java游戏编程初步--英雄会之强强联手.files/49722.gif" align=center vspace=1
border=1><BR><BR></P>
<P></P>
<P></P>
<P> 但是如何让我们的圆运动呢?这里我们利用函数Graphics
类的fillOval函数来设置了圆的起始位置x,y。现在我们只要在线程run方法中每单位时间增大y的值,线程将在每一个单位时间内重画圆的位置。每单位时间y值越大,下降的速度就会越快。在屏幕上我们就将看到这个圆球做自由降落运动。
如下代码所示:</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>while (true) </P>
<P>{ </P>
<P>// 设置动画移动速度 </P>
<P>y +=1;<BR>}</P>
<P>public void paint (Graphics g)<BR>{</P>
<P>//设置球的颜色<BR>g.setColor (Color.blue);</P>
<P>// 从x,y位置处画一个实心的圆<BR>g.fillOval (x , y, 2 * r, 2 * r);</P>
<P>}</P></TD></TR></TBODY></TABLE></P>
<P> 在这之前我们需要在开始处设置一些变量,定义好x,y的默认位置值。r 在此处是我们画的圆的半径大小。</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>int x = 100;<BR>int y = 20;<BR>int r = 10; </TD></TR></TBODY></TABLE></P>
<P> 我们的自由降落的动画就完了。是不是很简单,如果还有地方不明白,大家可在此处下载完整的代码及应用程序。看看真实的演示效果和代码。下面每一部分我们也将在最后附上相应的源代码及应用程序下载。如果大家有兴趣,可改变y的值,及x的值,你会得到不同的下降效果。</P>
<P><STRONG>双缓冲,消除闪烁</STRONG> </P>
<P></P>
<P> 大家可能注意到了上面例子中的我们下降的圆看起来不是很清晰,带着很严重的闪烁。这种现象在写游戏程序中是普遍存在的现象。这是由于我们的repaint()函数导致的结果,由于它在调用paint()函数前会自动清除屏幕,所以在一个毫秒内我们会看到一个空白的屏幕,在快速的变换操作中就出现了闪烁现象。</P>
<P> 解决这种闪烁现象有几种方法,下面是两种方法的列举说明,其他的方式大家可以自己尝试。</P>
<P> 第一种:我们始终不清除屏幕显示,但是这个方法会带来个附作用,我们下降的圆不在是一个圆了,而是一条直线,因为它的下降过程中没有了断点,保留了所有的圆球的影象。我们只要在Ball.java内加上如下代码update(Graphics
g) {paint(g)},你就会看到一条很长的线拉出来。有兴趣的朋友可以试试。</P>
<P> 第二种:使用双缓冲机制(Double buffering)</P>
<P> 现在大部分的游戏都是采用双缓冲机制来解决屏幕的闪烁现象,我们就以此为例来进行说明,有关缓冲区及相关缓冲机制的概念,大家可参考附录的缓冲说明。</P>
<P> 而我们的程序中简单的说就是在显示我们想要的图画之前,把所有的图画先在后台绘制好并存放到相应的图像变量中去。当需要显示时直接复制到前台屏幕就可以了。</P>
<P> 具体实现:</P>
<P> 1.首先我们用createImage方法新建一后台图像类变量</P>
<P> 2.然后使用getGraphics()方法得到当前图像的图形关联</P>
<P> 3.在后台处理所有相关的处理,如清除屏幕,后台绘画等等</P>
<P> 当完成所有的后台工作后,复制已经绘制好的图像到前台,并覆盖前台的存在图像。这样我们的所有操作都是在后台前行,在屏幕显示新的图像前,这些内容都已经存在于后台了。所以你也将在任何时刻都看不到空屏幕的存在。也即代表闪烁消除了。</P>
<P> 下面我们来看看相关的代码说明: </P>
<P> 在开始之前我们得先在程序的开始部分声明两个实例变量用来存储后台图画。如下:</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>private Image bgImage;<BR>private Graphics bg;
</TD></TR></TBODY></TABLE></P>
<P> 然后我们利用update()方法来实现双缓冲机制。</P>
<P> Update()方法要实现下面三个步骤:</P>
<P> 1.清除屏幕上的组件</P>
<P> 2.设置相关联组件的前景色</P>
<P> 3.调用paint方法重画屏幕</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>public void update (Graphics g)<BR>{</P>
<P>// 初始化buffer<BR>if (bgImage == null)<BR>{</P>
<P>bgImage = createImage (this.getSize().width,
this.getSize().height);<BR>bg = bgImage.getGraphics ();</P>
<P>}</P>
<P>// 后台清屏,即设置圆球组件和后台一样的颜色,大小<BR>bg.setColor (getBackground
());<BR>bg.fillRect (0, 0, this.getSize().width,
this.getSize().height);</P>
<P>// 绘制相应的元素组件<BR>bg.setColor (getForeground());<BR>paint (bg);</P>
<P>// 在屏幕上重画已经绘制好的圆<BR>g.drawImage (bgImage, 0, 0, this);</P>
<P>}</P></TD></TR></TBODY></TABLE></P>
<P> 此处g 为屏幕图形,bg为g的后台关联。而bgimage包含了bg图形。请于此处来看看我们的源代码例子及演示效果。</P>
<P></P>
<P> <B>改变运动方向</B></P>
<P> 我们已经解决了动画的两个很重要的问题,移动动画和闪烁消除。但是我们很快会发现一个问题,球从屏幕顶上落下来后,就不见了。这可不是我们所需要的。我们要的是一个生动的画面。如何让我们的球不穿过屏幕而始终在屏幕上活动呢?在开始之前,我建议大家自己想办法解决,如果你能自己处理好了。你的水平将会有一个很大的提高。如果没有想出好办法,没关系,下面我们将很详细的说明球的方向改变的技术。</P>
<P> 不知道大家注意了没有,在上面我们说到球的移动时,我们是通过增加y的值,让线程重画新的圆位置和图形。如果改变y的值的大小球的下降速度也会改变。不错,这就是我们的解决方法
,我们只要用一个变量来存储这个速度的大小而不用固定的值。在线程执行也即run方法处我们用代码改变速度的方向,球的方向也会改变。即设置这个变量”speed”为”-1”。当然在设置值前我们要进行判断,你是想让球穿过屏幕从别一边开始显示,还是来回反弹呢!如果想来回反弹,我们只要不让球的半径值超过applet屏幕显示区域就可以了。此处我们用r/2来表示球的半径。</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>//反弹下落球<BR>if (y > appletsize_y – r/2)<BR>{</P>
<P>// 改变方向<BR>x_speed = -1;</P>
<P>}<BR>// 反弹上升球<BR>else if ( < r/2)<BR>{</P>
<P>// 改变方向<BR>x_speed = +1;</P>
<P>}</P></TD></TR></TBODY></TABLE></P>
<P> 至于如何让球穿过从屏幕顶上重新下降,我们在此没有说明,也不会说明了。留给大家自己去想想,已经很简单了。在下面我们附上了两种方式的源代码和执行文件。如果大家运行程序,大家可能会发现,我们的球的大小和速度有一些改变。这里是为了更好的反应演示效果。</P>
<P><STRONG>多媒体</STRONG> </P>
<P></P>
<P> <B>使用多媒体声音</B></P>
<P> 多媒体功能在游戏中是必不少的一部分,优美的音乐,漂亮的界面往往是一个成功游戏必需具备的条件。</P>
<P> 在开始之前我们先了解一下主要的小型声音文件类型:<BR><BR> AU -
(扩展名为AU或SND)适用于短的声音文件,为Solaris和下一代机器的通用文件格式,也是JAVA平台的标准的音频格式。AU类型文件使用的三种典型音频格式为:
8位μ-law类型(通常采样频率为8kHz), 8位线性类型,以及16位线性类型。</P>
<P><BR> WAV - (扩展名为WAV)由 Microsoft和 IBM共同开发,对WAV的支持已经被加进Windows 95并且被延伸到Windows
98. WAV文件能存储各种格式包括μ-law,a-law和 PCM (线性)数据。他们几乎能被所有支持声音的Windows应用程序播放。</P>
<P> AIFF - (扩展名为AIF或IEF)音频互换文件格式是为Macintosh计算机和Silicon Graphics
(SGI)计算机所共用的标准音频文件格式。AIFF和 AIFF-C几乎是相同的,除了后者支持例如μ-law和 IMA ADPCM类型的压缩。</P>
<P> MIDI - (扩展名为MID)乐器数字接口MIDI是为音乐制造业所认可的标准,主要用于控制诸如合成器和声卡之类的设备。</P>
<P> 在JDK1.0上,java只支持*.au格式的声音文件,但是java2的API以及声音包提供了很强大的对声音技术的支持。而此部分为了让大家快速掌握游戏编程的基本知识,我们仅使用了AudioClip接口类来实现播放"*.wav"。如果大家有兴趣可参考sun
java网站的声音sapmle,上面提供了完备的实例和教程说明。</P>
<P> 使用AudioClip接口比较简单,我们只要实例对象,加载声音文件后,再在任何地方播放即可。恢复和播放声音最简单的方法是通过Applet类的play()方法。</P>
<P> AudioClip接口</P>
<P> 1.播放 play<BR> 2.循环 loop<BR> 3.停止 stop<BR><BR> 启动和停止声音文件,或循环播放,你必须用
applet的 getAudioClip方法把它装载进入
AudioClip对象,getAudioClip方法要用一个或两个参数,当作播放的指示。第一个或唯一的一个参数是
URL参数,用来指示声音文件的位置,第二参数是文件夹路径指针。</P>
<P> 下列代码行举例说明加载声音文件进入剪贴对象: 下面的"gun.wav"是指当前目录下的声音文件。我们也可用*.au格式的文件代替。</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>AudioClip co = getAudioClip(getCodeBase(), "gun.wav");
</TD></TR></TBODY></TABLE></P>
<P> getAudioClip()方法仅仅能被applt内调用。随着JAVA2的引入,应用程序也能用Applet类的newAudioClip方法装入声音文件。前一例子可以改写如下以用于Java应用程序:</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>AudioClip co = newAudioClip(“gun.wav”)</TD></TR></TBODY></TABLE></P>
<P> 我们现在可在任何地方使用方法play()播放我们的声音了。play()一旦被调用立刻开始恢复和播放声音。但这有一点要注意:如果声音文件不能被查找,将不会有出错信息,仅仅是沉默。<BR>源代码及应用程序请于此处下载.</P>
<P></P>
<P> <B> 图片处理技术</B></P>
<P> 图片的处理和声音的处理在一样简单。设置图片变量,得到图形,最后绘制图形。我们就直接从代码来分析。在此我们绘制一幅applet的背景图。开始绘制前,我们先要声明图形变量,用来存放图形文件。</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>Image backImage; </P>
<P>// 加载图片文件<BR>backImgage = getImage (getCodeBase (),
"black.gif");</P></TD></TR></TBODY></TABLE></P>
<P> 下面在我们的paint()方法中利用函数drawImage绘制我们图形。</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>g.drawImage (backImage, 0, 0, this);</TD></TR></TBODY></TABLE></P>
<P> DrawImage参数中的blackImage即我们得到的图形,而后面的0,0分别代表图形的x坐标和y坐标.this:为图形代表的类,这里指的即picture类。在这里建议大家使用*.gif格式的图片文件。因为如果是internet网上,文件的大小也决定了你的applet加载时的快慢,没有人很愿意等很长时间来玩你的游戏,即使你的游戏比较出色。源代码及演示程序下载.</P>
<P> 大家在玩游戏时是不是见过人物图像行走?动物来回跑动的动画?这些都是基于图形技术来实现的。我们只要把上面的代码稍微修改,用数组变量来存储我们得到的图形文件组,再利用drawImage()方法播放出来就可实现动画图片的播放.</P>
<P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>Image[] backImage; </P>
<P>// 加载图片文件</P>
<P>for (int i=4,i<backImage.length,i++)</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -