坦克大战底层框架搭建并思路分析(一)
坦克大战是我们都很熟悉的游戏,这游戏是含有大量的 J2ee 的基础知识,是一个值得研究,虽然简单的入手项目:从java的面向对象思想出发,
这个游戏最为主要的角色就是 坦克,因此首先先包装出一个坦克类来,以便以后自由复制生产更多的坦克:
import java.awt.*;
import java.awt.event.KeyEvent;
1 public class Tank { 2 public static final int WIDTH = 30; //定义一个常量表示坦克的宽度 3 public static final int HEIGHT = 30; 4 public static final int XSPEED = 5; //定义一个常量表坦克每次的移动速度 5 public static final int YSPEED = 5; 6 private int x,y; //坦克出现的坐标
public Tank(int x,int y){ 构建坦克的构造方法,传入坦克出现的坐标位置x,y this.x = x; this.y = y; }
废话说了一大箩,咱先把坦克给画出来才是王道对吧,下面定义一个draw()的方法来画坦克
public void draw(Graphics g){ Color c = g.getColor(); //获取默认的画笔颜色 g.setColor(Color.RED); //设置画笔的原色 g.fillOval(x, y, WIDTH, HEIGHT); //用刚刚设好的红色根据上面提供的参数画出坦克来 g.setColor(c); //再把画笔的颜色设回默认的颜色,用完了归位! move(); //把move()包装到draw()里,一画完就执行运动(这个方法我们暂时不管,先挂着,下面会讲到它的) }
private boolean BL,BU,BR,BD = false; //定义坦克的四个按键的初始化状态,默认布尔值设为false,一旦监听到被按下时再更改为 true
//由于坦克的攻打方向或是移动方向起码都得有上下左右四个方向,但仅有四个会显得太单调,而且不符合一般游戏的思路,因此另外
定义出LU(左上)、RD(右下)、LD()左下 、RU(右上),另外还有一个不动的时候的状态 STOP ,如果这几个对象是有限的,因此为了
使用方便,我们直接使用枚举的方法(enum)来规定这几个方向:
enum Direction{ //这是方向 L,U,R,D,LU,LD,RU,RD,STOP; }
Direction dir = Direction.STOP; //把坦克的默认状态设置为不动 STOP;
下面来讲讲坦克运动的方法 move() ,在上面我们定义了八个方向(STOP除外),我们要根据方向来进行运动,因此先写出坦克的move()方法来
1 void move(){ 2 switch(dir){ //使用switch来判断坦克的方向 3 case L:x-=XSPEED;break; //如果坦克方向为做,则向左迈 XSPEED 个单位, 4 case U:y-=YSPEED;break; //同上; 5 case R:x+=XSPEED;break; 6 case D:y+=YSPEED;break; 7 case LU:x-=XSPEED;y-=YSPEED;break; 8 case LD:x-=XSPEED;y+=YSPEED;break; 9 case RU:x+=XSPEED;y-=YSPEED;break; 10 case RD:x+=XSPEED;y+=YSPEED;break; 11 } 12 }
现在问题来了,我们怎么知道用户按下了那个方向键呢? 不知道方向键我们又怎么能判断出这move()里的八个方向来呢?
解: java里有监听器帮我们监听用户按下了那个键,这时就使用到了监听事件的内容了
我们知道监听按键的类是 KeyListenner,使用其适配器 KeyAdapter 来自由实现想要使用的方法 (不过这里不设置监听器,只定义两个判断按键方法以便客户端里的
监听器接收调用)
public void keyPressed(KeyEvent e){ //定义键盘被按下的方法 int key = e.getKeyCode(); //获取键盘按键的编码 switch(key){ case KeyEvent.VK_LEFT: BL = true;break; //在键盘中 向左 "<-" 的键盘编码为 KeyEvent.VK_LEFT; 静态常量,一旦识别出(被按下)是这个编码时就把它的状态更改为true
case KeyEvent.VK_UP: BU = true;break; //同上
case KeyEvent.VK_RIGHT: BR = true;break;
case KeyEvent.VK_DOWN: BD = true;break;
default:break; }
locateDirection(); //定位方法,下面即将谈到...
}
有了一个按键被按下时的方法,我们还必须有一个按键被释放的方法,总不能够让 方向键一旦被按下之后状态就一直都为true吧,肯定都有方法让其恢复为原始状态,否则会
造成一直发弹,或是按了一次方向键之后再想改方向就不灵了,而且无法停止你的战车向前狂奔去找MM...
因此定义一个 keyReleased()方法,来恢复键状态
1 public void keyReleased(KeyEvent e){ 2 int key = e.getKeyCode(); 3 switch(key){ 4 case KeyEvent.VK_LEFT: BL = false;break; //分别把状态改回false; 5 case KeyEvent.VK_UP: BU = false;break; 6 case KeyEvent.VK_RIGHT: BR = false;break; 7 case KeyEvent.VK_DOWN: BD = false;break; 8 default:break; 9 } 10 locateDirection(); //这里又调用了 定位方法 locateDirection(),那么下面就让我们来看看这方法究竟是咋的吧? 11 }
上面我们有了判断按下了那个键的两个方法,但现在怎么靠四个按键来判断八个方向呢? ,这就要求定义一个定位方法来做出判断
1 void locateDirection(){ 2 if( BL && !BU && !BR && !BD) dir = Direction.L; //如果只有一个左键为true(keyPressed()里设置的)的话,就把这个方向规定为左方向 3 else if(!BL && BU && !BR && !BD) dir = Direction.U; //同上... 4 else if(!BL && !BU && BR && !BD) dir = Direction.R; 5 else if(!BL && !BU && !BR && BD) dir = Direction.D; 6 else if( BL && BU && !BR && !BD) dir = Direction.LU; 7 else if( BL && !BU && !BR && BD) dir = Direction.LD; 8 else if(!BL && BU && BR && !BD) dir = Direction.RU; 9 else if(!BL && !BU && BR && BD) dir = Direction.RD; 10 else if(!BL && !BU && !BR && !BD) dir = Direction.STOP; 11 } 12 }
返回keyPressed()方法来看,当判断玩按键之后就立即对齐进行定位的判断,因此在keyPressed()最后引入了 locateDirection() 方法来判断,同理keyRealease()方法。。。
至此一个简单的底层坦克类搭建完成,下一讲将讲到坦克客户端调用这个坦克自由移动的问题,当然这不是最终坦克的类,而只是一个底层框架体下的坦克包装类,坦克的类
打算用三讲来讲全,分别是目前这个仅仅用于演示坦克移动的,后面的发射子弹的,有障碍的(也即完整版的)
致: 小弟不才,有不对的地方或者可以精简代码的地方,欢迎留言指出,感激不尽,望大神也别打击小弟!