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与Mysql的交互示例代码
Aug 18 NodeJs
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
Mar 18 NodeJs
NodeJS学习笔记之Connect中间件模块(二)
Jan 27 NodeJs
NodeJS学习笔记之Connect中间件应用实例
Jan 27 NodeJs
Nodejs中的this详解
Mar 26 NodeJs
nodejs实现发出蜂鸣声音(系统报警声)的方法
Jan 18 NodeJs
Nodejs下使用gm圆形裁剪并合成图片的示例
Feb 22 NodeJs
深入理解NodeJS 多进程和集群
Oct 17 NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 NodeJs
PHPStorm中如何对nodejs项目进行单元测试详解
Feb 28 NodeJs
Nodejs监控事件循环异常示例详解
Sep 22 NodeJs
NodeJS实现一个聊天室功能
Nov 25 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程序报date()警告的处理(date_default_timezone_set)
2013/10/22 PHP
PHP微信开发之微信消息自动回复下所遇到的坑
2016/05/09 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
php生成图片缩略图功能示例
2017/02/22 PHP
php7性能提升的原因详解
2019/10/13 PHP
js常用函数 不错
2006/09/08 Javascript
Jquery网页内滑动缓冲导航的实现代码
2015/04/05 Javascript
浅谈JavaScript中的Math.atan()方法的使用
2015/06/14 Javascript
Javascript简单改变表单元素背景的方法
2015/07/15 Javascript
JS实现点击上移下移LI行数据的方法
2015/08/05 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
2016/09/02 Javascript
8 行 Node.js 代码实现代理服务器
2016/12/05 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
bootstrap PrintThis打印插件使用详解
2017/02/20 Javascript
vue component组件使用方法详解
2017/07/14 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
vue实现图片按比例缩放问题操作
2020/08/11 Javascript
[16:21]教你分分钟做大人:圣堂刺客
2014/12/03 DOTA
python通过openpyxl生成Excel文件的方法
2015/05/12 Python
Python字典实现简单的三级菜单(实例讲解)
2017/07/31 Python
JSONLINT:python的json数据验证库实例解析
2017/11/28 Python
解决使用pycharm提交代码时冲突之后文件丢失找回的方法
2018/08/05 Python
使用Python如何测试InnoDB与MyISAM的读写性能
2018/09/18 Python
Python API 自动化实战详解(纯代码)
2019/06/11 Python
pandas的连接函数concat()函数的具体使用方法
2019/07/09 Python
详解Python并发编程之从性能角度来初探并发编程
2019/08/23 Python
python为什么会环境变量设置不成功
2020/06/23 Python
英国泰坦旅游网站:全球陪同游览,邮轮和铁路旅行
2016/11/29 全球购物
经济管理专业毕业生自荐信范文
2014/01/02 职场文书
大学生学业生涯规划
2014/01/05 职场文书
师范学院美术系毕业生自我鉴定
2014/01/29 职场文书
经典演讲稿汇总
2014/05/19 职场文书
设备管理实施方案
2014/05/31 职场文书
关于运动会广播稿50字
2014/10/18 职场文书
租赁协议书
2015/01/27 职场文书
三好学生竞选稿范文
2019/08/21 职场文书