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

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

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

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

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

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

(0)

相关推荐

  • 房卡麻将分析系列 "牌局回放" 之 数据设计详解及实例

    房卡麻将分析系列 "牌局回放" 之 数据设计       最近几个月,"房卡"棋牌游戏成为了资本追逐的热点,基于微信的广大用户和社交属性,"房卡"棋牌发展迅速.红孩儿团队因为之前几年有过相关项目的经验积累,鉴于未来广阔的地方棋牌市场和"开发间"机制的发展前景,也开始转向基于"开房间"棋牌游戏的项目开发中.为了更好的与开发者进行交流学习,特开设"房卡麻将游戏分析系列". 红孩儿团队研发的&

  • 麻将游戏算法深入解析及实现代码

    麻将游戏算法深入解析及实现代码 这两天为了工具箱的完善,整理了这些年引擎开发的一些资料,无意中发现06年写的一个麻将算法,编译运行了一下,还是有点意思的,拿出来整理一下分享给大家. 麻将是一种大家最喜爱的娱乐活动之一,相信所有人都有接触过.我写的这版算法,是可以吃,碰,杠,还有把牌摸完没有人胡时的皇庄和包听.是用控制台方式来表现的,什么?控制台? 对,因为是算法的设计,所以用控制台来表现当然最简单了. 当然,在交互时要用文字输入会有少许不便,不过这种形式的游戏可是图形游戏的鼻祖哦~ 好,废话不多

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

    详解房卡麻将分析系列 "牌局回放" 之 播放处理 昨天红孩儿给大伙讲了讲"牌局回放"的数据记录处理,有了数据的存储,下面就是数据的显示了. 实话讲,好久没用过 SQL Server 来做数据库了, 网狐的服务器是基于WIN,IOCP,  SQL Server 这套路子.配置好后,可以在QPTreasureDB数据库中看到三个牌局相关的表. 其中dbo.PrivateGameRecord是存储当前游戏的房间及玩家,最终胜负信息的. dbo.PrivateGameRec

  • 房卡麻将分析系列 "牌局回放" 之 数据设计详解及实例

    房卡麻将分析系列 "牌局回放" 之 数据设计       最近几个月,"房卡"棋牌游戏成为了资本追逐的热点,基于微信的广大用户和社交属性,"房卡"棋牌发展迅速.红孩儿团队因为之前几年有过相关项目的经验积累,鉴于未来广阔的地方棋牌市场和"开发间"机制的发展前景,也开始转向基于"开房间"棋牌游戏的项目开发中.为了更好的与开发者进行交流学习,特开设"房卡麻将游戏分析系列". 红孩儿团队研发的&

  • 详解SpringBoot简化配置分析总结

    在SpringBoot启动类中,该主类被@SpringBootApplication所修饰,跟踪该注解类,除元注解外,该注解类被如下自定注解修饰. @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan 让我们简单叙述下它们各自的功能: @ComponentScan:扫描需要被IoC容器管理下需要管理的Bean,默认当前根目录下的 @EnableAutoConfiguration:装载所有第三方的Bean @SpringB

  • 详解从源码分析tomcat如何调用Servlet的初始化

    引言 上一篇博客我们将tomcat源码在本地成功运行了,所以在本篇博客中我们从源码层面分析,tomcat在启动的过程中,是如何初始化servlet容器的.我们平常都是将我们的服务部署到 tomcat中,然后修改一下配置文件,启动就可以对外提供 服务了,但是我们对于其中的一些流程并不是非常的了解,例如如何加载的web.xml等.这是我们分析servlet 和 sringMVC必不可少的过程. 注释源码地址:https://github.com/good-jack/tomcat_source/tre

  • 详解Android框架MVVM分析以及使用

    Android MVVM 分析以及使用 首先我们需要知道什么是MVVM,他的功能和优点,以及他的缺点. MVVM是Model-View-ViewModel的简写.它本质上就是MVC 的改进版.MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开.当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑.微软的WPF带来了新的技术体验,如Silverlight.音频.视频.3D.动画-

  • C语言详解strcmp函数的分析及实现

    目录 1.函数介绍 1.1.函数接口 1.2.函数分析 1.3.函数的简单使用 1.4.函数使用结果分析 2.库函数strcmp源代码 2.1.库函数源代码 2.2.库函数分析 3.模拟实现 strcmp 函数 3.1.模拟实现 3.2.模拟实现分析 1.函数介绍 1.1.函数接口 int __cdecl strcmp (const char * src,const char * dst); 这里是库函数里面的函数定义接口.这个函数是将 src 和 dst 两个字符串进行比较,即为字符串比较函数

  • 详解PHP后期静态绑定分析与应用

    基础知识 1. 范围解析操作符 (::) 可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法. self,parent 和 static 这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的. parent用于调用父类中被覆盖的属性或方法(出现在哪里,就将解析为相应类的父类). self用于调用本类中的方法或属性(出现在哪里,就将解析为相应的类:注意与$this区别,$this指向当前实例化的对象). 当一个子类覆盖其父类中的方法时,PHP 不会调用父类中已被覆盖的方法.是否

  • 详解Vue-Router源码分析路由实现原理

    深入Vue-Router源码分析路由实现原理 使用Vue开发SPA应用,离不开vue-router,那么vue和vue-router是如何协作运行的呢,下面从使用的角度,大白话帮大家一步步梳理下vue-router的整个实现流程. 到发文时使用的版本是: - vue (v2.5.0) - vue-router (v3.0.1) 一.vue-router 源码结构 github 地址:https://github.com/vuejs/vue-router components下是两个组件<rout

  • JSON 数据详解及实例代码分析

     JSON 数据详解 一.json值的类型 1.简单值: 可以表示字符串,数值,布尔值,null不支持undefined(json的数值表示: 2 ) 2.对象: 一组有序的键值对,每个键值对的值可以是简单值,也可以是复杂数据类型.(json的字符串:"hello world").json字符串与JavaScript字符串的区别,json必须用双引号. 3.数组:一组有序值的列表,数组的值可以是简单值,也可以是复杂数据类型. 不支持变量,函数,以及对象实例 二.json对象与javas

随机推荐