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 相关文章推荐
使用forever管理nodejs应用教程
Jun 03 NodeJs
轻松创建nodejs服务器(4):路由
Dec 18 NodeJs
Nodejs学习笔记之NET模块
Jan 13 NodeJs
nodejs实现获取某宝商品分类
May 28 NodeJs
NodeJS使用formidable实现文件上传
Oct 27 NodeJs
详解NodeJS框架express的路径映射(路由)功能及控制
Mar 24 NodeJs
NodeJs中express框架的send()方法简介
Jun 20 NodeJs
nodejs+express搭建多人聊天室步骤
Feb 12 NodeJs
NodeJs搭建本地服务器之使用手机访问的实例讲解
May 12 NodeJs
nodejs中实现用户注册路由功能
May 20 NodeJs
Nodejs监听日志文件的变化的过程解析
Aug 04 NodeJs
通过实例了解Nodejs模块系统及require机制
Jul 16 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正则走开
2008/03/15 PHP
php array_push()数组函数:将一个或多个单元压入数组的末尾(入栈)
2011/07/12 PHP
PHP基础学习之流程控制的实现分析
2013/04/28 PHP
如何用php生成扭曲及旋转的验证码图片
2013/06/07 PHP
PHP文件锁函数flock()详细介绍
2014/11/18 PHP
项目中应用Redis+Php的场景
2016/05/22 PHP
Zend Framework基于Command命令行建立ZF项目的方法
2017/02/18 PHP
PHP的PDO预处理语句与存储过程
2019/01/27 PHP
php设计模式之观察者模式定义与用法经典示例
2019/09/19 PHP
phpinfo的知识点总结
2019/10/10 PHP
thinkphp5 框架结合plupload实现图片批量上传功能示例
2020/04/04 PHP
PHP与Web页面交互操作实例分析
2020/06/02 PHP
javascript通过class来获取元素实现代码
2013/02/20 Javascript
SpringMVC返回json数据的三种方式
2015/12/10 Javascript
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
javascript使用Promise对象实现异步编程
2016/03/01 Javascript
jQuery Jsonp跨域模拟搜索引擎
2017/06/17 jQuery
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
还不懂递归?读完这篇文章保证你会懂
2018/07/29 Javascript
Vue实现开关按钮拖拽效果
2020/09/22 Javascript
python书籍信息爬虫实例
2018/03/19 Python
pygame实现简易飞机大战
2018/09/11 Python
对pandas的行列名更改与数据选择详解
2018/11/12 Python
Python实现合并excel表格的方法分析
2019/04/13 Python
Python实现堡垒机模式下远程命令执行操作示例
2019/05/09 Python
十分钟搞定pandas(入门教程)
2019/06/21 Python
40行Python代码实现天气预报和每日鸡汤推送功能
2020/02/27 Python
python剪切视频与合并视频的实现
2020/03/03 Python
python爬虫基础之urllib的使用
2020/12/31 Python
西班牙香水和化妆品网上商店:Douglas
2017/10/29 全球购物
GWT (Google Web Toolkit)有哪些主要的原件组成?
2015/06/08 面试题
应届生服务员求职信
2013/10/31 职场文书
运动会跳远加油稿
2014/02/20 职场文书
一年级语文上册复习计划
2015/01/17 职场文书
长辈生日祝福语大全(72句)
2019/08/09 职场文书