Nodejs WebGL, websocket做的3D多人在线游戏,希望各位给点建议

Nodejs WebGL, websocket做的3D多人在线游戏,希望各位给点建议

第一次在这个社区发帖子……因为感觉这个社区的技术很好又有热情,所以才选择到这里发帖子,希望路过的朋友们能够帮帮忙…… 先说一下自己做的这个东西吧,我把它开源了并托管在github上,源代码地址在这里,它大概长这个样子……单机版的样子,最左侧是聊天系统,可以缩放到左下角,聊天系统支持广播和私聊两种方式,要先输入昵称才能进入聊天室,点击右侧昵称切换到私聊,点击右侧牛头换到广播(这奇葩的操作,我是怎么想的……)支持键盘操作,比如0-9切换枪,·键弹出系统菜单,空格跳跃,wasd行走等等,源码里有详细说明。 webGL这一块是用的Three.js这个开源库,包括模型的解析等,模型也是Three.js的例子上提供的,后台用的nodeJS,静态文件服务器跟websocket服务器没写在一起,websocket是用的nodeJS的socket.io模块,主要处理多人在线时的消息传输,先在这里感谢一下开源社区。 这个作品一眼看上去感觉效果挺好的,刚把这个东西做出来的时候也挺开心的,但是它存在很多的问题: 1.效率低下。因为要解析这个比较复杂的3D模型,所以在开始初始化的时候很容易导致浏览器崩溃。而且这个东西是前段时间通宵赶工赶出来的(那段时间郁闷极了才会这么逼自己),整个系统的结构,代码的结构,操作流程等等都没有怎么去考虑,只想赶快做出这个东西,所以有很多地方不合理,就比如支持多人在线这一块,本来应该是当有用户加入的时候动态生成一个3D模型,但是当时花了好久去弄,总是生成了一个没有纹理的模型,还不支持添加的键盘操作,然后很烦躁的把代码改成了一开始就初始化5个模型(所以多人也就最多5个人了……),然后有用户加入的时候把他们显示出来,真是坑爹…… 2.只支持chrome。只在chrome 19+做了实验,firefox问题不大,就是后来写css3动画的时候没有考虑firefox,IE就…… 3.存在一些已知或未知的bug。系统健壮性比较差,服务器偶尔会崩溃。现在github上的版本有点已知的bug还没有修改。 4.代码结构不好现在主要的逻辑都放在html文件里面了,还有不少的全局变量什么的,曾经想用seaJS模块化,但是失败了,因为事情比较多就没有继续尝试。 5.作品方向不能明确。这是最坑爹的,我一直在考虑webGL的前景以及这个作品未来的定位,webGL实在是不够成熟,自己做这个东西以后的方向是什么,自己有时也说不清楚。大一的时候看到有学长用openGL做了类似魔兽争霸的3D的游戏(效果什么的还是差很多,但是觉得确实做的很棒),但是被学院的教授们批评的体无完肤,就是因为作品方向的问题,我想现在我也遇到了类似的问题了吧…… 所以很希望有喜欢类似的作品的朋友提出建设性的意见,或者直接拿这份源码进行进一步的开发,只要这个作品能有用途就好。 简单说一下搭建服务器环境吧,server文件夹里面的server.js是静态文件服务器,要注意路径问题,start.js是websocket服务器,注意端口号。常规方式启动就好了,control_s.html里面的websocket服务器地址修改一下。 因为最近校园招聘比较多,这段时间奔波于各种宣讲会和笔试之间,按照以往的经验,一个项目放下一段时间后怎么也提不起兴趣再扩展了,所以也促成自己决心开源,不能让这个作品就这么烂尾了。当然里面吸取了很多开源的精华(虽然作品不咋的),也当作回馈开源社区,以后做出更好的作品还是会选择开源的。还有就是我的某个导师想把代码拿去,等下一级的学生做比赛用,个人觉得这种行为……而且这导师还忽悠我导致没能出去找实习,在他实验室苦逼了一暑假,真心觉得开源比拿去做比赛有意义太多太多了。在拿到正式工作的offer前估计是没多少时间写代码了,希望社区的对这个感兴趣的大神们能对那些问题进行优化或者有建设性的意见,小弟不胜感激!最近这段时间专心于校园招聘,最多修改一点小bug,也请多包涵。


28 回复

Nodejs WebGL, Websocket 做的 3D 多人在线游戏,希望各位给点建议

开源项目介绍

大家好,这是我第一次在这个社区发帖子。因为感觉这个社区的技术很好又有热情,所以才选择到这里发帖子,希望路过的朋友们能够帮帮忙。

我开源了一个基于 Node.js 和 WebGL 的 3D 多人在线游戏,并托管在 GitHub 上。源代码地址在 这里。这是一个初步实现的作品,下面是它的截图:

单机版的样子

  • 最左侧是聊天系统,可以缩放到左下角。
  • 聊天系统支持广播和私聊两种方式。
  • 支持键盘操作,例如 0-9 切换枪,· 键弹出系统菜单,空格跳跃,wasd 行走等。

技术栈

  • WebGL: 使用 Three.js 库来渲染 3D 模型。
  • WebSocket: 使用 socket.io 模块来处理多人在线时的消息传输。

项目存在的问题

  1. 效率低下:

    • 解析复杂的 3D 模型导致浏览器崩溃。
    • 代码结构混乱,没有考虑系统架构。

    示例代码(简化版):

    // server.js (简化版)
    const io = require('socket.io')(httpServer);
    let clients = [];
    
    io.on('connection', (socket) => {
      clients.push(socket);
      socket.on('disconnect', () => {
        clients = clients.filter(client => client !== socket);
      });
    });
    
    // start.js (简化版)
    const express = require('express');
    const app = express();
    const httpServer = require('http').createServer(app);
    
    app.use(express.static('public'));
    
    httpServer.listen(3000, () => {
      console.log('Listening on port 3000');
    });
    
  2. 浏览器兼容性问题:

    • 目前只在 Chrome 19+ 测试过,Firefox 和 IE 存在问题。

    示例代码(简化版):

    // client.js (简化版)
    if (!window.WebSocket) {
      alert('您的浏览器不支持 WebSocket');
    } else {
      const socket = new WebSocket('ws://localhost:3000');
      socket.onmessage = function(event) {
        console.log('Received:', event.data);
      };
    }
    
  3. 已知或未知的 Bug:

    • 系统健壮性较差,服务器偶尔会崩溃。
  4. 代码结构不佳:

    • 主要逻辑集中在 HTML 文件中,全局变量较多。

    示例代码(简化版):

    // 改善后的模块化代码
    define(['three', 'socket.io'], function(THREE, io) {
      function init() {
        // 初始化 Three.js 场景
      }
    
      function handleMessages(message) {
        // 处理 WebSocket 消息
      }
    
      return {
        init: init,
        handleMessages: handleMessages
      };
    });
    
  5. 作品方向不明确:

    • 对 webGL 的前景及未来定位不明确。

搭建服务器环境

  • server 文件夹中的 server.js 是静态文件服务器。
  • start.js 是 WebSocket 服务器。
# 启动静态文件服务器
node server.js

# 启动 WebSocket 服务器
node start.js

结语

由于近期校园招聘较多,我无法投入更多时间在这上面。因此,我决定开源这个项目,希望有志同道合的朋友能继续开发和完善它。如果有人愿意接手,或者有任何建设性的意见,我将不胜感激!

感谢大家的关注和支持!


希望这些建议和示例代码对你有所帮助。如果有任何问题或需要进一步的帮助,请随时联系我。


支持,关注,学习

支持,关注,学习,楼下保持队形。

好厉害. 想下载试玩一下, 求写 README

支持,关注,学习,收藏,楼下保持队形。

看起来好牛逼的样子。

多谢多谢~

互相学习~多谢~

嗯,写好了,上传上去了

多谢~互相学习~

只是看起来这样。。。估计真正看了代码就不会这样想了吧。。。

嗯,在关注网易要开源的框架。。 模型用3Dmax等建模工具建好(我不会,在网上找的模型),导出成.js格式的文件,数据是json格式,Three.js就能解析出来了,剩下的就是建立场景,设置摄像头,灯光等

3D模型应该是webGL做出来的

很好很强大啊~膜拜~

是webGL的技术,用的Three.js这个类库

哎,雕虫小技啊…没什么东西…一直膜拜您写的那个博客应用啊……

支持,关注,学习,楼下保持队形。

目前客户端 js 绘图的效率是比较坑爹的,台式机都不一定吃得住,更别说移动终端了。

我看看能不能把服务端改为在“零秒”上运行,我个人虽然不是很看好 HTML5 的 3D 游戏,但算是个 DEMO 了。

多谢了~

是啊,光渲染模型就要好几秒,移动终端基本就不用考虑了肯定卡爆了……真不知道前景如何

哎……找工作忙了俩星期结果代码还是老样子……帖子也沉了……失落啊

運行之後畫面十分十分的慢!~ 到底有沒有使用到 顯卡的GPU ?

我在路由器上做了端口映射 (9099) 為什麼連不上 ?? 現在只有localhost:9099 能連得上

聊天室用不了, 也不能換槍的, 別人連上來後 根本見不到對方啊

有谁遇到过客户端socket.io连接上服务器端之后,服务器端不断接受到同一个客户端的连接请求,感觉客户端在不断轮询,不断触发服务器端的connection事件(我用的是express-2.5),不一会就产生大量的日志信息,都快把我的服务器撑爆了~~~~,不得不暂时关闭socket连接了。有什么方法能避免么?

刚才看了下socket.io的官方文档,原来socket.io参数是可以配置的。将log leve等级设置为1之后,日志量明显下降了,但是为啥服务器一直能不断监听到同一台客户端连接信息(就是不断触发connection),难道客户端这段代码保持连接服务器之后,服务器端没有做客户端识别么,采取不管时候是同一个客户端但只要在保持连接的情况下认为是不同客户端?所以才会定期去触发connection事件?

根据你的描述,你正在开发一个使用WebGL和Websocket的3D多人在线游戏,并且已经开源。以下是一些建议和优化方向:

1. 性能优化

问题: 初始加载复杂模型时浏览器容易崩溃。 解决方案:

  • 分帧加载: 可以将模型加载过程分帧处理,避免一次性加载过多数据导致性能问题。
  • LOD (Level of Detail): 使用不同细节级别的模型,在玩家远离模型时降低模型细节,提高渲染速度。
// 示例代码
function loadModel(url) {
    const loader = new THREE.GLTFLoader();
    loader.load(url, (gltf) => {
        scene.add(gltf.scene);
        // 分帧加载
        requestAnimationFrame(() => {
            // 初始化其他部分
        });
    });
}

2. 跨浏览器兼容性

问题: 目前只支持Chrome。 解决方案:

  • CSS3 动画: 确保CSS3动画在不同浏览器中兼容,可以使用autoprefixer等工具来处理。
  • WebGL 支持: 使用THREE.WebGLRenderer检查浏览器是否支持WebGL。
if (!Detector.webgl) {
    Detector.addGetWebGLMessage();
} else {
    renderer = new THREE.WebGLRenderer({ antialias: true });
}

3. 代码结构优化

问题: 代码结构混乱,逻辑集中在HTML文件中。 解决方案:

  • 模块化: 使用ES6模块或webpack打包工具,将代码拆分为多个模块。
  • 类封装: 将功能封装成类,提高代码复用性和可维护性。
// 示例代码
class Game {
    constructor() {
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(...);
        this.renderer = new THREE.WebGLRenderer(...);
    }

    init() {
        // 初始化逻辑
    }

    update() {
        // 更新逻辑
    }
}

const game = new Game();
game.init();

4. 多人在线优化

问题: 只支持最多5个玩家。 解决方案:

  • 动态生成模型: 当玩家加入时动态创建3D模型。
  • 优化网络传输: 使用二进制格式传输数据,减少带宽消耗。
io.on('connection', (socket) => {
    socket.on('newPlayer', (data) => {
        const player = createPlayer(data); // 动态创建玩家模型
        socket.emit('playerAdded', player);
    });
});

5. 作品方向

问题: 作品方向不明确。 解决方案:

  • 明确目标: 设定具体的目标和功能列表,例如社交互动、PvP模式、任务系统等。
  • 社区反馈: 积极收集社区反馈,调整开发方向。

希望这些建议对你有所帮助,祝你早日完成这个项目!

回到顶部