[Mugeda HTML5技术教程之12]制作跨屏互动应用

mugeda动画平台还可以用来制作跨屏互动的动画应用,比如在PC端的大屏幕上显示动画的主界面,同时会显示出供手机扫描的二维码,手机扫描后会在手机上显示手机端动画界面。通过手机就可以和PC端的显示界面跨屏互动操作。这种动画应用在类似一些商场搞活动,或者户外宣传等常见可以使用。可以制作一对一玩的跨屏互动应用,也可以制作一对多玩(多个玩家同时玩)的跨屏互动应用。为了更好的理解跨屏互动应用的使用,本文档将通过一个简单的例子来演示跨屏动画的制作过程。


一、制作动画

1.PC端动画制作

a.在PC端,设置舞台吃尺寸为宽700、高480

b.在舞台中放在一个文字对象,并命名为info(用于显示连接及通讯信息)

c.在舞台中放在一个二维码的图片。(该二维码会在运行时被用真实的客户端连接的二维码替换)。给该图片命名qrc。

如图:


[Mugeda HTML5技术教程之12]制作跨屏互动应用

2.移动端动画制作

a.设置舞台尺寸为宽320、高416

b.在舞台中放一个用圆角矩形和文字组成的按钮,文字内容为connectPC。为该按钮设置动作为回调函数,触发方式:单击,函数名字:connectPC

如图:


[Mugeda HTML5技术教程之12]制作跨屏互动应用

c.用同步骤b相同的方式,再创建两个按钮,文字分别为sayHello、sayOK,函数名字分别为sayHello、sayOK。


最后舞台如图:


[Mugeda HTML5技术教程之12]制作跨屏互动应用

3.导入脚本

a.PC端,点击菜单栏的文件-》导入-》脚本。在弹出的导入脚本对话框中,勾选jquery.js、socketio.js、jquery.qrcode.js。点击确定。

如图:


[Mugeda HTML5技术教程之12]制作跨屏互动应用

b.用同样的方式在移动端导入socketio.js


导入文件说明:

跨屏动画通讯用到的Mugeda.Socket对象是基于socket.io封装的,所以PC端和移动端都需要导入socketio.js文件。PC端需要在游戏开始时动态更换二维码图片,所以需要导入与二维码相关的库文件jquery.js、jquery.qrcode.js


二、编写代码

用到的主要对象说明:

Mugeda.Socket对象,用于维护存连接相关数据和操作。

Mugeda.Socket.Client对象,用于维护存匿名认证客户的信息和操作。


实现通讯的主要步骤:

1.PC端先向服务器发起连接请求,产生连接

2.然后PC端通过侦听authorization事件获取到非认证用户(即客户端)带request和token的地址,进而通过replaceQrcode将动画中的图片对象替换为二维码。

3.玩家通过手机等移动设备扫描二维码,在自己的设备中打开客户端,

4.客户端向服务器发起连接请求,并产生连接

5.客户端与PC端通讯


连接服务器

通过实例化Mugeda.Socket对象,产生连接。Mugeda.Socket类的构造函数为:

Mugeda.Socket(request, token, isRegisteredUser, guestURL, server, port)

其中:

request:{string}请求字符串

token:{string}令牌

isRegisteredUser:{bool,缺省false}是否为认证客户。

server:{string,缺省为SERVER_URL常量} 服务器地址

port:{string,缺省为SERVER_PORT常量}服务器端口


1. 认证用户的实例化:认证用户拥有request、token以及非认证客户的游戏地址url,使用以下方式实例化Mugeda.Socket

var a = new Mugeda.Socket(request, token, true, url)


2. 匿名用户的实例化:匿名用户通常来自二维码的扫描,网页地址中包含request和token,可通过以下方式直接从地址中获取

var a = new Mugeda.Socket()

a.getReqestAndTokenFromUrl()


实例化Mugeda.socket对象后,认证用户和匿名用户都使用以下形式的方式连接服务器。

a.connect(function(err){})

在回调函数中,查看err字符串,如果为空,说明连接成功,否则,可能是token不对。


认证用户(即PC端)获取匿名用户(即客户端)队列

认证用户通过a.clients获取匿名用户数组,最早连接的用户在队列前面。数组的每一个元素都为Mugeda.Socket.Client实例。


侦听cliententer和clientleave事件,这两个事件在匿名用户连接和断开时刻发生。

a.addEventListener(‘cliententer‘, function(client){

   

})


a.addEventListener(‘clientleave‘, function(client){

   

})


认证用户对匿名用户的操作

1. 发送消息

对Client实例发送消息:

client.send(event, data, callback)

其中:

event{stirng},自定义事件名

data{string、number、object、null}发送的数据,其中number和string在发送前会被转化为{data: string}或{data.number}的形式。

callback{function},对需要匿名用户立即回复的情形,callback函数会传递到匿名客户,由匿名客户直接调用。


对全体Client发送消息

a.sendAll(event, data)

参数含义同上。


2. 检测Client是否有回应

client.checkAvailable(callback, timeout)

其中:

callback{function}回调

timeout{number,缺省10}超时秒数

检测非认证用户是否有回应,若有,callback回调,回调函数的第一个参数为true;否则,timeout后,callback回调,回调函数的第一个参数为false。


3. 不断检测Client的存在性

client.checkAvailableContinuously(callback, interval, timeout)

匿名用户将每隔interval秒(缺省5秒)向认证用户发送一个心跳包,当timeout(缺省20秒)后,callback回调且第一个参数为false。


4. 得到Client实例在a.clients数组中的Index

a.getClientIndexByUserId(client.user)


匿名用户的操作

1. 发送消息

a.send(event, data, callback)

参数含义同上。


2. 检测与服务器的连接讯速度

a.benchmark(callback, times, timeout)

匿名用户多次向服务器发送数据,服务器收到后返回数据,测试数据来回所用时间/2。

其中:

callback{function}回调函数,格式为function(averageTime, timeArray),其中timeArray记录了每一次的时间,averageTime为平均时间,单位均为ms。

times{number,缺省为3}测试的次数。

timeout{number,缺省2000}超时的时间,单位ms。


其他事件

1. 认证何用户消息侦听

a.addEventListener(‘message‘, function(client, event, data, callback){

    console.log(event, data)

})

侦听匿名用户通过a.send发送的消息。client为发送消息的用户的Client对象,其余参数同上。


2. 匿名用户消息侦听

a.addEventListener(‘message‘, function(event, data, callback){

    console.log(event, data)

})

形式与上面类似,但是回调少了client参数。


3. 匿名用户侦听PC断开事件

a.addEventListener(‘disconnected’, function(){

})



1.PC端代码


a.定义SocketComm对象

var mugeda=Mugeda.getMugedaObject();

var scene = null;

var info = null;

var isConnect = false;

var SocketComm = function(){//定义SocketComm对象

   this.socket = null;

   this.scene = null;

   this.connected = null;

   this.name = (new Date()).getTime();

   var _=this;


   this.setup = function(callback, scene){

       connect = new Mugeda.Socket(‘dejipuzzle‘,‘d2f7335a19ecc3ed2a0cbe66580fdd05‘, true,

       ‘https://cn.mugeda.com/client/preview_css3.html?id=d20c8a20‘);//通过实例化Mugeda.Socket类,产生连接

       this.scene = scene;

       connect.connect(function(err){//认证用户(PC端)连接服务器

           if(err){

               Mugeda.log(err);

           }

           else{

               _.connected = true

               callback({

                   event: ‘connect‘

               })

           }

       })

       connect.addEventListener(‘authorization‘,function(){//认证用户(PC端)侦听authorization事件

           var replaceQrcode = function(imgObj, url) {//将动画中的图片对象替换为二维码

               var cvs, height, width;

               var holder = document.createElement(‘div‘);

               holder.width = imgObj.width;

               holder.height = imgObj.height;

               if (url) {

                   $(holder).empty().qrcode({

                       text: url,

                       ecLevel: ‘L‘

                   });

                   width = imgObj.width;

                   height = imgObj.height;

                   $(imgObj.dom).css(‘background-image‘, ‘none‘);

                   $(imgObj.dom).css(‘background-color‘, ‘white‘);

                   $(imgObj.dom).css(‘padding‘, ‘4px‘);

                   cvs = $(holder).find(‘canvas‘);

                   cvs.css(‘margin‘, ‘2px‘);

                   cvs.css(‘width‘, (width - 4) + ‘px‘);

                   cvs.css(‘height‘, (height - 4) + ‘px‘);

                   imgObj.dom.src = cvs[0].toDataURL();

               }

           };

           var qrc = scene.getObjectByName(‘qrc‘);//获取舞台中原来的二维码图片对象

           replaceQrcode(qrc, this.clientURL);//通过this.clientURL获取非认证用户带request和token的地址,并替换二维码

           console.log(this.clientURL);

       })

       connect.addEventListener(‘cliententer‘, function(client){//侦听cliententer在匿名用户连接时触发。

           info.text = ("用户接入成功。");

            console.log(client);

       })

       connect.addEventListener(‘clientleave‘, function(client){//侦听clientleave事件,在匿名用户断开时触发。

           info.text = ("用户离开。");

            console.log(client);

       })

       connect.addEventListener(‘disconnect‘, function () {//侦听disconnect事件

           callback({

               ‘event‘:‘disconnect‘

           });

           _.connected = false;

           isConnect = false;

       });

       connect.addEventListener(‘message‘, function(client, event, data){

           //侦听匿名用户通过a.send发送的消息。并调用在setup的回调函数中处理

           callback({

               ‘event‘:event,

               ‘client‘:client,

               ‘data‘:data

           });

       })

   };

}


b.在renderReady监听回调中调用SocketComm实例的setup方法

var cross = new SocketComm();//实例化SocketComm对象

mugeda.addEventListener("renderReady", function () {

   scene = mugeda.scene;

   info = scene.getObjectByName(‘info‘);//获取info对象,显示连接状态和移动端发来的消息

   

   var processMessage = function(msg){//setup处理消息的回调函数

       if(!mugeda || !scene)

           return;

       msg = msg || {};

       if(msg.event == "connect"){

           info.text = ("连接成功。等待用户接入。");

       }

       else if(msg.event == "disconnect"){

           info.text = ("连接断开");

       }

       else if(msg.event == "update"){

           console.log(msg.data);

       }

       else if(msg.event == ‘mobilemessage‘) {//处理匿名用户(客户端)发来的消息

           var data = msg.data;

           info.text = data;

       }

   }

   

   cross.setup(processMessage, scene);//调用SocketComm实例的setup方法

});


2.移动端代码

var mugeda=Mugeda.getMugedaObject();

mugeda.addEventListener("renderReady", function () {

   scene = mugeda.scene;

   var hello = scene.getObjectByName(‘hello‘);//获取sayHello按钮对象

   var ok = scene.getObjectByName(‘ok‘);//获取sayOK按钮对象

   var connectButton = scene.getObjectByName(‘connect‘);//获取connectPC按钮对象

   hello.left = -700;//sayHello按钮移到舞台外

   ok.left = -700;//sayOK按钮移到舞台外

   

   var socket = new Mugeda.Socket();//实例化Mugeda.Socket对象

   socket.getReqestAndTokenFromUrl();//获取request和token

   

   socket.addEventListener(‘authorization‘, function(){//侦听authorization事件

       console.log(this.clientURL);

   });

   socket.addEventListener(‘message‘, function(event, data, callback){//侦听PC端通过send发送的消息

       console.log(event, data);

       processMessage(event,data, callback);

   })

   socket.addEventListener(‘disconneted‘, function(){//匿名用户(移动端)侦听PC断开事件

       console.log(‘disconneted‘);

       error.text = "连接失败,请重新刷二维码";

       scene.gotoAndPause(errorFrame);

   })


   window.connectPC = function(){//connectPC按钮的回调函数

       socket.connect(function(err){//回调中,查看err字符串,为空,说明连接成功。

           if(err){

   console.log(err);

   if(err.indexOf && err.indexOf(‘handshake‘)>=0){

       console.log("无效的二维码。请重新刷二维码。")

               }

           }

           else{

               console.log(‘connect OK‘);

               connectButton.left = -700;//connectPC按钮移到舞台外

               hello.left = 76;//sayHello按钮移到舞台内

               ok.left = 76;//sayOK按钮移到舞台内

           }

       });//匿名用户(移动端)连接服务器

   };

   window.sayHello = function(){//sayHello按钮的回调函数

       socket.send(‘mobilemessage‘, "Hello,World!");//向PC端发送消息

   };

   window.sayOK = function(){//sayOK按钮的回调函数

       socket.send(‘mobilemessage‘, "I‘m OK!");//向PC端发送消息

   };

});


二、运行程序

先运行PC端程序,用移动设备扫描PC端的二维码来运行移动端。

移动端点击connectPC按钮连接服务器。

点击sayHello和sayOK按钮,可以在PC端看到交互结果。


实例预览:

https://cn.mugeda.com/client/preview_css3.html?id=d8297427


总结,该例子只是用了最简单的示例来演示怎么建立一个最简单(Hello World)的跨屏互动应用。具体到商业级的产品的肯定还需要根据具体的产品需求制作更加丰富的动画内容。后面章节中会有一些案例分析,其中有一篇是是一款跨屏动画的案例分析。敬请期待后续更多文章推出。感觉好的请帮忙点赞^_^

[Mugeda HTML5技术教程之12]制作跨屏互动应用

上一篇:js MD5加密后的字符串


下一篇:关于CSS选择器的效率问题