房卡麻将分析系列 "牌局回放" 之 播放处理

持续放出房卡麻将设计与研发讲解。敬请关注微信共众号:红孩儿的游戏开发之路


                       房卡麻将分析系列 "牌局回放" 之 播放处理



           昨天红孩儿给大伙讲了讲”牌局回放“的数据记录处理,有了数据的存储,下面就是数据的显示了。


          实话讲,好久没用过 SQL Server 来做数据库了, 网狐的服务器是基于WIN,IOCP,  SQL Server 这套路子。配置好后,可以在QPTreasureDB数据库中看到三个牌局相关的表。




         其中dbo.PrivateGameRecord是存储当前游戏的房间及玩家,最终胜负信息的。

        dbo.PrivateGameRecordChild是存储当前游戏的每一局的牌局回放,也就是咱们上篇文中所讲述的每一场牌局详情和操作数据。

       dbo.PrivateGameRecordUserRecordID是记录ID与玩家ID的对应关系。


      我们打开dbo.PrivateGameRecord,可以看到有一个属性字段UserData存储着一堆二进制数据。也就是我们上节中通过Stream_VALUE来将结构数据填充为字节流后存进来的。


      当客户端在进入战绩界面时,会向登录服务器发送SUB_GP_GAME_RECORD_LIST消息,请求当前玩家的所有参与过的房间据,也就是dbo.PrivateGameRecord中与玩家相关的数据列表。这个可以在CGPGameRecord.cpp的CB_GetGameRecordList函数中看到。


       在登录服务器的AttemperEngineSink.cpp中,我们可以看到登录服务器会在收到消息后转发数据库请求,数据库再通过存储过程拉数据出来。之后返回给客户端。


     客户端收到后通过StreamValue将数据流解析到结构tagPrivateRandTotalRecord中显示出来。





        当玩家看到这条信息后,如果想查看每一局的战局,会再点击"详情"按钮,这时客户端会向登录服务器再次发送SUB_GP_GAME_RECORD_CHILD消息,同上面的流程大体一致,经过这样一个来回,客户端会得到房间中每局的详细数据,收到后通过StreamValue将数据流解析到结构tagPrivateRandRecordChild中显示出来。




   玩家现在能看到每一局的详情了,他如果想看牌局回放,会再调用GameScene的StartRecord(datastream kDataStream)来将tagPrivateRandRecordChild中的数据流转化为当前玩家牌局信息和操作信息。之后显示游戏场景和回放操作按钮菜单。有了具体的数据,通过按钮菜单来控制播放的速度,上一步,下一步并不复杂。在GameScene的NextRecordAction函数中,我们可以看到如何根据当前的操作类型来进行相应的操作复现玩家的出牌和操作。

void GameScence::NextRecordAction()
{
     ...
	GameRecordOperateResult& kAction = m_pGameRecord->kAction[m_iActRecordIdex];
	int iChairID = (m_wRecordSelfChairID-kAction.wOperateUser+MAX_PLAYER)%MAX_PLAYER;
	int iProvideUser = (m_wRecordSelfChairID-kAction.wProvideUser+MAX_PLAYER)%MAX_PLAYER;
	if (kAction.cbActionType == GameRecordOperateResult::TYPE_OperateResult)
	{
		Player* pPlayer = m_pPlayer[iChairID];
		CMD_S_OperateResult kTempCMD;
		kTempCMD.cbOperateCard = kAction.cbOperateCard;
		kTempCMD.cbOperateCode = kAction.cbOperateCode;
		kTempCMD.wOperateUser = kAction.wOperateUser;
		kTempCMD.wProvideUser = kAction.wProvideUser;
		Player* pProvidePlayer = m_pPlayer[iProvideUser];
		if (pProvidePlayer &&(kAction.cbOperateCode == WIK_PENG 
			|| kAction.cbOperateCode == WIK_LEFT
			|| kAction.cbOperateCode == WIK_CENTER
			|| kAction.cbOperateCode == WIK_RIGHT
			|| (kAction.cbOperateCode == WIK_GANG && kAction.wOperateUser != kAction.wProvideUser )))
		{
			pProvidePlayer->removeHandOutCard(kAction.cbOperateCard);
			pProvidePlayer->setActOutCard(-1);

			//设置当前玩家
			for (int i = 0; i<MAX_PLAYER; i++)
			{
				m_pPlayer[i]->stopAniCurrPlayer();
			}
			pProvidePlayer->runAniCurrPlayer();
		}

		pPlayer->setOperateResoult(&kTempCMD);
		pPlayer->showCard();
	}
	if (kAction.cbActionType == GameRecordOperateResult::TYPE_SendCard)
	{
		XPlayer* pPlayer = m_pPlayer[iChairID];
		if (kAction.cbOperateCard != 0)
		{
			pPlayer->addNewInCard(kAction.cbOperateCard);
		}
		pPlayer->showCard();

		//设置当前玩家
		for (int i = 0; i<MAX_PLAYER; i++)
		{
			m_pPlayer[i]->stopAniCurrPlayer();
		}
		pPlayer->runAniCurrPlayer();
	}
	if (kAction.cbActionType == GameRecordOperateResult::TYPE_OutCard)
	{
		Player* pPlayer = m_pPlayer[iChairID];
		for (int i = 0;i<MAX_PLAYER;i++)
		{
			m_pPlayer[i]->setActOutCard(-1);
		}
		pPlayer->sendOutCard(kAction.cbOperateCard);
		pPlayer->showCard();
	}
	if (kAction.cbActionType == GameRecordOperateResult::TYPE_ChiHu)
	{
		Player* pPlayer = m_pPlayer[iChairID];
		for (int i = 0;i<MAX_PLAYER;i++)
		{
			m_pPlayer[i]->setActOutCard(-1);
		}

		pPlayer->setChiHuCard(kAction.cbOperateCard);
		pPlayer->showEffect("Hu");
		if (kAction.wOperateUser != kAction.wProvideUser)
		{
			XZDDPlayer* pDestPlayer = m_pPlayer[iChairID];
			pPlayer->showHandCard();
			pPlayer->showStatusImagic("Hu");
			pDestPlayer->runAniHu();
		}
		else
		{
			pPlayer->showStatusImagic("ZiMo");
			pPlayer->runAniZiMo();
		}
		pPlayer->showCard();
	}

	m_iActRecordIdex++;
	...
}





于是,一场精彩的牌局就被完完整整的回放了。



                                           

扫一扫,关注红孩儿共众号,每天获取更多房卡麻将技术文章

                                        

                                                                                                                



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火云洞红孩儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值