桌面弹球是游戏中常见的游戏,从以前的掌上游戏机到如今的手机游戏,都是一个十分经典的游戏。玩家控制一个可以左右移动的挡板去改变运动中小球的移动方向,目的是用小球消除游戏屏幕中的所有砖块,不同颜色的砖块有着不一样的效果,例如:黄色砖块五魔法效果、粉色的砖块弹球可以穿越,咖啡色的砖块可以使小球加速,绿色的砖块可以使小球发色子弹等等。本节主要介绍如何实现一个简单的弹球游戏,让读者了解“动画”的实现原理。
其实所谓的动画就是一张一张图片的不断演示,让人看上去有动感,最后使用Java中的双缓冲去重复绘图,防止游戏的屏幕闪烁,我开发的桌面弹球游戏的效果如图所示:
<!--EndFragment-->
一、动画原理
简单地来说,动画是利用人的视觉暂留的生理特性,实现出来的一种假象,只要每隔一段时间(这个时间少于人的视频暂留时间)就重新绘制一幅状态改变的图片,就能造成这种“动”的假象。我们在程序中不断的进行擦除,然后不断的画出新的图片,对程序来讲,只需要在短时间内进行多次的绘画,并且每次绘画都需要改变绘画的相关值,就可以达到“动画”的效果。
二、弹球游戏开发
在做游戏前,得先实现一个主界面,然后往界面上添加各种物件以及图片。在这个游戏的开发中,我们有6个类(BallUI 主界面,Ball 弹球类,MapUI 地图类,Stick 挡板类,Shot 子弹类,Magic 魔法类),这些类实现不同的效果,使弹球游戏玩的更有意思。在下面将介绍主要的几个类
三、Ball弹球类
这个类是一个线程,当游戏启动的时候,界面中会出现一个小球,点开始按钮后,线程启动,小球开始运动,其中小球的速度是线程的sleep时间和小球在界面中位置的改变这两个因素决定的。实现小球的动其实很简单,看下代码就知道:
//先擦除,把颜色设为背景色(黑色)
g.setColor(Color.BLACK);
g.fillRect(x0, y0, 15, 15);
//再在下一刻画出小球(白色),假设坐标都加1
g.setColor(Color.WHITE);
g.fillRect(x0+1, y0+1, 15, 15);
然后这个处理很多主要的操作:
1.游戏输赢的操作。当小球移动时,用挡板来实现小球的反弹,但当没接住的时候,小球会往下掉,这时就会判游戏结束。如图:
<!--EndFragment-->
判断游戏是否胜利,只有把所有的砖块都打掉,这时弹出对话框,显示你已经胜利,如图:
1.这个类最主要的任务是来判断小球与砖块的碰撞、与墙壁的碰撞以及与挡板的碰撞。当碰撞时,用不同的方法来处理小球下一时刻的运动,也就是说,当小球碰到挡板时要反弹,碰到墙壁时也要反弹,这些都还好处理;但是当小球碰到不同砖块时候,要产生不同的效果,这是游戏比较难的地方,不同的效果调用的方法也就不同。
四、MapUI地图类
这个类是来创建地图,在文档存储了一份文件,是对这个地图的解释,当调用这份文件的时候,地图自动会在界面中创建。
由于涉及到文件,那么不可避免的要使用文件输入流,创建文件输入流的对象去读取文件,把读到的内容用一个char二维数组存储起来,然后再主界面中调用这个类,实现二维数组转换成地图的方法,这样地图就形成了。
五、主界面BallUI
这个类是去调用所用的类,从而实现弹球游戏。启动不同的线程,使小球的运动形式不一样以及游戏的可玩性得到提高。在调用线程后,当游戏结束时,记得关闭所有线程,不然浪费CPU资源。
最后我想谈的是双缓冲处理屏幕的闪烁问题,在游戏的开发中,让我头疼的就是屏幕的闪烁,不仅看的不爽,且对眼睛的伤害也是极大的。这里我们有三个主要的实物(小球、砖块、挡板),我们分别对这些物体进行重绘,从而解决闪屏的问题。看如下代码:
public void paint(Graphics g){
// 在重绘函数中实现双缓冲机制
offSreenImage =this.createImage(500,490);
// 获得截取图片的画布
Graphics gImage=offSreenImage.getGraphics();
// System.out.println(gImage.getColor());
// 获取画布的底色并且使用这种颜色填充画布,如果没有填充效果的画,则会出现拖动的效果
gImage.setColor(gImage.getColor());
// 有清楚上一步图像的功能,
gImage.fillRect(0, 0, 500, 490);
// 调用父类的重绘方法,传入的是截取图片上的画布,防止再从最底层来重绘
super.paint(gImage);
//重绘地图,也即是重绘砖块
for(int i=0;i<chars.length;i++){
for(int j=0;j<chars[i].length;j++){
if(chars[i][j]!=0){
char c = chars[i][j];
if(c!=' '){
String path = "images/"+c+".jpg";
//根据路径构造图片对象
ImageIcon icon = MapUI.createImageIcon(path);
gImage.drawImage(icon.getImage(), 35*j, 15*i, null);
}
}
}
}
//挡板的重绘
Stick stick =new Stick();
int x=Stick.x0;
gImage.setColor(Color.red);
stick.createStick(gImage, x-2-1,460-2-2-1-2-2, 100, 15);
//小球的重绘
Ball ball=new Ball();
ball.createBall(gImage, Ball.x0, Ball.y0);
// 将接下来的图片加载到窗体画布上去,才能得到每次画的效果
g.drawImage(offSreenImage, 0, 0, null);
}
最后,由于本人知识的不足,游戏中还存在很多问题,且游戏的效果也不是特别的好,游戏的可玩性不高。但总体来说,这次游戏的开发让我的编程能力得到提升,同时也能处理一些简单的问题。
<!--EndFragment--><!--EndFragment-->
<!--EndFragment-->