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

作者:lqh 时间:2022-12-26 08:54:27 

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

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

          实话讲,好久没用过 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++;
 ...
}

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

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

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://blog.csdn.net/honghaier/article/details/60756241

标签:牌局,回放
0
投稿

猜你喜欢

  • java遍历properties文件操作指南

    2023-11-23 02:43:45
  • 基于Spring Boot使用JpaRepository删除数据时的注意事项

    2023-04-03 09:05:39
  • 基于SPRINGBOOT配置文件占位符过程解析

    2021-06-27 04:25:12
  • C#的TimeSpan案例详解

    2023-11-20 11:34:52
  • c#根据文件大小显示文件复制进度条实例

    2022-10-10 10:35:16
  • C#在WinForm中使用WebKit传递js对象实现与网页交互的方法

    2021-05-26 00:07:08
  • Spring Boot使用AOP实现REST接口简易灵活的安全认证的方法

    2023-04-10 04:38:44
  • Flutter中数据库的使用教程详解

    2023-12-09 11:16:28
  • 引入mybatis-plus报 Invalid bound statement错误问题的解决方法

    2021-06-01 14:28:00
  • Spring @Conditional通过条件控制bean注册过程

    2023-08-06 10:00:11
  • sqlite数据库的介绍与java操作sqlite的实例讲解

    2023-05-09 03:07:40
  • Android教程之开机流程全面解析

    2023-02-18 21:02:44
  • Spring cloud alibaba之Gateway网关功能特征详解

    2022-10-26 18:22:28
  • Java线程中sleep和wait的区别详细介绍

    2021-08-27 02:23:12
  • SpringBoot中@ConditionalOnBean实现原理解读

    2023-04-25 14:24:54
  • Java实现单链表基础操作

    2021-08-07 13:46:04
  • C#中的IEnumerable简介及简单实现实例

    2023-07-15 22:27:07
  • C#统计字符串的方法

    2021-06-12 17:00:12
  • Android仿微信语音聊天功能

    2022-11-24 03:36:12
  • JavaWeb框架MVC设计思想详解

    2022-09-09 06:43:50
  • asp之家 软件编程 m.aspxhome.com