一、功能描述:
这个坦克大战实现了我方坦克(玩家控制)以及敌方坦克(程序随机控制)的对战,当击毁所有敌方坦克之后玩家获胜,当我方坦克生命值被消耗完毕后失败。游戏中,敌方坦克分为两类:一是快速的黄色坦克,二是有两点生命值的慢速坦克。玩家坦克的生命值一共为三。其中键盘的w、s、a、d分别控制坦克上下左右四个方向的移动,点击鼠标之后为发射子弹。其中要注意的是,当子弹击中对方坦克或碰到障碍物消失之后才能发射下一个子弹。游戏过程中还会随机出现加速道具,获取之后玩家坦克的速度提升为初始的两倍。下面便是游戏的图片展示 :
游戏界面
右下角的生命值:
出现的加速道具:
游戏结束:
二,技术分析:
在坦克大战的编写中,技术上不同于前面项目主要用到了两点,一个是多线程的应用,另一个是界面加载图形的处理,即双缓冲技术。下面来进行分析:
(一)多线程的处理:
在这个游戏中,最为核心的技术便是多线程的应用,我方坦克,敌方的十辆坦克、我方发射的子弹以及敌方坦克发射的子弹均为独立的线程,因此,在线程的控制上有了一定的难度,由于在弹球游戏的开发中,计时线程与小球线程同时受一个主类里面变量的控制并在某个时候需同时对其进行修改,因此,会出现抢占CPU时间片的情况从而使得程序的运行结果出现意想不到的结果。基于这个经验,我在这次的设计中将控制变量设置在某一个线程中,并且修改的动作只发生在一个线程内,这样的话便比较有效的解决类上述的问题。当然,有的同志也许会说用线程同步synchronized来控制,但是这个的话会使的程序的复杂度更加加大,以至于你对每一个控制细节牢记于心。
(二)双缓冲技术:
当框设计好之后,我信心满满的加上了仰慕已久的图片,结果却令我抓狂,因为屏幕上已经在不停的闪烁了,找到高手求教之后才明白这里涉及到双缓冲的问题,关于双缓冲的详细理解将在以后的技术博客中谈及,这里的话简单介绍一下,就是通过重写窗体的upData()方法,将窗体的写入缓冲区内,具体的相关代码如下 // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示
- public void update(Graphics g) {
- if (offScreenImage == null) { offScreenImage = this.createImage(WIDTH, HEIGHT); }
- Graphics gImage = offScreenImage.getGraphics();
- Color c = gImage.getColor();
- gImage.setColor(Color.BLACK);
- gImage.fillRect(0, 0, WIDTH, HEIGHT);
- gImage.setColor(c); paint(gImage);
- g.drawImage(offScreenImage, 0, 0, null);
- }
其中需要注意的一点是我在查找资料的时候发现有介绍双缓冲机制主要用于awt之中,而在swing中已经自动实现,因此我继承了Frame类,改为swing组件中就没有预定的效果了。因此我在想是否swing中已经很好的处理了双缓冲的问题了呢。
三、总结分析
其实坦克大战游戏设计的目的并不是想要单纯的做一个小游戏,二是为了加强对多线程的掌握,这一点我想应该可以通过游戏时一共运行二十二个线程来证实吧。尽管初衷比较单纯,但是设计过程之中却感觉自己收获了不少的东西,在此想和大家一起分享一下。
1、程序编写的框架十分重要,在程序编写的初期,我尽量的规范自己的代码,虽然有些麻烦,但是后来的经历却让我庆幸这一点上的功夫,在加载一些障碍物图片之后,坦克以及子弹线程的控制从碰到墙壁这一简单判断增加要对障碍物也进行判断,由于各个线程的设计思路相似,因此我在玩家坦克类中成功测试石头小河等障碍物后,比较轻松得就将判断移植到其他的线程之中了。
2、在遇到新的一些问题,比如说双缓冲,应当有独立解决的能力,通过前面一些牛人的经验,网上的相关资料通过已学到的知识自己摸索这个问题,而不是让老师一句一句的解释。这对于以后的发展是极为重要的。学到的知识总是有限的,更为重要的是掌握获取知识的方法。
其实,在这个坦克大战中还有一些缺陷,比如说功能道具太单调,不能直接重启结束后的游戏。但是我想对于java学习初期的我来说,更重要的是学会熟练掌握其中的基本知识与技能,而不是项目本身有多绚。因此今后自己还要更加得努力,与大家一起进步。