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


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

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


  • 相关阅读:
    浅谈UML中类之间的五种关系及其在代码中的表现形式
    Understanding Liskov Substitution
    WPF捕获事件即使这个事件被标记为Handled
    [三层架构+WCF]三层架构+WCF实现TaskVision
    [.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言
    WPF拖动总结
    Understanding Single Responsibility and Interface Segregation
    [WinForm ADO.NET实现TaskVision][SQL Server 2008][winform datagridview总结][自定义Custom控件]Winform DataGridView各种现有column及自定义column+Winform自定义控件
    经尉迟方兄提点,终于明白为什么不是一个简单的26进制程序了
    一个有关windows服务的安装问题
  • 原文地址:https://www.cnblogs.com/zyp221314/p/3130652.html
Copyright © 2020-2023  润新知