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


Posted in NodeJs onDecember 06, 2014

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

准备工作

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

游戏基本原理

1.服务器监听客户端的连接
2.客户端连接成功时候,绑定页面移动鼠标事件,事件里处理发送当前坐标给服务器
3.服务器保存一个全局的坐标对象,并以客户端唯一编号为键值
4.有新连接来的时候,把坐标广播给其它客户端
5.客户端断开连接的时候,服务端删除它的坐标信息,并广播给其它客户端

开始实现服务端代码

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);

    })

});

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

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

编写客户端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,这里也有很多其它的鼠标图标,前端的原理比较简单,简单的分析如下

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

运行例子

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

总结

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

NodeJs 相关文章推荐
NodeJS学习笔记之网络编程
Aug 03 NodeJs
Nodejs为什么选择javascript为载体语言
Jan 13 NodeJs
手把手教你把nodejs部署到linux上跑出hello world
Jun 19 NodeJs
NodeJS实现图片上传代码(Express)
Jun 30 NodeJs
Nodejs实现文件上传的示例代码
Sep 26 NodeJs
nodejs操作mongodb的填删改查模块的制作及引入实例
Jan 02 NodeJs
nodejs(officegen)+vue(axios)在客户端导出word文档的方法
Jul 31 NodeJs
NodeJS模块与ES6模块系统语法及注意点详解
Jan 04 NodeJs
NodeJs 实现简单WebSocket即时通讯的示例代码
Aug 05 NodeJs
Nodejs实现图片上传、压缩预览、定时删除功能
Oct 25 NodeJs
nodejs使用socket5进行代理请求的实现
Feb 21 NodeJs
Nodejs实现的一个静态服务器实例
Dec 06 #NodeJs
nodejs中简单实现Javascript Promise机制的实例
Dec 06 #NodeJs
nodejs实现的一个简单聊天室功能分享
Dec 06 #NodeJs
详谈nodejs异步编程
Dec 04 #NodeJs
nodejs下打包模块archiver详解
Dec 03 #NodeJs
nodejs中转换URL字符串与查询字符串详解
Nov 26 #NodeJs
nodejs教程之制作一个简单的文章发布系统
Nov 21 #NodeJs
You might like
十天学会php之第五天
2006/10/09 PHP
配置PHP使之能同时支持GIF和JPEG
2006/10/09 PHP
php 结果集的分页实现代码
2009/03/10 PHP
IIS6.0中配置php服务全过程解析
2013/08/07 PHP
Mootools 1.2教程 Fx.Morph、Fx选项和Fx事件
2009/09/15 Javascript
写了10年的Javascript也未必全了解的连续赋值运算
2011/03/25 Javascript
js 剪切板的用法(clipboardData.setData)与js match函数介绍
2013/11/19 Javascript
鼠标滚轴控制文本框值的JS代码
2013/11/19 Javascript
javascript拖拽上传类库DropzoneJS使用方法
2013/12/05 Javascript
禁止iframe页面的所有js脚本如alert及弹出窗口等
2014/09/03 Javascript
node中socket.io的事件使用详解
2014/12/15 Javascript
深入理解JavaScript系列(45):代码复用模式(避免篇)详解
2015/03/04 Javascript
JS实现自动变化的导航菜单效果代码
2015/09/09 Javascript
javaScript实现可缩放的显示区效果代码
2015/10/26 Javascript
node.js文件上传处理示例
2016/10/27 Javascript
JS中数组重排序方法
2016/11/11 Javascript
获取url中用&amp;隔开的参数实例(分享)
2017/05/28 Javascript
Vue.js基础指令实例讲解(各种数据绑定、表单渲染大总结)
2017/07/03 Javascript
JavaScript判断日期时间差的实例代码
2018/03/01 Javascript
vue-cli3全面配置详解
2018/11/14 Javascript
video.js 一个页面同时播放多个视频的实例代码
2018/11/27 Javascript
Vue数据双向绑定底层实现原理
2019/11/22 Javascript
详解关于Vue单元测试的几个坑
2020/04/26 Javascript
[01:20:06]TNC vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Eclipse + Python 的安装与配置流程
2013/03/05 Python
Python多线程编程简单介绍
2015/04/13 Python
python中getaddrinfo()基本用法实例分析
2015/06/28 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
如何利用python制作时间戳转换工具详解
2018/09/12 Python
wxPython实现画图板
2020/08/27 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
2020/02/07 Python
详解CSS3中@media的实际使用
2015/08/04 HTML / CSS
初中同学聚会邀请函
2014/02/03 职场文书
2014年幼儿园植树节活动方案
2014/03/02 职场文书
工作业绩不及格检讨书
2014/10/28 职场文书
家长会主持词开场白
2015/05/29 职场文书