项目作者: xianyinuma

项目描述 :
BOAT Battle
高级语言: JavaScript
项目地址: git://github.com/xianyinuma/totalProject.git
创建时间: 2017-05-03T06:14:56Z
项目社区:https://github.com/xianyinuma/totalProject

开源协议:MIT License

下载


Uncharted Waters: Web多人VR环境

Uncharted Waters 是一个web多人VR游戏,使用了express、vue、three.js、socket.io等技术。

Demo: webpj.ruchenshanghai.cn

Communications

What is it?

Uncharted Waters 是一个Web多人VR社交游戏,玩家在注册后可以加入游戏。

在选择了船的模型之后,玩家可以进入游戏。
在游戏的主场景中,用户可以用 WASD 键控制船的移动,用F键控制船的开火。用户的主要游戏目的就是控制自己的船攻击别的用户的船,击沉后获取经验升级。

用户也可以通过内置的聊天界面和别的用户进行沟通交流。

同时,游戏场景里也有一些人工智能的NPC会对用户进行攻击,NPC分为两种,第一种不会移动,会对进入其攻击范围(500码)的玩家船只进行攻击;第二种会对进入其追踪范围(1000码)的玩家船只进行追踪,对进入其攻击范围(500码)的玩家船只进行攻击。

当然,由于我们的游戏的主要部分还是在玩家和玩家之间的对战,所以对于NPC的攻击玩家以躲避为主。

Programe Architecture

  • 项目组织:

前端:

assets文件夹

  1. ./public/assets/
  2. ├── images
  3. ├── lib
  4. ├── bootstrap
  5. ├── css
  6. ├── fonts
  7. └── js
  8. └── js
  9. ├── models
  10. ├── texture
  11. images文件夹主要存储了需要用到的图片。
  12. lib文件夹存储了用到的three.js库和其他库。
  13. models文件夹存储了我们用到的模型。
  14. texture文件夹主要存储了天空盒子和水的材质。

css文件夹

  1. ./public/css/
  2. .
  3. ├── chatroom.css
  4. ├── index.css
  5. ├── login.css
  6. ├── register.css
  7. ├── reset.css
  8. ├── style.css
  9. └── welcome.css
  10. 主要存储了自己写的CSS文件。

js文件夹

  1. .
  2. ├── loading.js
  3. ├── model
  4. ├── CreateModel.js
  5. ├── DDSLoader.js
  6. ├── MTLLoader.js
  7. ├── OBJLoader.js
  8. ├── OrbitControls.js
  9. └── WaterShader.js
  10. ├── sea-battle
  11. ├── Boat.js
  12. ├── Box.js
  13. ├── Bullet.js
  14. ├── GameManager.js
  15. ├── Map.js
  16. ├── MovableObject.js
  17. ├── NPC.js
  18. ├── Player.js
  19. ├── Portal.js
  20. ├── StaticObject.js
  21. ├── UnmovableNPC.js
  22. ├── chatroom.js
  23. └── loading
  24. ├── Bird.js
  25. ├── Boid.js
  26. ├── CanvasRenderer.js
  27. ├── Projector.js
  28. └── stats.min.js
  29. └── sea-battle.js
  30. 主要储存了js文件。
  31. loading.js 加载动画
  32. ./model/CreateModel.js 加载模型
  33. ./sea-battle/Boat.js Boat类,船的移动、属性等
  34. ./sea-battle/Box.js Box类,补给箱
  35. ./sea-battle/Bullet.js Bullet类,子弹
  36. ./sea-battle/GameManager.js 游戏类,处理用户按键事件、组织游戏逻辑
  37. ./sea-battle/Map.js Map类,地图
  38. ./sea-battle/MovableObject.js 船的父类
  39. ./sea-battle/NPC.js NPC类,可移动追踪的NPC船的实现
  40. ./sea-battle/player.js 创建玩家
  41. ./sea-battle/Portal.js 传送门的实现
  42. ./sea-battle/staticObject.js 静态物品的父类
  43. ./sea-battle/UnmovableNPC.js 静止NPC的实现
  44. ./sea-battle/charoom.js 聊天室的实现
  45. ./sea-battle/loading/ 加载动画的实现
  46. ./sea-battle.js 主文件
  • 关键功能实现细节

船的移动

  1. boat.controlBoat = {
  2. moveForward = false,
  3. moveBackward = false,
  4. moveLeft = false,
  5. moveRight = false
  6. };
  7. 用上述四个flag控制船的移动,根据用户WASD的相关操作,将不同的flag设为true
  8. updateMoveModel()函数中根据上述的四个flag对船的当前移动(包括mesh.position mesh.rotation进行计算)。

NPC的移动

  1. detect()函数,确定周围是否有玩家的船,有的话进行追踪或攻击。
  2. 静态NPC:当有玩家靠近,lookAt玩家,并进行攻击。
  3. 动态NPC:取两个向量,VecA是当前NPC船的方向向量,VecB是从NPC船的位置指向玩家船的位置的向量,计算两者外积之后,结果为正则左转,为负则右转。

船的同步

  • 使用技术:Socket.io
  • 同步细节:
    • 的同步:
      • 每个client拥有一条boat,client将自己boat的相关信息(移动速度、方向、等级血量信息)定时发送到server,再由server同步到所有client。同步的间隔为30ms。
      • 每个client对自己船的信息有着绝对的控制权,不被其他client所改变。一个client判断自己船的相关碰撞(与其他船、静态物品、子弹的碰撞),改变自己的信息,不干扰其他boat的信息。
    • 子弹的同步:
      • 开炮:当一个boat开炮时,相应的client会触发socket.io的“Fire”事件,在将子弹的信息传到server,再由server同步给所有的client。
    • 静态物品(传送门与补给包)的同步:
      • 初始静态物品读取:server向新加入的client发送静态物品数据,进行同步
      • 船与静态物品发生碰撞:client将相应碰撞到的静态物品的id发送给server,server将自己与所有client中的该物品删去
    • NPC的同步:完全由server控制,NPC在server中移动开火,定时将NPC的信息发送给所有的client,同步间隔为30ms。
    • 组队的同步:由一client向另一特定的client发送请求信息,答应则,向所有的相关队友client发送新增队友信息,进行消息同步。

后端

  • MVC框架:Express

  • Model:models文件夹下存放服务器端实体,并且提供访问数据库的接口User提供save、updateMail、updateNick、get、updateRecord接口,分别对应对数据库中的增删改查等操作。

  • View:视图层采用jade模板生成HTML代码
    主要包括以下jade模板文件:error, index, info, layout, log, main, reg, ship, welcome;
    分别对应不同功能的页面

  • Controller:根据不同的http请求(get,post)设置对应路由
    /main 游戏主页面; /reg 注册页面; /log 登录页面; /info 玩家信息页面;
    /ship 选择船模型页面; /welcome 默认首页

  • 项目完成的比较仓促,但是我们尽量保持代码的整洁和可维护性,一些编码方式也借鉴当前流行的最佳实践。但理想是美好的,现实总是不会做到那么完美,需要不断的完善。目前存在的问题是后端代码结构不够清晰、整体代码中无用代码还没有来得及移除。

  • 同步机制:前端socket.io emit特定接口的事件,后端socket.io on接收对应接口事件。(详细同步在上面有说明)

  • 生产环境发布:pm2进程管理器 + MLab云MongoDB数据库