JAVA制作游戏⼊门教程
现在流⾏的游戏似乎都是⽤C或C++来开发的。在java平台上⼏乎没有很⼤型及可玩的流⾏游戏。由于java是个新⽣语⾔,他的许多特性还有待⼤家的发掘,但是我们不能否认Java在游戏编程⽅⾯的强⼤性。本⽂将带领⼤家⼀步⼀步学习编写Java游戏。最终打造属于⾃⼰的Java 游戏。
  在开始之前我们得确认你已经安装了Java JDK,并已经安装了浏览器软件如IE。本章是以Internet为开发对象,⼀步⼀步教⼤家认识Java的Thread、Applets….以及游戏编程要注意的⼀些⽅⽅⾯⾯并在每⼀⼩部分附上了相应的源代码以供⼤家参考,最后我们还会对我们的游戏程序进⾏指导性的提⽰。在⽂章中我们还穿插了很多建设性的问题,让读者参与到我们的开发中来。但是由于本章指在带领⼤家进⼊这个门槛,⼤部分知识并不会很详细说明,有兴趣的读者可查阅相关的资料补充。在开始之前我们还得确认你已经知道类,继承和java语⾔的⼀些基本属性了。
  基本applet
  Applets是⼀种Web浏览器上的⼩程序,由于applet对系统⽽⾔绝对安全,所以它做的事⽐aaplication有限,但是对于客户端的程序,applets仍然是个很强⼤的⼯具。为了浏览和运⾏⽅便,我们就以applet为开发对象。
  开发Applets程序,我们得继承Applet类,并覆写必要的函数,下⾯⼏个函数控制了Web页⾯上的applet⽣成与执⾏。
函数 作⽤
Init() 这个函数会被⾃动调⽤,执⾏applet的初始化动作—包括组件在版⾯上的分配,你⼀定得覆写它
Start() 每当浏览器显⽰applet内容时,都会调⽤它,让applet开启其正规⼯作(尤其是那些被stop()关闭的⼯作),调⽤init()之后也会调⽤这个函数
Stop() 每当浏览器不显⽰内容时,都会调⽤它。让applet关闭某些耗资源的⼯作,调⽤destory()之后也会调⽤这个函数
Destroy() 浏览器将applet⾃⽹页移除之际,便会调⽤它,以执⾏”applet不再被使⽤”应该做的最后释放资源等动作
Paint() 让你在Applet界⾯上进⾏相应的绘画动作,每次刷新时都会重画
  所有的applet⽂件源⽂件名和java应⽤程序⼀样都是.java为扩展名,编译后的执⾏⽂件扩展名为.class,由于在applet中已经没有了main()函数,它是和HTML⾃动集成,所以我们要执⾏applet,要
在HTML源⽂件中放⼊⼀特定的标签(tag),才能告诉⽹页如何装载并执⾏这个applet,这⾥有⼀点要注意,我们执⾏的⽹页必须能执⾏java程序。
  普通HTML 源码格式
<HTML>
<APPLET CODE="HelloWorld.class" WIDTH=300 HEIGHT=500>
</APPLET>
</HTML
  <applet code ="HelloWorld.class" width=300 height=500>这⾏即applet的执⾏处。
  applet 执⾏⽂档为 ="HelloWorld.class" 告诉⽹页”applet ”扩展⽂件为HelloWorld.class
  width 和 height 告诉浏览器这个显⽰的applet的⼤⼩
  有关标签(tag)的说明,⼤家可在⽹上到很多相关的说明⽂档。
  线程
  由于apllet,java应⽤程序的执⾏都和线程有关。我们来⼤概了解⼀下线程的概念。
  线程也称为轻型进程 (LWP)。每个线程只能在单个进程的作⽤域内活动、协作和数据交换,并且在计算资源⽅⾯⾮常廉价。线程需要操作系统的⽀持,因此不是所有的机器都提供线程。Java 编程语⾔,作为相当新的⼀种语⾔,已将线程⽀持与语⾔本⾝合为⼀体,这样就对线程提供了强健的⽀持。
  Thread 类是⼀个具体的类,即不是抽象类,该类封装了线程的⾏为。要创建⼀个线程,程序员必须创建⼀个从 Thread 类导出的新类。程序员必须覆盖 Thread 的 run() 函数来完成有⽤的⼯作。⽤户并不直接调⽤此函数;⽽是必须调⽤ Thread 的 start() 函数,该函数再调⽤ run()。
  但是使⽤Thread类实现线程,增加了程序的类层次,所以⼀般程序员都由另⼀个java线程接⼝Runnable接⼝来实现,Runnable接⼝只有⼀个函数run(),此函数必须由实现了此接⼝的类实现。
  线程中有⼏个重要的⽅法是我们得了解:
   Thread.start(): 启动⼀个线程
   Thread.stop(): 停⽌⼀个线程
   Thread.sleep(time in milliseconds): 暂停线程在⼀个等待时间内。
动画技术
  ⾃由降落动画
  了解了⼀些基本概念后,下⾯我们就开始我们的实质性的⼯作。我们设计⼀个球从屏幕顶上降落到屏幕下⾯,程序实现⽐较简单,但是这是游戏动画中不可少的⼀部分。在开始之前我们来看看我们的applet开始语句。
import java.awt.*;
import java.applet.*;
public class Ball
extends Applet implements Runnable
{
public void init() { }
public void start() { }
public void stop() { }
public void destroy() { }
public void run () { }
public void paint (Graphics g) { }
}
  在开始函数中我们要新建程序的主线程,并启动这个线程。⼀旦做好这些准备⼯作以后,当applet第⼀次被显⽰时,就会创建线程对象的⼀个实例,并把this对象作为建构⽅法的参数,之后就可以启动动画了
public void start ()
{
// 定义⼀个新的线程
Thread th = new Thread (this);
// 启动线程
th.start ();
}
  现在我们来看看线程的run⽅法,它在循环while(),中每隔20毫秒重画动画场景。sleep这个⽅法很重要,如果在run循环中没有这部分,圆的重画动作将执⾏得很快,其他⽅法将得不到有效执⾏,也即我们在屏幕上将看不到球的显⽰。
public void run ()
{
//
while (true)
{
// 重画applet画⾯
repaint();
try
{
// 暂停线程20毫秒
Thread.sleep (20);
}
catch (InterruptedException ex)
{
}
}
}
  我们接着读下去之前,有⼏个问题需要回答。你也许会问,浏览器调⽤Java⼩程序的start和stop⽅法吗? run ⽅法是如何被调⽤的?情况是这样的,当浏览器启动了⼀个内部线程时,就相应地启动了applet 的运⾏。当⽹页显⽰时,就启动了applet的start ⽅法。Start⽅法创建⼀个线程对象,并把applet⾃⾝传送给线程,以实现run⽅法。
  此时,两个线程在运⾏:由浏览器启动的初始线程,以及处理动画的线程。快速查看applet的start⽅法,可以知道它创建了线程,并启动了它。类似地,当⽹页被隐藏后,applet的stop⽅法就调⽤了线程的stop⽅法。
  注意:在Applets和Threads中的 start/stop⼦程序
  在Applet 和Thread 两个类中都有start和stop⽅法,但它们的功能不同。⼀旦Applet 显⽰时,就调⽤applet的start⽅法,⼀旦applet 隐藏时,就调⽤applet的stop ⽅法。相反,线程的start⽅法将调⽤run⽅法,线程的stop⽅法将停⽌正在执⾏的线程。
public void paint(Graphics g);
  paint() ⽅法所传⼊的参数—— java.awt.Graphics 对象将是⼀个经裁剪的相关显⽰区的图像代表(⽽不会是整个显⽰区)。我们对圆球图形元素的绘制就是在通过重写 paint()⽅法,在其中对传⼊的Graphics 对象g进⾏操作完成的。
  当我们应⽤程序的逻辑要对系统界⾯进⾏更新时,调⽤ repaint() ⽅法来通知AWT线程进⾏刷新操作。repaint() ⽅法实际会让 AWT 线程去调⽤另外⼀个⽅法,update。update⽅法在默认情况下会做两件事,⼀是清除当前区域内容,⼆是调⽤其 paint()⽅法完成实际绘制⼯作。paint、repaint、update 三个⽅法关系如图所⽰:
  但是如何让我们的圆运动呢?这⾥我们利⽤函数Graphics 类的fillOval函数来设置了圆的起始位置x,y。现在我们只要在线程run⽅法中每单位时间增⼤y的值,线程将在每⼀个单位时间内重画圆的位置。每单位时间y值越⼤,下降的速度就会越快。在屏幕上我们就将看到这个圆球做⾃由降落运动。 如下代码所⽰:
while (true)
{
// 设置动画移动速度
y +=1;
}
public void paint (Graphics g)
{
//设置球的颜⾊
g.setColor (Color.blue);
// 从x,y位置处画⼀个实⼼的圆
g.fillOval (x , y, 2 * r, 2 * r);
}
  在这之前我们需要在开始处设置⼀些变量,定义好x,y的默认位置值。r 在此处是我们画的圆的半径⼤⼩。
int x = 100;
int y = 20;
int r = 10;
  我们的⾃由降落的动画就完了。是不是很简单,如果还有地⽅不明⽩,⼤家可在此处下载完整的代码及应⽤程序。看看真实的演⽰效果和代码。下⾯每⼀部分我们也将在最后附上相应的源代码及应⽤程序下载。如果⼤家有兴趣,可改变y的值,及x的值,你会得到不同的下降效果。
双缓冲,消除闪烁
  ⼤家可能注意到了上⾯例⼦中的我们下降的圆看起来不是很清晰,带着很严重的闪烁。这种现象在写游戏程序中是普遍存在的现象。这是由于我们的repaint()函数导致的结果,由于它在调⽤paint()函数前会⾃动清除屏幕,所以在⼀个毫秒内我们会看到⼀个空⽩的屏幕,在快速的变换操作中就出现了闪烁现象。
  解决这种闪烁现象有⼏种⽅法,下⾯是两种⽅法的列举说明,其他的⽅式⼤家可以⾃⼰尝试。
  第⼀种:我们始终不清除屏幕显⽰,但是这个⽅法会带来个附作⽤,我们下降的圆不在是⼀个圆了,⽽是⼀条直线,因为它的下降过程中没有了断点,保留了所有的圆球的影象。我们只要在Ball.java内加上如下代码update(Graphics g) {paint(g)},你就会看到⼀条很长的线拉出来。有兴趣的朋友可以试试。
  第⼆种:使⽤双缓冲机制(Double buffering)
  现在⼤部分的游戏都是采⽤双缓冲机制来解决屏幕的闪烁现象,我们就以此为例来进⾏说明,有关缓冲区及相关缓冲机制的概念,⼤家可参考附录的缓冲说明。
  ⽽我们的程序中简单的说就是在显⽰我们想要的图画之前,把所有的图画先在后台绘制好并存放到相应的图像变量中去。当需要显⽰时直接复制到前台屏幕就可以了。
  具体实现:
   1.⾸先我们⽤createImage⽅法新建⼀后台图像类变量
   2.然后使⽤getGraphics()⽅法得到当前图像的图形关联
   3.在后台处理所有相关的处理,如清除屏幕,后台绘画等等
  当完成所有的后台⼯作后,复制已经绘制好的图像到前台,并覆盖前台的存在图像。这样我们的所有操作都是在后台前⾏,在屏幕显⽰新的图像前,这些内容都已经存在于后台了。所以你也将在任何时刻都看不到空屏幕的存在。也即代表闪烁消除了。
  下⾯我们来看看相关的代码说明:
  在开始之前我们得先在程序的开始部分声明两个实例变量⽤来存储后台图画。如下:
private Image bgImage;
private Graphics bg;
  然后我们利⽤update()⽅法来实现双缓冲机制。
  Update()⽅法要实现下⾯三个步骤:
   1.清除屏幕上的组件
简单的java游戏代码   2.设置相关联组件的前景⾊
   3.调⽤paint⽅法重画屏幕
public void update (Graphics g)
{
// 初始化buffer
if (bgImage == null)
{

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。