drawingPanel类主要负责服务器端界面窗口的创建和设置,powerUp类主要用来设置子弹属性,例如加快速度、提升火力等,feedbackHandler类主要用来解码从客户端发来的指令字符串,再将其转换成指令来判断游戏失败后玩家是否继续游戏的问题。
在客户端,ClientModel类主要用来设置与服务器的连接,ClientView类主要负责客户端端图形界面的面板信息,ClientControler类主要负责处理来自客户端视图框架的输入和创立通信与帮助信息等,drawingPanel主要用来设置客户端窗口界面,instructionHandler类主要用来解码从服务器端发来的指令字符串,再将其转换成指令来判断游戏失败后玩家是否继续游戏的问题,shield类主要负责设置坦克吃掉头盔图标获得保护时的状态,normalObject类主要用来创建和描绘其他物体对象。
在服务器端和客户端中都存在的类中,Actor类主要用来创建接口,base类主要用来创建基地并设置属性,bullet类主要用来创建子弹并设置属性,Ticker类主要用来创建时间信息,bomb类主要用来创建子弹打出后产生的爆炸效果,river类主要用来创建河道并设置属性,grass类主要负责创建草坪并设置属性,Steelwall类主要用来创建铁墙并设置属性,wall类主要用来创建和设置普通墙及其属性,level类负责创建关卡。如表1,表2所示。
表1 游戏服务器端各类功能表 ServerModel ServerView ServerControler enemy player drawingPanel powerUp feedbackHandler Actor base Ticker bullet bomb river grass Steelwall wall level
表2 游戏客户端各类功能表 ClientModel ClientView
设置与服务器的连接 设置客户端端图形界面的面板信息 3
创建主机 设置服务器端图形界面的面板信息 处理来自服务器视图框架的输入 创建敌方坦克 设置玩家的得分及其显示位置等信息 创建和设置服务器端界面窗口 加快子弹速度并提升火力 判断指令并执行 创建接口 创建并设置基地 创建并设置时间信息 创建子弹并设置属性 设置爆炸效果 创建河道并设置属性 创建草坪并设置属性 创建铁墙并设置属性 创建普通墙并设置属性 创建关卡
ClientControler drawingPanel instructionHandler shield normalObject level base Ticker bullet bomb river wall
客户端玩家输入主机地址来完成与服务器玩家的连接,双方通过使用指令键来操控自己的坦克,敌方坦克和子弹则是自主随机运行,游戏中会对玩家的分数进行记录,还增加了特殊武器,另外,此游戏还进行了小小的创新,添加了通信功能,客户端与服务器端的连接访问通过使用套接字Socket来实现。
其总体功能如图1所示。
负责处理来自客户端视图框架的输入 设置客户端窗口界面 判断指令并执行 设置玩家坦克防护盾 创建并描绘其他的物体对象 创建关卡 创建并设置基地 创建并设置时间信息 创建子弹并设置属性 设置爆炸效果 创建河道并设置属性 创建普通墙并设置属性
图1 总体功能图
3.2 坦克大战总体流程图 如图2所示。
4
图2 总体流程图
4.详细设计 4.1 面板功能设计 4.1.1 基地的设计
base类定义了几个变量,通过构造器初始化了基地的变量参数,使用g.drawImage()方法设置一幅图片来代表基地,通过public void move(){}来处理基地受到铁墙防护时的变化,使用if()判断语句判断铁墙的保护时间。游戏的核心重点自然就是基地了,一旦基地被毁,则玩家失败,游戏结束。游戏面板是游戏程序的关键,这里使用了方法paintComponent(Graphics g)来进行建立并设置其属性,具体实现代码如下:
5
public void draw(Graphics g){
g.drawImage(base, xPos - 12, yPos - 12, null );} public void paintComponent(Graphics g) {
Graphics offScreenGraphics; if (offScreenImage == null) { }
offScreenGraphics = offScreenImage.getGraphics(); myPaint(offScreenGraphics);
g.drawImage(offScreenImage, 0, 0, this);}
offScreenImage = createImage(640, 550);
4.1.2敌方坦克的设计
enemy类设置了敌方坦克的共同属性,并根据不同外形的坦克设置了不同的属性,如椭圆形的坦克的移动速度会比较快,拥有多层颜色坦克的生命力与其拥有的颜色数量一样,利用随机函数Math.random()*4随机生成一个随机值,并转换成整形数值,将此值赋给变量direction来作为敌方坦克生成时的方向,再将Math.random()*200生成的随机值转换成整形数值,赋予变量interval来作为生成时的时间间隔,并且设置了地方坦克的移动周期,在一个周期内将会朝着相同的方向继续移动,并设置了其发射子弹的遂进行。而在特殊属性中,分别设置了敌方坦克的的火力、速度、图标等属性,再用方法draw(Graphics g){}向地图中加入敌方坦克。具体实现代码如下:
interval = (int)(Math.random()*200); direction = (int)(Math.random()*4); if(type ==args1 ){
firePosibility = args2; speed = args3;
textures = new Image[args4];}
public void draw(Graphics g){
if(flashing && gameModel.gameFlow > 4)
g.drawImage(textures[textures.length-4+direction], xPos - size, yPos - size, null); else
g.drawImage(textures[direction], xPos - size, yPos - size, null);} 4.1.3河道、草坪的设计
grass类继承了Actor接口,通过grass类构造器定义了草坪的x,y坐标和矩形边界以及图标,通过public void draw(Graphics g) {}方法绘制了草坪。游戏双方坦克及其子弹可以自由通过草坪。具体实现代码如下:
public grass(int a, int b){
6
}
xPos = a; yPos = b;
border = new Rectangle(0,0,0,0);
public void draw(Graphics g) {
g.setColor(new Color(0, 225, 0));
for(int i = yPos - 11; i <= yPos + 12; i+=5)
g.drawLine(xPos - 12, i, xPos + 12, i); g.drawLine(i, yPos - 12, i, yPos + 12); for(int i = xPos - 11; i <= xPos + 12; i+=5) g.setColor(new Color(0, 128, 0)); for(int i = yPos - 10; i <= yPos + 12; i+=5) }
g.drawLine(xPos - 12, i, xPos + 12, i); g.drawLine( i, yPos - 12, i, yPos + 12);
for(int i = xPos - 10; i <= xPos + 12; i+=5)
river类继承了Actor接口,用river类构造器定义了河道的x,y坐标和矩形边界以及图标,使用g.drawImage(Image,int,int, ImageObserver)方法设置一幅图片来代表河道。以前各个经典版本的坦克大战游戏都将河道设置为不允许坦克经过,但子弹可以自由通过,本程序为了遵循经典,也如此设计。具体实现代码如下:
public river(int a, int b, ServerModel gameModel){
this.gameModel = gameModel; river = gameModel.textures[71]; xPos = a; yPos = b;
Border = new Rectangle(xPos - 12, yPos - 12, 25, 25);}
g.drawImage(river, xPos - 12, yPos - 12, null)} 4.1.4墙与铁墙的设计
该模块通过new Rectangle(int x,int y,int width,int height)完成了一个矩形的创建,然后将其具体值赋给变量数组border[数组索引]生成了墙。坐标x和y为绘制矩形时的起始点,width,height分别为矩形绘制的宽和高。通过构造器定义普通墙和铁墙的矩形边界和图标。具体实现代码如下:
generalBorder = new Rectangle(xPos - 12, yPos - 12, 25, 25); border[0] = new Rectangle(xPos - 11, yPos - 11, 11, 11); border[1] = new Rectangle(xPos + 1, yPos - 11, 11, 11); border[2] = new Rectangle(xPos - 11, yPos + 1, 11, 11); border[3] = new Rectangle(xPos + 1, yPos + 1, 11, 11);
public wall(int a, int b, int orientation, ServerModel gameModel){
xPos = a; yPos = b;
this.gameModel = gameModel; wall = gameModel.textures[70];
generalBorder = new Rectangle(xPos - 12, yPos - 12, 25, 25);}
4.1.5界面窗口的创建
再该模块中,在ServerView类的构造器中用super()方法调用父类构造器设置窗口题目为“坦克大战”,使用JButton(String)定义了六个(退出、帮助、发送、暂停/继续、建立主机和隐藏)鼠标点击事件(即所谓的按钮),JTextField定义文本框,并将其设置为不可编辑。使用new
7