坦克大战底层框架搭建并思路分析(一)

      坦克大战是我们都很熟悉的游戏,这游戏是含有大量的 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()方法。。。
至此一个简单的底层坦克类搭建完成,下一讲将讲到坦克客户端调用这个坦克自由移动的问题,当然这不是最终坦克的类,而只是一个底层框架体下的坦克包装类,坦克的类
打算用三讲来讲全,分别是目前这个仅仅用于演示坦克移动的,后面的发射子弹的,有障碍的(也即完整版的)

     
  致: 小弟不才,有不对的地方或者可以精简代码的地方,欢迎留言指出,感激不尽,望大神也别打击小弟!


 

 

 

posted @ 2013-06-10 12:48  大鹏鸟2018  阅读(1643)  评论(4编辑  收藏  举报