原理讲解
图讲解 server端 server端主要做信息接收和传递以及一些处理。可以理解为一个中转站。
show端 show端就是一个展示端,比如小霸王游戏机中需要的显示器。
control端 control端就好像小霸王游戏中的手柄,来操作游戏。
通信协议websocket
流程讲解
show端。生成一个随机数(xxx),作为自己唯一的ID验证。同时连接server服务器并把自己ID传输过去,标记此WebSocket连接为show端。
server端,记录步骤1中,连接过来的show端,同时记录ID(xxx)和身份标记show端。
手机扫描show端游戏页面的二维码(二维码包含show端生成的随机数ID),打开control端,连接server服务器端。
server端,对步骤3连接的WebSocket进行判断,通过ID,把show端和control端连接起来。同时标记此WebSocket为control端。
这两个WebSocket连接就连接起来了,就可以进行通信,信息数据交流了。
说明:为什么要有唯一的ID呢,因为这里的demo是一个show端对应一个control端的需求。可以满足多个人,同时打开show端,然后拿起手机扫描二维码,进行游戏操作。(这里如果想做多人控制一个比如,多人同时摇手机,给加油鼓劲。)
服务端代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 var controlArr = new Array();//记录所有control端的连接 var showArr = new Array();//记录所有show端的连接 var ws = require('./node_modules/nodejs-websocket'); var server = ws.createServer(function (connection) { connection.data = null; connection.type = null; console.log("new connetion"); console.log("连接数connection = " + server.connections.length); //接收数据 connection.on("text", function (str) { var data = JSON.parse(str); console.log("userid =",data.userid,"type =",data.type); if (connection.data === null) { /** * 1.判断链接是control端还是show端 * 2.如果是control端,且是第一次发送消息,什么都不做 * 3.如果是control端,不是第一次发送消息,那给所有的show端发送消息请求,游戏开始。 * 4.show端接受消息,对应的唯一show端,做相对应的处理,并返回消息。 * 5.游戏正式开始 */ if (data.type == "control") { controlArr.push(connection); } else if (data.type == "show") { showArr.push(connection); } connection.userid = data.userid; connection.type = data.type; //如果是第一次发送消息什么都不做。 if (data.event == "HelloWebSocket") { return; } //如果发送消息的是控制端 if (data.type == "control") { var msg1 = { userid: connection.userid, type: connection.type, event: data.event, leftOrRight: data.leftOrRight }; var sendMsg1 = JSON.stringify(msg1); sendMessageToShow(sendMsg1); } //如果发送消息的是show端 if(data.type == "show") { var msg2 = { userid: connection.userid, type: connection.type, event: data.event, leftOrRight: data.leftOrRight }; var sendMsg2 = JSON.stringify(msg2); sendMessageToControl(sendMsg2); } } else { broadcast("[" + connection.userid + "] " + connection.userid); console.log("connection.userid = " + connection.userid); } }); connection.on("close", function () { var data = { userid: connection.userid, type: connection.type, event: "leave", leftOrRight: "null" }; var str = JSON.stringify(data); broadcast(str); console.log("userid =",data.userid,"type =",data.type," close"); console.log("连接数connection = " + server.connections.length); }); connection.on("error", function () { if (connection.type == "control") { var indexControl = controlArr.indexOf(connection); if (indexControl != -1) { controlArr.splice(indexControl, 1); } } if (connection.type == "show") { var indexShow = controlArr.indexOf(connection); if (indexShow != -1) { controlArr.splice(indexShow, 1); } } }); }) server.listen(8001); /** * * 发送消息到所有连接 */ function broadcast(str) { server.connections.forEach(function (connection) { connection.sendText(str); }) } /** * * 发送消息到control(控制)端 */ function sendMessageToControl(str) { server.connections.forEach(function (connection) { if (connection.type == "control") { connection.sendText(str); } }) } /** * * 发送消息到show(表现)端 */ function sendMessageToShow(str) { server.connections.forEach(function (connection) { if (connection.type == "show") { connection.sendText(str); } }) } console.log("服务器启动");
模块介绍 这里使用的是别人封装好的模块nodejs-websocket ,点击链接,可以查看详细的API介绍和使用方法的介绍。
这里就只介绍整个操作流程,从创建过程到代码的编写。请先确保电脑已经安装nodejs,如果不会安装请谷歌或者百度,官网链接
安装之后,全局安装nodejs-websocket。在终端执行sudo npm install nodejs-websocket -g
。更详细的教程查看这里
我这里使用的是Mac系统,如果不是Mac系统,大家可以对比一下查看。
操作步骤 1.安装依赖模块 打开终端,输入cd,然后拖拽文件目录,回车
输入mkdir crossscreen && cd crossscreen
,这里是创建crossscreen文件夹并进入crossscreen文件夹
输入mkdir server && cd server
,这里是创建server文件夹并进入server文件夹
输入npm install nodejs-websocket
,然后回车,安装成功终端应该是这样的
系统文件目录应该是这样的
这里说一下,有的Mac可能执行的图不是和我这里表现的一样,因为我这里安装了zsh
2.编写server.js代码 因为这里编辑纯js代码,这里使用的编辑器是VS code.
把server文件夹下内容导入VS code,然后创建server.js文件。
接下来,大家就可以把代码拷贝到我们创建的server.js里面。
如果想运行server.js ,直接在终端输入node server.js
中间隔着空格,记住要在server文件夹下,或者直接拖拽到终端也行。 结果应该是这样的。
3.代码讲解 1 var ws = require('./node_modules/nodejs-websocket');
引用依赖库
1 2 3 4 5 var server = ws.createServer(function (connection) { }) server.listen(8001);
创建server,监听8001端口。
1 2 3 connection.on("text", function (str) {}); connection.on("close", function (str) {}); connection.on("error", function (str) {});
监听传送过来的数据 监听连接关闭 监听连接错误
扩展思路 数据格式 数据格式,这里使用的是使用的JSON来传送数据。如果想在egret中使用protobuf
,请查看这里
因为这里比较简单所以就是定义的如下格式,这个可以根据自己的习惯来定。
1 2 3 4 5 6 { "userid": "", "type": "", "event": "", "data": "" }
声明类 Message
1 2 3 4 5 6 7 8 9 10 11 12 class Message { constructor(userid:string,event:string,type:string,data:string) { this.userid = userid; this.type = type; this.event = event; this.data = null; } userid:string = null; type:string = null;// "show" or "control" event:string = null;// "gameStart" data:string = null;//“left”,“right” }
利用JSON.parse(),JSON.stringify()
来转换。
WebSocket 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class WebSocket { constructor() { } static instance: WebSocket = new WebSocket(); webSocket: egret.WebSocket = new egret.WebSocket(); static getInstance(): MyWebSocket { return WebSocket.instance; } //初始化 init(url:string,port:any): void { //接收消息 this.webSocket.addEventListener(egret.ProgressEvent.SOCKET_DATA, this.onReceiveMessage, this); //连接 this.webSocket.addEventListener(egret.Event.CONNECT, this.onSocketOpen, this); this.webSocket.connect(url, port); //添加链接关闭侦听,手动关闭或者服务器关闭连接会调用此方法 this.webSocket.addEventListener(egret.Event.CLOSE, this.onSocketClose, this); //添加异常侦听,出现异常会调用此方法 this.webSocket.addEventListener(egret.IOErrorEvent.IO_ERROR, this.onSocketError, this); } /** * 连接成功 */ private onSocketOpen(): void { var cmd = new Message(GlobalData.userid,"HelloWebSocket","show","null"); var msg = JSON.stringify(cmd); console.log("连接成功,发送数据:" + msg); this.webSocket.writeUTF(msg); } /** * 传送数据 */ sendMesssage(str:string) { this.webSocket.writeUTF(str); this.webSocket.flush(); } /** * 接收消息 */ onReceiveMessage(e: egret.Event): void { var msg = this.webSocket.readUTF(); var event = new game.SceneEvent(game.SceneEvent.ChangeScene);//自定义的事件来传送数据 event.eventData = JSON.parse(msg); //转换字符串为JSON格式 if(GlobalData.userid == event.eventData.userid)// 判断是否是属于同一组连接 game.ViewManager.getInstance().dispatchEvent(event) } private onSocketClose(): void { console.log("WebSocketClose"); } private onSocketError(): void { console.log("WebSocketError"); } }
更多的使用方式查看API ;
二维码 二维码使用的库是https://github.com/cxh612/qrCode
具体的使用功能可以查看readme.md
解析URL API 使用egret.getOption
扩展思路
手机做遥感,pc做显示器。
体感游戏,手机做感应器,pc做显示端。
两个手机,情侣之间,朋友之间的对抗赛,同步屏幕操作。
代码部署 说在之前 因为个人的一些习惯癖好,不喜欢PHP,写起来感觉好难受。再一个Node.js又比较火,又可以使用TypeScript来编写,于是很愉快的决定使用Node.js了。写玩之后,发现找一个支持node.js的服务器好难,在这个上面折腾了好久。游戏1天半差不多就写完了,结果部署折腾了快一个星期的时间,因为不是很懂服务器,没有办法。最后只好找同学来指点一下,然后就自己折腾去了。最后买了阿里云。
服务器 我这里购买的是阿里云,配置的镜像是Ubuntu 14.04 64位。因为个人相比而言,相对于来说偏向Linux服务器,对于Ubuntu 更熟悉一些。这个根据个人的习惯爱好就行。有兴趣的,可以先在本地电脑安装虚拟机,然后安装Ubuntu。如果你不愿意折腾,那就直接购买就好了。如果购买阿里云,可以到网上找一些优惠码,这个阿里云还是固定发送一些的。我的推荐码xy0glk 阿里云购买地址
安装Node.js 因为只当服务器使用,这里说一下安装Node.js,在Ubuntu下,node 这个命令可能被占用,一般使用nodejs 命令.如果不想换,继续使用node命令,那么查看这里 。具体的操作可以查看这里
sftp上传 这里使用的是Yummy FTP,购买阿里云之后会给你发一份邮件给你。
输入IP,用户名,端口号,然后就可以连接了。
然后上传服务器端代码
然后进入终端连接,启动服务器端代码,更详细的教程