Nodejs实现的一个多人同时在线移动鼠标的小游戏

简介:

最近因为项目需要,所以研究了一下nodejs的websocket实现,socket.io,这是nodejs后台应用websocket广泛使用的框架


准备工作

  • 安装socket.io,使用命令npm install socket.io
  • windows系统的话,需要vc编译环境,因为安装socket.io的时候,会编译vc代码

游戏基本原理

  • 服务器监听客户端的连接

  • 客户端连接成功时候,绑定页面移动鼠标事件,事件里处理发送当前坐标给服务器

  • 服务器保存一个全局的坐标对象,并以客户端唯一编号为键值

  • 有新连接来的时候,把坐标广播给其它客户端

  • 客户端断开连接的时候,服务端删除它的坐标信息,并广播给其它客户端

开始实现服务端代码

scoket.io建立服务器监听的时候,需要依赖一个http连接,用来处理升级协议用,所以也需要一个http模块,代码如下

var http = require('http'),
    io = require('socket.io');


var app = http.createServer().listen(9091);

var ws = io.listen(app);

然后定义一个全局的坐标对象

var postions = {};

开始监听客户端的连接,并新增广播函数(其实可用socket.io自带的广播方法io.sockets.broadcast.emit),核心代码如下

ws.on('connection', function(client){
    // 广播函数
    var broadcast = function(msg, cl){
        for(var k in ws.sockets.sockets){
            if(ws.sockets.sockets.hasOwnProperty(k)){
                if(ws.sockets.sockets[k] && ws.sockets.sockets[k].id != cl.id){
                    ws.sockets.sockets[k].emit('position.change', msg);
                }
            }
        }
    };
    console.log('\033[92m有新的连接来:\033[39m', postions);
    // 客户端连接成功之后,就发送其它客户端的坐标信息
    client.emit('position.change', postions);
    // 接收客户端发送消息
    client.on('position.change', function(msg){
        // 目前客户端的消息就只有坐标消息
        postions[client.id] = msg;
        // 把消息广播给其它所有的客户端
        broadcast({
            type: 'position',
            postion: msg,
            id: client.id
        }, client);
    });
    // 接收客户端关闭连接消息
    client.on('close', function(){
        console.log('close!');
        // 删除客户端,并通知其它客户端
        delete postions[client.id];
        // 把消息广播给其它所有的客户端
        broadcast({
            type: 'disconnect',
            id: client.id
        }, client);
    });
    // 断开连接
    client.on('disconnect', function(){
        console.log('disconnect!');
        // 删除客户端,并通知其它客户端
        delete postions[client.id];
        // 把消息广播给其它所有的客户端
        broadcast({
            type: 'disconnect',
            id: client.id
        }, client);
    })
    // 定义客户端异常处理
    client.on('error', function(err){
        console.log('error->', err);
    })
});

分析上面的代码,关键点在于

  • 新的客户端连接成功,发送其它客户端的坐标信息
  • 客户端更新坐标信息的时候,通知其它客户端
  • 客户端断开连接,通知其它客户端
  • 广播消息类型分为修改坐标与移除坐标

编写客户端html页面

由于socket.io是自定义的框架,所以客户端需要引用socket.io.js,这个js可以从socket.io模块里查找,路径一般为node_modules\socket.io\node_modules\socket.io-client\dist,里面有合并与压缩两个版本,开发的时候可以用合并版.

完整代码如下

<!DOCTYPE html>
<html>
<head>
    <title>socket.io 多人同时在线互动 例子</title>
    <meta charset="utf-8">
</head>
<body>

<script type="text/javascript" src="socket.io.js"></script>
<script type="text/javascript">
    var ws = io.connect('http://localhost:9091/');
    var isfirst;

    ws.on('connect', function(){
        console.log(ws);
        // 开始绑定mousemove事件
        document.onmousemove = function(ev){
            if(ws.socket.transport.isOpen){
                ws.emit('position.change', { x: ev.clientX, y: ev.clientY });
            }
        }
    })

    ws.on('position.change', function(data){
        // 开始同时在线的别的客户端
        if(!isfirst){
            isfirst = true;
            // 第一条消息是收到别个所有客户端的坐标
            for(var i in data){
                move(i, data[i]);
            }
        }else{
            // 否则,要不就是别个断开连接的消息,或者别个更新坐标的消息
            if('position' == data.type){
                move(data.id, data.postion);
            }else{
                remove(data.id);
            }
        }
    })

    ws.on('error', function(){
        console.log('error:', ws);
        ws.disconnect();
    })


    function move(id, pos){
        var ele = document.querySelector('#cursor_' + id);
        if(!ele){
            // 不存在,则创建
            ele = document.createElement('img');
            ele.id = 'cursor_' + id;
            ele.src = 'img/cursor.png';
            ele.style.position = 'absolute';
            document.body.appendChild(ele);
        }

        ele.style.left = pos.x + 'px';
        ele.style.top = pos.y + 'px';
    }

    function remove(id){
        var ele = document.querySelector('#cursor_' + id);
        ele.parentNode.removeChild(ele);
    }

</script>
</body>
</html>

页面中的img/cursor.png,可以这里找到,cursor.png,这里也有很多其它的鼠标图标,前端的原理比较简单,简单的分析如下

  • 连接成功时,绑定页面mousemove事件,里面处理发送新坐标消息
  • 收到消息根据消息类型,处理是修改其它客户端消息,还是移除其它客户端消息
  • 定义添加其它客户端cursor图标与移除cursor图标
  • 处理客户端异常消息,并添加断开连接,以让服务端移除坐标信息

运行例子

  • 保存服务器代码为io_multigame.js
  • 保存客户端代码为io_multigame.html
  • 运行服务器代码node io_multigame.js
  • 打开多个io_multigame.html页面,即可看到效果

总结

写的比较随意,参考了了不起的nodejs,这是一本好书,想了解nodejs的朋友们,可以看看这本书。


目录
相关文章
|
4月前
|
存储 缓存 Unix
微信小游戏制作工具中实现计时功能
微信小游戏制作工具中实现计时功能
77 0
|
6月前
|
存储 前端开发 JavaScript
前端实现俄罗斯方块游戏(内含源码)
前端实现俄罗斯方块游戏(内含源码)
80 2
|
4月前
|
定位技术 API 开发者
【Godot引擎开发】简单基础,外加一个小游戏DEMO
【Godot引擎开发】简单基础,外加一个小游戏DEMO
|
8月前
|
区块链 Python
桌面太单调?用Python做个“冰墩墩雪容融”桌面部件(好玩又有趣)
桌面太单调?用Python做个“冰墩墩雪容融”桌面部件(好玩又有趣)
138 0
|
9月前
|
移动开发 前端开发 JavaScript
赛车游戏——【极品飞车】(内含源码inscode在线运行)
赛车游戏——【极品飞车】(内含源码inscode在线运行)
赛车游戏——【极品飞车】(内含源码inscode在线运行)
|
存储 Java
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(下)
文章目录 1 开发环境及游戏展示 1.1 游戏主界面 1.2 移动界面 1.3 奖励界面 1.4 F加速功能界面 1.5 死亡界面 2 需求分析 3 系统设计 3.1 系统总体功能设计 3.2 系统总体流程设计 4 功能设计 4.1 贪吃蛇移动及加速功能设计 4.2 贪吃蛇吃食物加速及死亡判定功能的设计 4.2.1 贪吃蛇吃食物加速功能的设计 4.2.2 贪吃蛇死亡判定功能的设计 4.3 贪吃蛇主动加速功能的设计 4.4 贪吃蛇奖励机制功能的设计 5 项目结构与项目实现 5.1 项目结构及类间关系 5.2 项目完整源码 5.2.1 Images类
|
10月前
|
存储 Java API
一个精美的主界面窗口功能的设计和实现原来如此简单,万字肝爆
一个精美的主界面窗口功能的设计和实现原来如此简单,万字肝爆
71 0
|
11月前
|
Java
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏03全屏显示游戏窗口
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏03全屏显示游戏窗口
125 0
|
11月前
|
Java
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏02支持中文及显示FPS
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏02支持中文及显示FPS
117 0
|
图形学 数据安全/隐私保护
还在用Unity开发游戏?那你就out了,试试用Unity做一个答题系统吧
大家都支持Unity是用来做游戏开发,比如说做2D游戏、3D游戏,或者工业虚拟仿真软件的开发。 其他Unity可以做的有很多,比如答题系统。 本篇就介绍答题系统的开发 这个答题系统,可以从文本文档中提取题目和分数,然后绑定到UI上,在答题的过程中,自动判断分数,自动判断正确率。 目的是实现一个可快速导入到项目中使用的小模块。