#推荐
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

2024-10-01 1,447

要点

  1. 情怀麻将版图回顾
  2. 情怀麻将游戏服务器注册至大厅,实现负载配置
  3. 客户端发起创建房间请求
  4. 服务器响应创建房间请求
  5. 客户端登录并连接至游戏服务器

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

查找客户端发送逻辑

  1. 定位创建按钮,并追踪其关联的函数:hall.js 中的 onCreateRoomClicked

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

btn_create_room 组件按钮 —— 对应的 JS 函数为 onCreateRoomClicked

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

 onCreateRoomClicked:function(){
        if(cc.vv.gameNetMgr.roomId != null){
            cc.vv.alert.show("提示","房间已经创建!\n必须解散当前房间才能创建新的房间");
            return;
        }
        console.log("onCreateRoomClicked");
        this.createRoomWin.active = true;   
    },

查找 this.createRoomWin.active = true; 的用途 —— 该语句用于 UI 界面的显示控制,但其具体逻辑未在代码中实现处理。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

其作用是激活创建房间的 UI 组件。

  1. 显示创建房间界面,并查找该界面对应的挂载脚本:createRoom.js

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析 Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

CreateRoom.js的onBtnOK();

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

3创建房间列表,并配置房间参数。createRoom 函数将这些参数通过 http 请求发送至大厅服务器。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

 createRoom:function(){
        var self = this;
        var onCreate = function(ret){
            if(ret.errcode !== 0){
                cc.vv.wc.hide();
                //console.log(ret.errmsg);
                if(ret.errcode == 2222){
                    cc.vv.alert.show("提示","房卡不足,创建房间失败!");  
                }
                else{
                    cc.vv.alert.show("提示","创建房间失败,错误码:" + ret.errcode);
                }
            }
            else{
                cc.vv.gameNetMgr.connectGameServer(ret);
            }
        };
        
        var difen = 0;
        for(var i = 0; i < self._difenxuanze.length; ++i){
            if(self._difenxuanze[i].checked){
                difen = i;
                break;
            }
        }
        
        var zimo = 0;
        for(var i = 0; i < self._zimo.length; ++i){
            if(self._zimo[i].checked){
                zimo = i;
                break;
            }     
        }
 
        var huansanzhang = self._wanfaxuanze[0].checked;        
        var jiangdui = self._wanfaxuanze[1].checked;
        var menqing = self._wanfaxuanze[2].checked;
        var tiandihu = self._wanfaxuanze[3].checked;
        
        var type = 0;
        for(var i = 0; i < self._leixingxuanze.length; ++i){
            if(self._leixingxuanze[i].checked){
                type = i;
                break;
            }     
        }
        
        if(type == 0){
            type = "xzdd";
        }
        else{
            type = "xlch";
        }
        
        var zuidafanshu = 0;
        for(var i = 0; i < self._zuidafanshu.length; ++i){
            if(self._zuidafanshu[i].checked){
                zuidafanshu = i;
                break;
            }     
        }
        
        
        var jushuxuanze = 0;
        for(var i = 0; i < self._jushuxuanze.length; ++i){
            if(self._jushuxuanze[i].checked){
                jushuxuanze = i;
                break;
            }     
        }
        
        var dianganghua = 0;
        for(var i = 0; i < self._dianganghua.length; ++i){
            if(self._dianganghua[i].checked){
                dianganghua = i;
                break;
            }     
        }
        
        var conf = {
            type:type,
            difen:difen,
            zimo:zimo,
            jiangdui:jiangdui,
            huansanzhang:huansanzhang,
            zuidafanshu:zuidafanshu,
            jushuxuanze:jushuxuanze,
            dianganghua:dianganghua,
            menqing:menqing,
            tiandihu:tiandihu,   
        }; 
        
        var data = {
            account:cc.vv.userMgr.account,
            sign:cc.vv.userMgr.sign,
            conf:JSON.stringify(conf)
        };
        console.log(data);
        cc.vv.wc.show("正在创建房间");
        cc.vv.http.sendRequest("/create_private_room",data,onCreate);   
    }

将参数组合成一个完整的配置对象 conf,并发送至服务器,请求创建房间。

javascript
cc.vv.http.sendRequest("/create_private_room", data, onCreate);

将配置转换为 JSON 字符串格式:conf: JSON.stringify(conf)

请求提交至:客户端 Client ——> 大厅服务器的 HTTP client_service 服务。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

4:响应的地址为:/create_private_room,数据内容为房间创建参数,返回结果通过 onCreate 函数进行回调处理。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

服务器接收到 client 发送的 data 后,根据请求内容执行相应的逻辑处理操作。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

查找服务器响应处理:

  1. hall_server:配置的 "/create_private_room" 路由;
  • 从数据库中查询玩家数据:
javascript
db.get_user_data(account, function(data) {
  1. 处理步骤:
    (1) 查询数据库,获取账号信息: db.js 中的 get_user_data 函数。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

gems:房卡数据

(2)检测玩家是否已经在一个房间游戏: get_room_id_of_user,只有没有在游戏才可以创建;

//验证玩家状态
		db.get_room_id_of_user(userId,function(roomId){
			if(roomId != null){
				http.send(res,-1,"user is playing in room now.");
				return;
			}
			//创建房间

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

(3)room_service.js 的createRoom:Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

1>找到最小的负载的 server ;

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

2> 获取用户的gems房卡的数目;

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

优化点:这里经过了2次查询房卡,可以进行系统优化;

然后执行room_service.js的createRoom函数:

//创建房间
			room_service.createRoom(account,userId,conf,function(err,roomId){

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

然后消息又发送到http服

http.get(serverinfo.ip,serverinfo.httpPort,“/create_room”,reqdata,function(ret,data){

流程描述:通过最小负载的游戏服务器进行房间创建请求,并通过大厅服务器的 room_service 定位到相应的游戏服务器,由其 http_service 进行开房处理。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

3>麻将服务器http_server, create_room URL响应;

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

4> roomMgr创建一个createRoom:

roomMgr.createRoom(userId,conf,gems,serverIp,config.CLIENT_PORT,function(errcode,roomId){

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

/游戏服开房逻辑
exports.createRoom = function(creator,roomConf,gems,ip,port,callback){
	if(
		roomConf.type == null
		|| roomConf.difen == null
		|| roomConf.zimo == null
		|| roomConf.jiangdui == null
		|| roomConf.huansanzhang == null
		|| roomConf.zuidafanshu == null
		|| roomConf.jushuxuanze == null
		|| roomConf.dianganghua == null
		|| roomConf.menqing == null
		|| roomConf.tiandihu == null){
		callback(1,null);
		return;
	}
 
	if(roomConf.difen < 0 || roomConf.difen > DI_FEN.length){
		callback(1,null);
		return;
	}
 
	if(roomConf.zimo < 0 || roomConf.zimo > 2){
		callback(1,null);
		return;
	}
 
	if(roomConf.zuidafanshu < 0 || roomConf.zuidafanshu > MAX_FAN.length){
		callback(1,null);
		return;
	}
 
	if(roomConf.jushuxuanze < 0 || roomConf.jushuxuanze > JU_SHU.length){
		callback(1,null);
		return;
	}
	
	//需要消耗多少房卡
	var cost = JU_SHU_COST[roomConf.jushuxuanze];
	if(cost > gems){
		callback(2222,null);
		return;
	}
 
	var fnCreate = function(){
		var roomId = generateRoomId();
		if(rooms[roomId] != null || creatingRooms[roomId] != null){
			fnCreate();
		}
		else{
			creatingRooms[roomId] = true;
			db.is_room_exist(roomId, function(ret) {
 
				if(ret){
					delete creatingRooms[roomId];
					fnCreate();
				}
				else{
					var createTime = Math.ceil(Date.now()/1000);
					var roomInfo = {
						uuid:"",
						id:roomId,
						numOfGames:0,
						createTime:createTime,
						nextButton:0,
						seats:[],
						conf:{
							type:roomConf.type,
							baseScore:DI_FEN[roomConf.difen],
						    zimo:roomConf.zimo,
						    jiangdui:roomConf.jiangdui,
						    hsz:roomConf.huansanzhang,
						    dianganghua:parseInt(roomConf.dianganghua),
						    menqing:roomConf.menqing,
						    tiandihu:roomConf.tiandihu,
						    maxFan:MAX_FAN[roomConf.zuidafanshu],
						    maxGames:JU_SHU[roomConf.jushuxuanze],
						    creator:creator,
						}
					};
					
					if(roomConf.type == "xlch"){
						roomInfo.gameMgr = require("./gamemgr_xlch");
					}
					else{
						roomInfo.gameMgr = require("./gamemgr_xzdd");
					}
					console.log(roomInfo.conf);
					
					for(var i = 0; i < 4; ++i){
						roomInfo.seats.push({
							userId:0,
							score:0,
							name:"",
							ready:false,
							seatIndex:i,
							numZiMo:0,
							numJiePao:0,
							numDianPao:0,
							numAnGang:0,
							numMingGang:0,
							numChaJiao:0,
						});
					}
					
 
					//写入数据库
					var conf = roomInfo.conf;
					db.create_room(roomInfo.id,roomInfo.conf,ip,port,createTime,function(uuid){
						delete creatingRooms[roomId];
						if(uuid != null){
							roomInfo.uuid = uuid;
							console.log(uuid);
							rooms[roomId] = roomInfo;
							totalRooms++;
							callback(0,roomId);
						}
						else{
							callback(3,null);
						}
					});
				}
			});
		}
	}
 
	fnCreate();
};

a: 检查并验证创建房间的参数;

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

支持两种麻将玩法:血战到底血流成河

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

b: 检查房卡余额:

javascript
var cost = JU_SHU_COST[roomConf.jushuxuanze];

c: 执行房间创建:

javascript
db.create_room(roomInfo.id, roomInfo.conf, ip, port, createTime, function(uuid) {
  1. URL 响应返回后进入 enterRoom

roommgr.js 中的 exports.createRoom 将通过 callback(0, roomId);roomId 传递给 http_service

随后将 roomId 返回:

javascript
http.send(res, 0, "ok", { roomid: roomId });
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

hall_service.js 获取回调的 roomId 后,开始执行进入房间的逻辑:

javascript
room_service.enterRoom(userId, name, roomId, function(errcode, enterInfo) {
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析
在游戏中尽量减少使用 console.log 进行日志打印操作;频繁的日志输出会占用服务器资源,可能导致服务器出现卡顿情况。建议使用异步日志系统,将日志处理独立出来,避免阻塞服务器的主进程,从而提升服务器性能。

(4) room_service.js 的enterRoom:

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析


exports.enterRoom = function(userId,name,roomId,fnCallback){
	var reqdata = {
		userid:userId,
		name:name,
		roomid:roomId
	};
	reqdata.sign = crypto.md5(userId + name + roomId + config.ROOM_PRI_KEY);
 
	var checkRoomIsRuning = function(serverinfo,roomId,callback){
		var sign = crypto.md5(roomId + config.ROOM_PRI_KEY);
		http.get(serverinfo.ip,serverinfo.httpPort,"/is_room_runing",{roomid:roomId,sign:sign},function(ret,data){
			if(ret){
				if(data.errcode == 0 && data.runing == true){
					callback(true);
				}
				else{
					callback(false);
				}
			}
			else{
				callback(false);
			}
		});
	}
 
	var enterRoomReq = function(serverinfo){
		http.get(serverinfo.ip,serverinfo.httpPort,"/enter_room",reqdata,function(ret,data){
			console.log(data);
			if(ret){
				if(data.errcode == 0){
					db.set_room_id_of_user(userId,roomId,function(ret){
						fnCallback(0,{
							ip:serverinfo.clientip,
							port:serverinfo.clientport,
							token:data.token
						});
					});
				}
				else{
					console.log(data.errmsg);
					fnCallback(data.errcode,null);
				}
			}
			else{
				fnCallback(-1,null);
			}
		});
	};
 
	var chooseServerAndEnter = function(serverinfo){
		serverinfo = chooseServer();
		if(serverinfo != null){
			enterRoomReq(serverinfo);
		}
		else{
			fnCallback(-1,null);					
		}
	}
 
	db.get_room_addr(roomId,function(ret,ip,port){
		if(ret){
			var id = ip + ":" + port;
			var serverinfo = serverMap[id];
			if(serverinfo != null){
				checkRoomIsRuning(serverinfo,roomId,function(isRuning){
					if(isRuning){
						enterRoomReq(serverinfo);
					}
					else{
						chooseServerAndEnter(serverinfo);
					}
				});
			}
			else{
				chooseServerAndEnter(serverinfo);
			}
		}
		else{
			fnCallback(-2,null);
		}
	});
};

1> 麻将服务器http_server, enter_room URL响应

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

//加入房间
app.get('/enter_room',function(req,res){
	var userId = parseInt(req.query.userid);
	var name = req.query.name;
	var roomId = req.query.roomid;
	var sign = req.query.sign;
	if(userId == null || roomId == null || sign == null){
		http.send(res,1,"invalid parameters");
		return;
	}
 
	var md5 = crypto.md5(userId + name + roomId + config.ROOM_PRI_KEY);
	console.log(req.query);
	console.log(md5);
	if(md5 != sign){
		http.send(res,2,"sign check failed.");
		return;
	}
 
	//安排玩家坐下
	roomMgr.enterRoom(roomId,userId,name,function(ret){
		if(ret != 0){
			if(ret == 1){
				http.send(res,4,"room is full.");
			}
			else if(ret == 2){
				http.send(res,3,"can't find room.");
			}	
			return;		
		}
 
		var token = tokenMgr.createToken(userId,5000);
		http.send(res,0,"ok",{token:token});
	});
});

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

大厅服room_service.js拿到token,游戏服http_service发过来的;

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

3> 大厅服务组合麻将服务器的ip, port, token, 房间ID 回给客户端

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

查找客户端处理返回结果:

  1. 获取到麻将服务器的 ipporttokentime 参数;
    对应客户端的创建消息回调函数进行处理。

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

获取服务器返回信息后,启动游戏连接操作:

javascript
cc.vv.gameNetMgr.connectGameServer(ret);
2:连接麻将服务器:定位至 GameNetManager.js 中的 connectGameServer 方法。
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析
connectGameServer:function(data){
        this.dissoveData = null;
        cc.vv.net.ip = data.ip + ":" + data.port;
        console.log(cc.vv.net.ip);
        var self = this;
 
        var onConnectOK = function(){
            console.log("onConnectOK");
            var sd = {
                token:data.token,
                roomid:data.roomid,
                time:data.time,
                sign:data.sign,
            };
            cc.vv.net.send("login",sd);
        };
        
        var onConnectFailed = function(){
            console.log("failed.");
            cc.vv.wc.hide();
        };
        cc.vv.wc.show("正在进入房间");
        cc.vv.net.connect(onConnectOK,onConnectFailed);
    }
  1. 连接成功后,向游戏服务器发送登录指令:通过 socket.io 发送登录命令 login

javascript

cc.vv.net.send("login", sd);
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析
socket.emit('login_result',ret);
 
//通知其它客户端
userMgr.broacastInRoom('new_user_comes_push',userData,userId);

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

  1. 服务器发送登录结果命令 login_result 到客户端,并由客户端进行保存。

GameNetMgr.js 中使用 initHandlers 方法处理:

javascript
cc.vv.net.addHandler("login_result", function(data) {
javascript
cc.vv.net.addHandler("login_finished", function(data) {

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

  1. 发送登录结束命令 login_finished,客户端接收后进入游戏场景:
javascript
socket.emit('login_finished');
cc.vv.net.addHandler("login_finished",function(data){
            console.log("login_finished");
            cc.director.loadScene("mjgame",function(){
                cc.vv.net.ping();
                cc.vv.wc.hide();
            });
            self.dispatchEvent("login_finished");
        });

服务器的扩展:

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析.

心跳/服务器负载:

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析

通过 load 属性来记录当前服务器的负载状态:

javascript
gameServerInfo.load = roomMgr.getTotalRooms();
Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析
收藏 打赏

感谢您的支持,我会继续努力的!

打开USDT(trc-20)扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

Ts:本站所有内容均为互联网收集整理和网友上传。仅限于学习研究,请必须在24小时内删除。否则由此引发的法律纠纷及连带责任本站概不承担。

如侵犯到您的合法权益,请联系我们删除侵权资源!

韩仔技术 搭建教程 Cocos Creator棋牌麻将源代码开发教程第三篇——情怀麻将的开房间流程解析 https://www.hanzijs.com/dajian/2691.html

相关文章

发表评论
暂无评论