情怀麻将客户端初始化流程解析
1. 情怀麻将整体结构图
该部分展示了达达麻将客户端初始化时的整体架构图,包含了主要模块和流程。通过模块间的关系和功能划分,可以清晰了解客户端启动时的操作步骤。
客户端代码结构分析
scripts
文件夹结构:
- (1) 第三方代码库:包含
socket-io
等第三方网络通信库; - (2) Components:游戏中挂载到节点上的组件脚本;
- (3) 全局对象:放置在代码根目录中的全局管理对象。
Loading 场景
Loading Scene
挂载了对应的脚本文件:LoadingLogic.js
。
(1)扩展了String对象.format()函数;
String.prototype.format = function(args) {
if (arguments.length>0) {
var result = this;
if (arguments.length == 1 && typeof (args) == "object") {
for (var key in args) {
var reg=new RegExp ("({"+key+"})","g");
result = result.replace(reg, args[key]);
}
}
else {
for (var i = 0; i < arguments.length; i++) {
if(arguments[i]==undefined) {
return "";
}
else {
var reg=new RegExp ("({["+i+"]})","g");
result = result.replace(reg, arguments[i]);
}
}
}
return result;
}
else {
return this;
}
};
(2) 监听事件:push_need_create_role
,当收到该事件时,跳转进入创建角色场景。
(3) 若检测到当前环境非网页模式,则隐藏游客登录按钮。
(4) 若本地保存了微信账号信息,则直接执行自动登录操作;
(5) 处理微信账号登录的响应逻辑;
(6) 游客账号登录处理;
从 url
中获取用户的参数信息,如果存在,则使用用户传递的参数进行登录操作。
//游客登录
onBtnQuickStartClicked:function(){
cc.vv.userMgr.guestAuth();
},
获取本地存储的用户账号信息,若不存在,则根据当前时间戳随机生成一个新账号。
//游客验证登录
guestAuth:function(){
var account = cc.args["account"];
if(account == null){
account = cc.sys.localStorage.getItem("account");
}
if(account == null){
account = Date.now();
cc.sys.localStorage.setItem("account",account);
}
cc.vv.http.sendRequest("/guest",{account:account},this.onAuth);
},
将游客登录请求发送至服务器进行验证。
cc.vv.http.sendRequest("/guest",{account:account},this.onAuth);
userMgr
发送至账号服务器的响应地址为:/guest
。
账号服务器响应结果:返回 OK
状态、登录用户信息及大厅服务器的 IP 地址。
//游客登录服务器返回消息处理
onAuth:function(ret){
var self = cc.vv.userMgr;
if(ret.errcode !== 0){
console.log(ret.errmsg);
}
else{
self.account = ret.account;
self.sign = ret.sign;
cc.vv.http.url = "http://" + cc.vv.SI.hall;//大厅服务器的地址
self.login();
}
},
userMgr
:执行 login
函数进行登录操作。
login:function(){
var self = this;
var onLogin = function(ret){
if(ret.errcode !== 0){
console.log(ret.errmsg);
}
else{
if(!ret.userid){
//jump to register user info.
cc.director.loadScene("createrole");
}
else{
console.log(ret);
self.account = ret.account;
self.userId = ret.userid;
self.userName = ret.name;
self.lv = ret.lv;
self.exp = ret.exp;
self.coins = ret.coins;
self.gems = ret.gems;
self.roomData = ret.roomid;
self.sex = ret.sex;
self.ip = ret.ip;
cc.director.loadScene("hall");
}
}
};
cc.vv.wc.show("正在登录游戏");
cc.vv.http.sendRequest("/login",{account:this.account,sign:this.sign},onLogin);
},
发送登录请求至大厅服务器,由 client_server.js
提供的接口 /login
进行处理。
服务器返回登陆信息
//配置好响应请求:登录到大厅服务器;
app.get('/login',function(req,res){
if(!check_account(req,res)){
return;
}
var ip = req.ip;
if(ip.indexOf("::ffff:") != -1){
ip = ip.substr(7);
}
var account = req.query.account;
db.get_user_data(account,function(data){
if(data == null){
http.send(res,0,"ok");
return;
}
var ret = {
account:data.account,
userid:data.userid,
name:data.name,
lv:data.lv,
exp:data.exp,
coins:data.coins,
gems:data.gems,
ip:ip,
sex:data.sex,
};
//判断是否在游戏,还是在房间;则直接进当前房间
//一个账户,不能同时在两个房间里面游戏;
db.get_room_id_of_user(data.userid,function(roomId){
//如果用户处于房间中,则需要对其房间进行检查。 如果房间还在,则通知用户进入
if(roomId != null){
//检查房间是否存在于数据库中
db.is_room_exist(roomId,function (retval){
if(retval){
ret.roomid = roomId;
}
else{
//如果房间不在了,表示信息不同步,清除掉用户记录
db.set_room_id_of_user(data.userid,null);
}
http.send(res,0,"ok",ret);
});
}
else {
http.send(res,0,"ok",ret);
}
});
});
});
跳转并进入大厅场景进行后续操作。