Tank

来自马士兵
跳转至: 导航搜索

坦克大战项目纪要

演示视频

多人联网版坦克项目演示视频

项目技术点

  • 面向对象
  • 多态
  • NIO
  • Lambda表达式
  • 多种设计模式
  • 非阻塞网络模型
  • JUnit JavaLoggingAPI
  • 反射
  • ...

版本纪要

  1. new 出一个窗口
  2. 设定标题栏内容
  3. TankFrame从Frame继承,然后显示
  4. 认识paint方法,重写
  5. 学习graphics类,画图
  6. 学习repaint方法
  7. 实现MyKeyListener,对键盘作出响应
  8. MyKeyListener从KeyAdapter继承
  9. 取得具体按键信息
  10. 根据具体按键调整坦克位置,持有对方引用
  11. 抽象出坦克类,学习使用枚举类型,记录键盘状态,根据键盘状态确定坦克方向,根据方向进行移动
  12. 把监听处理类MyKeyListener放到TankFrame内部, static inner class 还是 成员内部类?
  13. 用匿名内部类处理窗口关闭
  14. 根据按键状态,改变坦克方向
  15. 根据坦克方向移动位置 ,增加move方法,设定SPEED常量
  16. 能停,能动, 需要根据moving的值来确定到底是否移动
  17. test包,关于classloader的知识 显示图片 ImageIO 尝试显示一张图片
  18. 将坦克换成图片版,能力训练:窗口背景改成黑色
  19. 画出一颗子弹,让子弹飞一会儿,定义子弹类,加载资源,设定属性和方法paint move
  20. 按下ctrl键,主战坦克打出一发炮弹
  21. 打出多发子弹
  22. 子弹从坦克中心位置打出
  23. 子弹消亡(飞出游戏区),作业://有一个bug没有修正:调用getRect每次都new,子弹和坦克自己控制自己对容器的添加和删除 ,坦克边界处理
  24. 定义rectangle属性,不用每次都new
  25. 炮弹new出来自动加入容器,死掉后自动去除
  26. 分离玩家和机器人,对边界进行不同的处理,对玩家坦克进行边界处理,先加载资源,再new TankFrame,不然会有空指针异常
  27. 用双缓冲消除闪烁,修改TankFrame,加入update代码
  28. 加一堆敌人坦克,tank自己负责生死,加入和删除
  29. 做碰撞检测,让子弹能够打死坦克,tank.die()
  30. 显示爆炸
  31. 加入声音
  32. 让敌人坦克更加智能
    1. moving = true, 坦克可以动了
    2. 随机改变方向:randomDir()
    3. 随机发射子弹
  33. 对坦克和子弹加入 Group属性,不同的Group可以互相撞击
  34. 测试Properties类的使用,test包里
  35. 建立PropertyMgr类
  36. MV分开 Model View分离,分层思想,对修改关闭,对扩展开放,Singleton Observer
  37. GameModel 改成单例模式
  38. 对于碰撞的处理,interface Collider() -> TankTankCollider() BulletTankCollider -> BulletBullet BulletPlayer PlayerTank WallBullet TankWall TankBox TankSoldier
  39. Class.forName().newInstance(); test ClassInitTest
  40. 抽象出游戏物体的父类, GameObject -> x, y , paint(),Tank Player Bullet Explode extends GameObject @Override 去掉x, y,GameModel -> List<GameObject> -> add remove
  41. 把GameModel中的各种不同物体的List合成为一个List<GameObject>,对应的add remove方法只需一个就够了,由于GameObject的List已经混淆了类型,考虑用新的碰撞逻辑处理,使用责任链模式处理碰撞
  42. 完善责任链模式
    1. :抽象链条类
      使用链式编程 add() return this
      在collide中加入boolean返回值,控制链条是否继续
  43. 加入墙
    1. Wall extends GameObject
    2. x y w h
    3. paint
    4. getRect()
    5. BulletWallCollider
    6. TankWallCollider
  44. 按键切换发射策略
    1. C
    2. 切换策略,策略由FireMgr来管理
  45. 实现暂停功能
  46. 实现存盘功能
    1. GameModel中加一个方法save loa
    2. 键盘处理s l
  47. 使用Junit测试服务器loop
    1. test.MsgTest
    2. 写出TankJoinMsg
    3. 以及NetTankClient
  48. 去掉敌人的坦克(机器控制的坦克)
    1. 处理接收到的消息PlayJoinMsg
    2. UUID Universal Unique ID
    3. Player : 属性1UUID 2:名字
  49. 处理接收到的消息
    1. 如果是自己发送的,略过
    2. 如果是其他player发送的,new 新的player加入到objects
  50. player新的构造方法,UUID加入到GameObject, 重写实现GameModel findbyuuid
  51. 让后来人能看到先加入者
    • 先加入者也要发一个加入消息
  52. 加入坦克方向改变的消息
    1. 加入enum MsgType,每一种消息都有自己的消息类型,接收到字节数组后首先读取消息类型,
    2. 根据不同的消息类型将字节数组处理成为不同的消息对象,然后再进行处理
    3. 加入消息类 PlayerDirChangedMsg uuid dir TYPE
    4. 处理时,首先读取消息类型,根据消息类型,交给不同的子类处理
    5. 接收到改变方向的消息时,首先查找对应player,然后设定他的方向
    6. 在坦克方向和上一次方向不一致时,发出该消息
      • 加入成员变量oldDir,构建player的时候让oldDir = dir
      • 每次move之前,记录oldDir = dir,在按下键设定坦克方向之后,进行判断,如果方向不一致,就发出该消息
  53. 重构代码
    1. 抽象父类Msg send方法修改为send(Msg)
    2. 读取MsgType类型后,通过class.forName方法来创建新的instance,然后调用parse方法
    3. parse完后自己handle
  1. 收到改变坦克方向消息时,让player的moving为true
  2. 发送主战坦克停止的消息
    • 调整误差做同步,每次发送停止或者改变方向的信息,需要同步x,y位置
  3. 发送主战坦克开始移动的消息(方向没变)
    1. 同时发送子弹产生的消息
  1. 加入子弹和Player的撞击逻辑
  2. 把主战坦克也加入到List中
  3. 完善服务器登陆的代码