DiscardCardCtrl.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. cc.Class({
  2. extends: cc.Component,
  3. properties: {
  4. m_NodePos:[cc.Node],
  5. m_CardItem:[cc.Prefab],
  6. m_SingleRow:cc.Integer, //单行牌数 //11
  7. m_Arrow:cc.Node,
  8. },
  9. // LIFE-CYCLE CALLBACKS: // 构造函数,在对象创建时被调用
  10. ctor: function () {
  11. // 初始化一个空数组来存储牌的数据
  12. this.m_CardData = new Array();
  13. // 循环4次,为每个玩家(假设共4个玩家)创建一个空数组来存储他们的牌
  14. for (var i = 0; i < 4; i++) {
  15. this.m_CardData[i] = new Array();
  16. }
  17. // 初始化一个数组来记录每个玩家弃牌的数量,初始值为0
  18. this.m_DiscardCount = new Array(0, 0, 0, 0);
  19. // 设置一个布尔值来表示弃牌区的显示方式,false表示横向,true表示纵向
  20. this.m_cbViewType = false; // false横向,true纵向
  21. // 将m_SingleRow转换为整数类型(假设m_SingleRow已经定义,此处仅做类型转换)
  22. this.m_SingleRow = parseInt(this.m_SingleRow);
  23. },
  24. onLoad: function () {
  25. // 循环4次,分别处理四个方向的手牌:底部、顶部、左侧、右侧
  26. for (var j = 0; j < 4; j++) {
  27. var posX = 0, posY = 0; // 初始化手牌的位置坐标
  28. // 根据方向和单行手牌数量确定每副手牌的布局
  29. for (var i = 0; i < 2 * this.m_SingleRow; i++) {
  30. // 实例化手牌对象
  31. var card = cc.instantiate(this.m_CardItem[j]);
  32. // 根据方向设置手牌的位置
  33. if (GameDef.HAND_BOTTOM == j) { // 当前方向是底部
  34. posX = i % this.m_SingleRow * card.width; // 计算X坐标,按单行排列
  35. if (parseInt(i / this.m_SingleRow) >= 1) {
  36. posY = -97; // 如果有多行,Y坐标设为-97
  37. }
  38. } else if (GameDef.HAND_TOP == j) { // 当前方向是顶部
  39. posX = ((this.m_SingleRow - 1) - i % this.m_SingleRow) * card.width; // 计算X坐标,反向排列
  40. if (parseInt(i / this.m_SingleRow) >= 1) {
  41. posY = -97; // 如果有多行,Y坐标设为-97
  42. }
  43. } else if (GameDef.HAND_LEFT == j) { // 当前方向是左侧
  44. posY = i % this.m_SingleRow * card.height * -1; // 计算Y坐标,按单行排列
  45. if (parseInt(i / this.m_SingleRow) >= 1) {
  46. posX = 56; // 如果有多行,X坐标设为56
  47. }
  48. } else if (GameDef.HAND_RIGHT == j) { // 当前方向是右侧
  49. posY = ((this.m_SingleRow - 1) - i % this.m_SingleRow) * card.height * -1; // 计算Y坐标,反向排列
  50. if (parseInt(i / this.m_SingleRow) >= 1) {
  51. posX = 56; // 如果有多行,X坐标设为56
  52. }
  53. // 设置右侧手牌的zIndex,使其按顺序排列
  54. card.zIndex = this.m_SingleRow - i;
  55. }
  56. // 设置手牌显示阴影的条件
  57. var ShowShoadow = false;
  58. if (GameDef.HAND_TOP == j || GameDef.HAND_BOTTOM == j) { // 当前方向是顶部或底部
  59. ShowShoadow = (i == 0 || i == 11); // 第一张和最后一张手牌显示阴影
  60. } else if (GameDef.HAND_LEFT == j) { // 当前方向是左侧
  61. ShowShoadow = (i < 11); // 前11张手牌显示阴影
  62. } else if (GameDef.HAND_RIGHT == j) { // 当前方向是右侧
  63. ShowShoadow = (i >= this.m_SingleRow); // 超过单行数量的手牌显示阴影
  64. }
  65. // 设置手牌的位置
  66. card.setPosition(posX, posY);
  67. // 将手牌添加到对应的节点上
  68. this.m_NodePos[j].addChild(card);
  69. // 获取手牌的组件
  70. card = card.getComponent('CardItem');
  71. // 设置手牌是否显示阴影
  72. card.SetShadowShow(ShowShoadow);
  73. // 将手牌数据保存到对应的数组中
  74. this.m_CardData[j][i] = card;
  75. // 设置手牌的显示状态
  76. card.SetState(GameDef.HAND_STATE_SHOW);
  77. // 初始状态下不激活手牌节点
  78. card.node.active = false;
  79. }
  80. }
  81. // // 创建一个动作序列,先向下移动20个单位,再向上移动20个单位
  82. // var seq1 = cc.sequence(cc.moveBy(0.5, 0, 20), cc.moveBy(0.5, 0, -20));
  83. // // 创建一个动作序列,先放大到1.5倍,再恢复到1倍
  84. // var seq2 = cc.sequence(cc.scaleTo(0.5, 1.5), cc.scaleTo(0.5, 1));
  85. // // 同时执行上述两个动作序列
  86. // var spawn = cc.spawn(seq1, seq2);
  87. // // 无限循环执行上述动作组合
  88. // this.m_Arrow.runAction(cc.repeatForever(spawn));
  89. // 初始状态下不激活箭头节点
  90. this.m_Arrow.active = false;
  91. },
  92. start () {
  93. },
  94. // 设置玩家手牌数据的函数
  95. SetCardData: function(viewID, cbCardData, cbCardCount, cbTingHouOut) {
  96. // 如果传入的cbCardData为0或null,直接返回
  97. if (cbCardData == 0 || cbCardData == null) return;
  98. // 遍历当前玩家手牌数组,将所有牌的node设置为不激活状态
  99. for (var i = 0; i < this.m_CardData[viewID].length; i++) {
  100. this.m_CardData[viewID][i].node.active = false;
  101. }
  102. // 计算需要新增的牌的数量
  103. var index = 0;
  104. if (cbCardCount > this.m_CardData[viewID].length) {
  105. index = cbCardCount - this.m_CardData[viewID].length;
  106. }
  107. // 更新玩家手牌数据
  108. for (var i = 0; i < this.m_CardData[viewID].length; i++) {
  109. // 如果当前手牌数组中的元素为null,输出错误信息并跳过
  110. if (this.m_CardData[viewID][i] == null) {
  111. console.log('SetCardData this.m_CardData[viewID][i] 越界:', i);
  112. continue;
  113. }
  114. // 如果新的手牌数据中有牌(值大于0),则激活node并设置手牌数据和状态为显示
  115. if (cbCardData[i + index] > 0) {
  116. this.m_CardData[viewID][i].node.active = true;
  117. this.m_CardData[viewID][i].SetCardData(cbCardData[i + index]);
  118. this.m_CardData[viewID][i].SetState(GameDef.HAND_STATE_SHOW);
  119. }
  120. // 如果有报听的牌,并且该牌需要显示为背面
  121. if (cbTingHouOut != null && cbTingHouOut[i + index] > 0) {
  122. // 设置手牌状态为显示背面
  123. this.m_CardData[viewID][i].SetState(GameDef.HAND_STATE_SHOW_BACK);
  124. }
  125. }
  126. // 根据手牌数量和玩家数量设置丢弃的牌的数量
  127. if (cbCardCount > this.m_SingleRow * 2 && this.m_UserCount > 2) {
  128. this.m_DiscardCount[viewID] = this.m_SingleRow * 2;
  129. } else {
  130. this.m_DiscardCount[viewID] = cbCardCount;
  131. }
  132. },
  133. /**
  134. * 根据视图ID和卡牌ID获取卡牌节点
  135. * @param {number} viewID - 视图ID,标识不同的玩家或玩家位置
  136. * @param {number} CardID - 卡牌ID,标识玩家手牌中的具体哪一张卡牌
  137. * @returns {CardNode} - 返回指定视图和ID对应的卡牌节点
  138. */
  139. GetCardNode: function(viewID, CardID) {
  140. // 返回存储在m_CardData数组中的指定视图和ID对应的卡牌节点
  141. return this.m_CardData[viewID][CardID];
  142. },
  143. /**
  144. * 获取下一张弃牌节点
  145. * @param {number} viewID - 视图ID,用于标识不同的玩家或视角
  146. * @returns {Node} - 返回弃牌节点
  147. */
  148. GetNextDiscardNode: function(viewID) {
  149. // 获取当前视角下的弃牌计数索引
  150. var index = this.m_DiscardCount[viewID];
  151. // 检查索引是否超出当前视角下的牌数据长度
  152. if (index >= this.m_CardData[viewID].length) {
  153. // 如果超出长度,将所有牌的数据向前移动一位
  154. for (var i = 0; i < this.m_CardData[viewID].length - 1; i++) {
  155. // 将第i+1张牌的数据赋值给第i张牌
  156. this.m_CardData[viewID][i].SetCardData(this.m_CardData[viewID][i + 1].GetCardData());
  157. }
  158. // 获取最后一张牌的索引
  159. var nMaxIndex = this.m_CardData[viewID].length - 1;
  160. // 将最后一张牌的节点设置为不活跃(隐藏)
  161. this.m_CardData[viewID][nMaxIndex].node.active = false;
  162. // 返回最后一张牌的节点
  163. return this.m_CardData[viewID][nMaxIndex];
  164. }
  165. // 如果索引未超出长度,直接返回对应索引的牌节点
  166. return this.m_CardData[viewID][index];
  167. },
  168. /**
  169. * 获取指定视图ID的节点的缩放比例
  170. * @param {number} viewID - 视图的唯一标识符
  171. * @returns {number} - 返回该视图ID对应的节点的缩放比例
  172. */
  173. GetScale:function(viewID){
  174. return this.m_NodePos[viewID].scale;
  175. },
  176. // 定义 AddDiscard 函数,用于在指定玩家位置丢弃一张牌
  177. AddDiscard: function(viewID, cbCardData, bShowArrow, wTingCard) {
  178. // 如果传入的牌数据为空或为0,则直接返回,不执行后续操作
  179. if (cbCardData == 0 || cbCardData == null) return;
  180. // 获取当前玩家丢弃的牌数据
  181. var CardData = this.m_CardData[viewID][this.m_DiscardCount[viewID]];
  182. // 如果当前索引的牌数据为空,则使用该玩家最后一张牌的数据
  183. if (CardData == null) {
  184. CardData = this.m_CardData[viewID][this.m_CardData[viewID].length - 1];
  185. }
  186. // 激活牌节点
  187. CardData.node.active = true;
  188. // 设置牌的数据
  189. CardData.SetCardData(cbCardData);
  190. // 根据是否传入了听牌信息来设置牌的显示状态
  191. if (wTingCard != null && wTingCard != 0) {
  192. // 如果传入了听牌信息,则设置牌为背面显示状态
  193. CardData.SetState(GameDef.HAND_STATE_SHOW_BACK);
  194. } else {
  195. // 否则,设置牌为正面显示状态
  196. CardData.SetState(GameDef.HAND_STATE_SHOW);
  197. }
  198. // 根据玩家数量来决定丢弃计数的增加方式
  199. if (this.m_UserCount == 2) {
  200. // 如果玩家数量为2,则每次丢弃计数加1
  201. this.m_DiscardCount[viewID]++;
  202. } else {
  203. // 如果玩家数量不为2,则只有当当前丢弃计数小于单行牌数的两倍时,才增加丢弃计数
  204. if (this.m_DiscardCount[viewID] < this.m_SingleRow * 2) {
  205. this.m_DiscardCount[viewID]++;
  206. }
  207. }
  208. // 如果传入了显示箭头的标志且为真,则显示箭头
  209. if (bShowArrow != null && bShowArrow) {
  210. this.ShowArrow(viewID);
  211. }
  212. },
  213. GetLastCardData:function(viewID){
  214. if(this.m_DiscardCount[viewID]<=0)return 0;
  215. var CardData = this.m_CardData[viewID][this.m_DiscardCount[viewID]];
  216. return CardData.GetCardData();
  217. },
  218. RemoveDiscard:function(viewID){
  219. if(this.m_DiscardCount[viewID]<=0)return;
  220. this.m_CardData[viewID][--this.m_DiscardCount[viewID]].node.active = false;
  221. if( this.m_Arrow.active )
  222. {
  223. this.m_Arrow.active = false;
  224. }
  225. },
  226. Reset:function(){
  227. for(var j = 0 ;j<4;j++){
  228. this.m_DiscardCount[j] = 0;
  229. for (const i in this.m_CardData[j]) {
  230. this.m_CardData[j][i].node.active = false;
  231. this.m_CardData[j][i].SetCardData(0);
  232. }
  233. }
  234. },
  235. // 显示箭头的方法,用于指示某个玩家丢弃牌的位置
  236. ShowArrow: function(viewID) {
  237. // 检查viewID是否在有效范围内(0到4),以及该玩家是否有丢弃的牌
  238. if (viewID < 0 || viewID > 4 || this.m_DiscardCount[viewID] == 0) {
  239. // 如果viewID无效或没有丢弃的牌,则隐藏箭头并返回
  240. this.m_Arrow.active = false;
  241. return;
  242. }
  243. // 如果viewID有效且有丢弃的牌,则显示箭头
  244. this.m_Arrow.active = true;
  245. // 计算箭头应指向的丢弃牌的索引
  246. var arrowIndex = this.m_DiscardCount[viewID] - 1;
  247. // 确保arrowIndex不超出该玩家丢弃牌数组的长度范围
  248. if (arrowIndex > this.m_CardData[viewID].length - 1) {
  249. arrowIndex = this.m_CardData[viewID].length - 1;
  250. }
  251. // 获取该玩家丢弃牌的节点的世界坐标位置
  252. var pos = this.m_CardData[viewID][arrowIndex].node.convertToWorldSpaceAR(cc.v2(0, 0));
  253. // 将世界坐标转换为当前节点的本地坐标
  254. pos = this.node.convertToNodeSpaceAR(pos);
  255. // 根据viewID调整箭头的Y轴位置,以更好地适应UI布局
  256. if (viewID == GameDef.HAND_LEFT || viewID == GameDef.HAND_RIGHT) {
  257. // 如果是左手玩家或右手玩家,箭头Y轴位置加20
  258. pos.y += 20;
  259. } else {
  260. // 其他情况(例如上家或下家),箭头Y轴位置加30
  261. pos.y += 30;
  262. }
  263. // 设置箭头的位置为计算后的pos
  264. this.m_Arrow.setPosition(pos);
  265. },
  266. setUserCount:function(wUserCount){
  267. this.m_UserCount = wUserCount;
  268. // 当玩家数量为2人时
  269. if( wUserCount == 2 ){
  270. // 初始化X和Y位置变量
  271. var posX = 0, posY = 0;
  272. // 遍历四个玩家位置(0, 1, 2, 3)
  273. for (var j = 0; j < 4; j++) {
  274. // 跳过玩家位置1和3,因为他们不参与当前的布局
  275. if( j == 1 || j == 3 ) continue;
  276. // 从第2*this.m_SingleRow张牌开始布局,c用于计算当前是第几张牌
  277. for (var i = 2*this.m_SingleRow, c=0; i<65; i++, c++) {
  278. // 初始化index变量,用于确定手牌的左右位置
  279. var index = 0;
  280. // 根据玩家位置设置index
  281. if( 0 == j ){ // 玩家位置0
  282. index = GameDef.HAND_LEFT; // 左手
  283. }
  284. else if( 2 == j ){ // 玩家位置2
  285. index = GameDef.HAND_RIGHT; // 右手
  286. }
  287. // 如果当前位置已经有牌,则跳过
  288. if( this.m_CardData[j][i] != null ) continue;
  289. // 实例化一张新的牌
  290. var card = cc.instantiate(this.m_CardItem[index]);
  291. // 根据玩家位置计算新牌的位置
  292. if(0 == j){ // 玩家位置0
  293. // 计算X位置,每排的牌宽度为card.width,向左移动
  294. posX = parseInt(c/this.m_SingleRow) * card.width * -1;
  295. // 计算Y位置,每张牌的高度为card.height,向下移动
  296. posY = parseInt(c % this.m_SingleRow) * card.height * -1;
  297. // 调整X位置,使牌稍微向右移动
  298. posX += 40;
  299. }else if(2 == j){ // 玩家位置2
  300. // 计算X位置,每排的牌宽度为card.width,向右移动
  301. posX = parseInt(c/this.m_SingleRow) * card.width;
  302. // 计算Y位置,每张牌的高度为card.height,向下移动
  303. posY = parseInt(c % this.m_SingleRow) * card.height * -1;
  304. // 调整X位置,使牌稍微向左移动
  305. posX += 5;
  306. }
  307. // 设置新牌的位置
  308. card.setPosition(cc.v2(posX, posY));
  309. // 将新牌添加到相应位置节点的子节点中
  310. this.m_NodePos[index].addChild(card);
  311. // 获取新牌的CardItem组件
  312. card = card.getComponent('CardItem');
  313. // 在m_CardData数组中记录新牌的位置信息
  314. this.m_CardData[j][i] = card;
  315. // 设置新牌的状态为显示状态
  316. card.SetState(GameDef.HAND_STATE_SHOW);
  317. // 将新牌的节点设置为不可见
  318. card.node.active = false;
  319. }
  320. }
  321. }
  322. // if( wUserCount == 3 ){
  323. // // var width = this.m_CardData[0][0].node.width;
  324. // // this.m_NodePos[0].x += width;
  325. // // this.m_NodePos[1].x += width-20;
  326. // // this.m_NodePos[2].x += width;
  327. // var posX =0;
  328. // var posY =0;
  329. // for (var j = 0; j < 3; j++) {
  330. // this.m_NodePos[j].removeAllChildren();
  331. // this.m_CardData[j] = new Array();
  332. // for (var i = 0; i < 3*this.m_SingleRow; i++) {
  333. // if( this.m_CardData[j][i] != null ) continue;
  334. // var card = cc.instantiate(this.m_CardItem[j]);
  335. // if(GameDef.HAND_LEFT == j){
  336. // posX = parseInt( i/this.m_SingleRow )*card.width;
  337. // posY = parseInt( i%this.m_SingleRow )*card.height*-1;
  338. // }
  339. // else if(GameDef.HAND_TOP == j){ //0
  340. // var value = 15;
  341. // posX = (i%value)*card.width;
  342. // posY = (parseInt( i/value) -1)*card.height*-1;
  343. // posY -= card.height
  344. // posX += card.width
  345. // }else if( GameDef.HAND_BOTTOM == j){ //2
  346. // var value = 15;
  347. // posX = (i%value)*card.width;
  348. // posY = (parseInt( i/value) -1)*card.height*-1;
  349. // posX += card.width
  350. // posY -= card.height
  351. // if( i >= 30 ){
  352. // posY +=card.height*3;
  353. // }
  354. // }
  355. // var ShowShoadow = false;
  356. // if(GameDef.HAND_TOP == j|| GameDef.HAND_BOTTOM == j){
  357. // ShowShoadow = (i == 0 || i == 15);
  358. // }
  359. // else if(GameDef.HAND_LEFT == j){
  360. // ShowShoadow = (i <11);
  361. // }
  362. // card.setPosition(posX,posY);
  363. // this.m_NodePos[j].addChild(card);
  364. // card = card.getComponent('CardItem');
  365. // this.m_CardData[j][i] = card;
  366. // card.SetState(GameDef.HAND_STATE_SHOW);
  367. // card.SetShadowShow(ShowShoadow);
  368. // card.node.active = false;
  369. // }
  370. // }
  371. // }
  372. },
  373. // update (dt) {},
  374. });