本文主要讲解以下几个方面:

card model

滑动处理

阴影

选择

出牌

Card Model

首先,牌有两个属性:数字、花型;

ps:本文现在是,用数字和花型来组成一张牌,有空可以再用另一种形式走一遍,比如用54个数字(0-53)来表示一副牌。

CardInfo.js

//花型

var CardSuit = cc.Enum ({

none: 0,

spade: 1, //黑桃

heart: 2, //红心

club: 3, //梅花

diamond: 4,//方块

});

//数字

var CardNumber = cc.Enum ({

none: 0,

num_3: 3,

num_4: 4,

num_5: 5,

num_6: 6,

num_7: 7,

num_8: 8,

num_9: 9,

num_10: 10,

num_J: 11,

num_Q: 12,

num_K: 13,

num_A: 14,

num_2: 15,

littleJoker: 16,

bigJoker: 17,

});

var CardInfo = cc.Class ({

extends: cc.Component,

properties: {

//数字

number: {

default: CardNumber.none,

type: CardNumber

},

//花型

suit: {

default: CardSuit.none,

type: CardSuit

},

},

statics: {

CardNumber: CardNumber,

CardSuit: CardSuit

},

//主要用于打印时,能清晰看到现在是哪张牌

desc() {

var desc = "";

if (this.number == CardNumber.littleJoker) {

return "小王";

}

if (this.number == CardNumber.bigJoker) {

return "大王";

}

switch(this.suit) {

case CardSuit.heart:

desc = "红桃";

break;

case CardSuit.spade:

desc = "黑桃";

break;

case CardSuit.club:

desc = "梅花";

break;

case CardSuit.diamond:

desc = "方块";

break;

}

switch(this.number) {

case CardNumber.num_3:

desc += "3";

break;

case CardNumber.num_4:

desc += "4";

break;

case CardNumber.num_5:

desc += "5";

break;

case CardNumber.num_6:

desc += "6";

break;

case CardNumber.num_7:

desc += "7";

break;

case CardNumber.num_8:

desc += "8";

break;

case CardNumber.num_9:

desc += "9";

break;

case CardNumber.num_10:

desc += "10";

break;

case CardNumber.num_J:

desc += "J";

break;

case CardNumber.num_Q:

desc += "Q";

break;

case CardNumber.num_K:

desc += "K";

break;

case CardNumber.num_A:

desc += "A";

break;

case CardNumber.num_2:

desc += "2";

break;

}

return desc;

},

});

ps:小王,大王的花型为 CardSuit.none。

显示自己手上的牌

首先,在场景中,添加一个空节点,锚点设置为(0,0);

宽度,我这里设置为屏幕宽度1334;(如果你能准确算出,所有牌最长的宽,也可以设置为具体值)

高度,牌的高+牌选中状态向上的偏移量(我这里设置为:201+19)

手牌node.png

代码走起来

main.js(绑定在当前场景上)

var CardInfo = require("CardInfo");

...

initHandCards : function(numbers){

//随便初始化几张牌

for (var number = 3; number <= 15; number++) {

let cardInfo = new CardInfo();

cardInfo.suit = number%2==0?CardInfo.CardSuit.diamond:CardInfo.CardSuit.spade;

cardInfo.number = number;

cardInfo.name = cardInfo.desc();

//cardInfoArr 存储牌的信息对象的数组

this.cardInfoArr.push(cardInfo);

//根据牌的信息 初始化预制体

var card = cc.instantiate(this.cardPrefab);

card.getComponent("Card").mCardInfo = cardInfo;

//将牌预制体 添加到父节点

this.handCardArea.addChild(card, cardInfo.number);

card.isChiose = false;

//cardArr 存储card prefab的对象数组

this.cardArr.push(card);

}

//计算posx,第一张牌显示的x坐标

var posx = 1334/2 - (this.cardArr.length -1)/2 * 50;

for (var i = 0; i < this.cardArr.length; i++){

this.cardArr[i].setPosition(posx+ i*50, 100.5);

}

}

运行结果如下(牌的间距为50):

显示自己牌.png

滑动选牌

选牌的事件监听对象,是不是牌呢?

如果只需要点击选择,我们可以直接在card prefab上添加点击事件监听

如果做滑动选牌,就需要在card prefab的父节点上(handCardArea),监听touchDown,touchMove,touchUp等事件

CardArea.js(绑定在handCardArea节点上)、

var Main = require("Main");

cc.Class({

extends: cc.Component,

properties: {

_touchBegan: null,

_touchMoved: null,

//用于调用Main场景上的脚本的方法,同时可以传递数据

game:{

default : null,

type: Main,

}

},

onTouchEvent: function () {

this.node.on(cc.Node.EventType.TOUCH_START, this.touchBegan, this);

this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.touchCancel, this);

this.node.on(cc.Node.EventType.TOUCH_END, this.touchEnd, this);

this.node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoved, this);

},

offTouchEvent: function () {

this.node.off(cc.Node.EventType.TOUCH_START, this.touchBegan, this);

this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.touchCancel, this);

this.node.off(cc.Node.EventType.TOUCH_END, this.touchEnd, this);

this.node.off(cc.Node.EventType.TOUCH_MOVE, this.touchMoved, this);

},

onLoad () {

this.onTouchEvent();

},

onDestroy(){

this.offTouchEvent();

},

/**

* Touch begin

* 当前触摸的点 是否在牌的区域

* */

_getCardForTouch: function (touch, cardArr) {

cardArr.reverse(); //to 1

for (var k in cardArr) {

var box = cardArr[k].getBoundingBox(); //获取card覆盖坐标范围

if (cc.rectContainsPoint(box, touch)) { //判断触摸的点,是否在当前牌的范围内

cardArr[k].isChiose = true;

cardArr[k].getComponent("Card").setMaskShowing(true); //显示阴影遮罩

cc.log("CCC touch select: "+k);

cardArr.reverse();

return cardArr[k];

}

}

cardArr.reverse();

},

/**

* Touch move

*

* */

_checkSelectCardReserve(touchBegan, touchMoved) {

//获取左边的点 为起始点

var p1 = touchBegan.x < touchMoved.x ? touchBegan : touchMoved;

//滑动的宽度

var width = Math.abs(touchBegan.x - touchMoved.x);

//滑动的高度 最小设置为5

var height = Math.abs(touchBegan.y - touchMoved.y) > 5 ? Math.abs(touchBegan.y - touchMoved.y) : 5;

//根据滑动 获取矩形框

var rect = cc.rect(p1.x, p1.y, width, height);

for (let i = 0; i < this.game.cardArr.length; i++) {

//判断矩形是否相交

if (!cc.rectIntersectsRect(this.game.cardArr[i].getBoundingBox(), rect)) {

//不相交 设置为反选状态

this.game.cardArr[i].isChiose = false;

this.game.cardArr[i].getComponent("Card").setMaskShowing(false);

}

}

//如果是从右向左滑动

if (p1 === touchMoved) {

for (let i = this.game.cardArr.length - 1; i >= 0; i--) {

//从右往左滑时,滑到一定距离,又往右滑

//这是要判断反选

if (this.game.cardArr[i].x - p1.x < 24) { //

this.game.cardArr[i].getComponent("Card").setMaskShowing(false);

this.game.cardArr[i].isChiose = false;

}

}

}

},

/**

* 开始点击 TOUCH_START回调函数

* */

touchBegan: function (event) {

cc.log("Touch begin");

var touches = event.getTouches();

var touchLoc = touches[0].getLocation();

cc.log("touch begin location: "+touchLoc);

this._touchBegan = this.node.convertToNodeSpace(touchLoc);

this._getCardForTouch( this._touchBegan, this.game.cardArr);

},

/**

* 移动 TOUCH_MOVE回调函数

* */

touchMoved: function (event) {

cc.log("Touch move");

var touches = event.getTouches();

var touchLoc = touches[0].getLocation();

this._touchMoved = this.node.convertToNodeSpace(touchLoc);

this._getCardForTouch(this._touchMoved, this.game.cardArr);

this._checkSelectCardReserve(this._touchBegan, this._touchMoved);

},

touchCancel: function () {

},

/**

* 点击结束 TOUCH_END回调函数

* */

touchEnd: function (event) {

cc.log("Touch end");

var touches = event.getTouches();

var touchLoc = touches[0].getLocation();

for (var k in this.game.cardArr) {

this.game.cardArr[k].getComponent("Card").setMaskShowing(false);

if (this.game.cardArr[k].isChiose === true) {

this.game.cardArr[k].isChiose = false;

// to 2

if (this.game.cardArr[k].status === SITDOWN) {

this.game.cardArr[k].status = STANDUP;

this.game.cardArr[k].y += 19;

} else {

this.game.cardArr[k].status = SITDOWN;

this.game.cardArr[k].y -= 19;

}

}

}

},

1. 为什么要调用 cardArr.reverse()?

首先,显示牌的时候,我们是从左往右显示的,也是从 0 到 cardArr.length-1 显示的。也就是说cardArr中,第0个元素是显示在最左边的。

第二点,我们举个例子:

 上面这张图里,鼠标现在放在 “方块8” 上,由于牌重叠放置,现在 “方块6”,“黑桃7”,“方块8” 三张牌的坐标范围,都包含了鼠标当前的位置。

现在鼠标在当前位置点击一下

如果,我们从“黑桃3”开始判断,那结果就会出现 “方块6”,“黑桃7”,“方块8” 三张牌,

很显然,这样的记过是不对的,我们想选择的只有 “方块8” 而已。

所以,正确的操作应该是,从最右边的 “黑桃2” 开始判断,因此,我们需要调用一次 reverse()。

第三点,需要注意的是,如果在 _getCardForTouch(cardArr) 中,使用的是原始cardArr数据,则需要在本地判断完成后,再次调用 reverse() 方法,将cardArr原始数据顺序还原,否则当你判断下一个点的时候,调用 reverse() 后,cardArr的数据就变成了正序,就达不到我们想要的效果了;

当然,如果每次传递的是原始数据,在 _getCardForTouch(cardArr) 方法中,使用的是cardArr的引用,就不需要再次调用 reverse()方法了。

2. touchEnd()中,为什么要将牌的状态反置?

如果滑动覆盖的区域内,包含已经是STANDUP状态的牌,应该将其置为未选中状态。

选牌效果

选牌时.png

选牌后.png

出牌

注意:

要打出的牌,不能直接用handCardArea节点下的组件,否则会提示被绑定。

代码先行

discards (cards) {

//出牌

if (!cards || cards.lenngth == 0) return;

//从父节点分离

for (const key in cards) {

if (cards.hasOwnProperty(key)) {

const card = cards[key];

card.node.removeFromParent(true); // 1

for (var i = 0; i < this.handCards.length; i++) {

var cardInfo = this.handCards[i];

if (cardInfo == card.cardInfo) {

this.handCards.splice(i, 1); // 2

break;

}

}

}

}

this.appendCardsToOutZone(cards); // 3

this.updateCards(); // 4

if(this.handCards.length == 0) {

this.game.gameOver(this);

}

},

/**

* 将牌的预制体,添加到出牌区域

*/

appendCardsToOutZone(cards) {

this.outCardZone.node.removeAllChildren(true); // 3.1

var count = cards.length;

var zeroPoint = count / 2;

for (var i = 0; i < count; i++) {

var card = cards[i];

var cardNode = card.node;

this.outCardZone.node.addChild(cardNode, 100 - card.cardInfo.number); // 3.2

}

this.outCardZone.node.sortAllChildren();

// 设置position

for (var i = 0; i < count; i++) {

var cardNode = this.outCardZone.node.getChildren()[i];;

var x = (i - zeroPoint) * 30;

var y = cardNode.getPositionY()+180;

cardNode.setScale(0.7, 0.7); // 3.3

cardNode.setPosition(x, y); // 3.4

}

},

1. 将 选中的牌 从父节点中移除

card.node.removeFromParent(true);

2. 从handCards 数组中,删除 选中的牌

this.handCards.splice(i, 1);

3. this.appendCardsToOutZone(cards)

将 “选中的牌” 添加到出牌区域

3.1 清空出牌区域

this.outCardZone.node.removeAllChildren(true);

3.2 添加子节点

this.outCardZone.node.addChild(cardNode, 100 - card.cardInfo.number);

3.3 设置scale

cardNode.setScale(0.7, 0.7);

3.4 设置position

cardNode.setPosition(x, y);

4. this.updateCards();

重新设置 手中的牌 的位置,这一点和显示手上牌的最后一步类似。

java斗地主怎么出牌_斗地主滑动选牌出牌(Cocos Creator)相关推荐

  1. java写出文本文档乱码_对象流如何写出到文件以及为什么乱码

    在写入对象文件的过程中,采用了txt文件,发现文件乱码,引发了思考. 首先需要理解好IO流是如何处理文件的. 1.ObjectOutputStream 对Java对象进行序列化处理,处理后的数据,不是 ...

  2. java经典源码 阅读_公开!阿里甩出“源码阅读指南”,原来源码才是最经典的学习范例...

    我们为啥要阅读源码? 为什么面试要问源码?为什么我们Java程序员要去看源码?相信大多数程序员看到源码第一感觉都是:枯燥无味,费力不讨好!要不是为了"涨薪"我才不去看这个鬼东西!但 ...

  3. java筛选法求质数_用筛选法找出N内所有素数(质数)

    //筛选法实现 // main.c #include #define ArraySize 100 int main(int argc, const char * argv[]) { int i ; i ...

  4. java语言c语言基础_新手入门选什么:有些人说C语言要比Java更难!你应该怎么办?...

    从学习角度上说,很多人认为C语言单纯简单,其实比Java要容易. 我认为,如果要把本质学懂,确实如此,而且在学懂C语言的基础上再学Java的人往往会获得很好的效果. Java中由于隐藏了内存分配的处理 ...

  5. 头部ct能检查出什么_脑部ct能检查出什么

    全国体检预约平台 脑部 ct 能检查出什么 颅脑的 CT 检查具有无痛苦,方便.安全,适宜任何人群和年龄段的患者.这种检查手段也 越来越广泛的运用在各种疾病的的临床诊断检查中.因为很多脑部的一些疾病和 ...

  6. python web前端 java ui学哪个好_学IT选Java还是Python?就业发展有何区别?

    学IT选Java还是Python?就业发展有何区别? 来源:奇酷学院 发表于:2018-09-27 10:14:35 想了解一个语言就业到底好不好,得先明确语言的发展方向. 很多学员在选择专业上遇着难 ...

  7. 为什么输入法显示中文打不出中文_输入法为什么打不出汉字_电脑输入法打不出汉字如何解决-win7之家...

    我们要在电脑中使用输入法打字的时候,不急可以打出汉字也可以打出英文,不过有不少用户却遇到了输入法打不出汉字的情况,这让用户们很苦恼,那么输入法为什么打不出汉字呢?一般出现这样的问题是输入法出现了问题, ...

  8. python斗地主出牌算法_斗地主之用蚁群算法整理牌型:如何进行牌力估计

    我们在前面讲到过,各牌手的牌力估计就是我们在用蚁群算法构造最优牌型时的启发性知识.启发性知识其实就是我们利用自己的经验对事物做出的判优性评估,或者说就是对事物价值的判断. 原则上,应用蚁群算法需要用到 ...

  9. java斗地主比大小_斗地主算法的设计与实现(三)--如何比较两手牌的大小

    本篇主要讲解斗地主中如何比较两手牌的大小. 友情提示:本篇是接着以下两篇文章就讲解的,建议先看看下面这2篇. 牌型比较 火箭最大:炸弹次之:再次是一般牌型(单牌.对牌.三张牌.三带一.单顺.双顺.三顺 ...

最新文章

  1. jquery ajax return值不能取得的解决方案
  2. 并发模型之——基本概念
  3. 深度学习之自编码器(2)Fashion MNIST图片重建实战
  4. ABB 机器人 IsStopMoveAct 指令 - Is stop move flags active
  5. Spring Data JPA 从入门到精通~定义查询方法的配置方法
  6. 精讲23种设计模式-基于观察者模式~设计异步多渠道群发框架
  7. php中padding,css中padding填充详解
  8. mysql 二进制 查询_MySql如何插入和查询二进制数据_MySQL
  9. SVN创建项目以及检出项目
  10. atitit.web 推送实现方案集合(2)---百度云,jpush 极光推送 ,个推的选型比较.o99
  11. vsftpd配置系统用户为登陆用户
  12. HTML鼠标移到a上面让a变色
  13. 软件智能:aaas系统的 AI服务功能:大纲图的无意识代理功能和八卦图的关系
  14. vue路由守卫以及用法
  15. Lombok插件下载与离线安装
  16. 1033:计算线段长度
  17. php版本降级,wamp技巧之–升级降级PHP版本 | SDT技术网
  18. 使用Python控制手机(二)关于淘宝的那些事
  19. Unity中获取地形的法线
  20. win10在哪找计算机配置,电脑教程:windows10的设置在哪

热门文章

  1. 07.配置日志的存储路径、设置日志的格式
  2. oracle 客户端连接数_查看oracle数据库允许的最大连接数和当前连接数
  3. makefile语法_Makefile的语法
  4. Halcon例程学习之距离变换(distance_transform)
  5. Typedef声明简介
  6. Java配置文件Properties的读取、写入与更新操作
  7. 力拼5G,台湾拟释放出更多频谱
  8. Bzoj3004 吊灯
  9. HttpClient那些事儿
  10. TEST DESIGN TECHNIQUES: AN OVERVIEW