你的位置:首页 > Java教程

[Java教程]cocos creator Touch事件应用(触控选择多个子节点)

最近参与了cocos creator的研究,开发小游戏,结果被一个事件坑得不行不行的。现在终于解决了,分享给大家。

 

原理

1.触控事件是针对节点的

2.触控事件的冒泡,是直接关系冒泡,父子可以,孙子不行,就是不能隔代冒泡

3.父节点不响应触控事件,肯定是被孩子节点遮挡了,只要孩子节点也监听一下事件,父节点就可以响应了

4.触控位置是绝对坐标,相对于整个canvas,节点位置相对于父节点,相对位置可以与绝对坐标相互转化

5.节点是否被触控到,touch start事件可以肯定被触摸到,但是一个节点触摸到必须等待其结束,另一个节点才能响应touch事件

6.判断是否框选中,根据坐标计算相互交叉即是选中。就是说我从触控起点->触控终点 构成的矩形区域,与节点的矩形存在重叠,就是被框选。本例中,采用比较粗略的算法实现,根据横坐标的范围是否包含子节点的横坐标判断是否选中。

7.计算某个数值是否在某一范围内,首先计算出范围的最大值、最小值,然后作比较即可。

 

核心代码

cc.Class({ extends: cc.Component, properties: {  // foo: {  // default: null,  // The default value will be used only when the component attaching  //       to a node for the first time  // url: cc.Texture2D, // optional, default is typeof default  // serializable: true, // optional, default is true  // visible: true,  // optional, default is true  // displayName: 'Foo', // optional  // readonly: false, // optional, default is false  // },  // ...   poker:{    default:null,    type:cc.Node   },   cardMask:{    default:null,    type: cc.Prefab   } }, // use this for initialization onLoad: function () {      //牌   this.cards = this.poker.children;   //牌初始位置   this.cardInitY = this.cards[0].y;   //触摸选择到的牌   this.touchedCards = [];   //选中的牌   this.selectedCards = [];   console.info(this.cards);  },    start: function () {   // this.cards = this.poker.children;   // console.info(this.cards);      this.addTouchEvent();  },  /**   * 添加事件   */  addTouchEvent:function(){   //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)   this.poker.on(cc.Node.EventType.TOUCH_START, function (event) {    console.log('poker TOUCH_START');        //牌    var card = event.target;        //起始触摸位置(和第一张card一样,相对于poker的位置)    this.touchStartLocation = this.cards[0].convertTouchToNodeSpace(event);    console.log('touch start Location:'+ JSON.stringify(this.touchStartLocation));        //计算牌位置    var index = 0;    for(var i=0;i<this.cards.length;i++){     var c = this.cards[i];     if(c.name == card.name){      index = i;      break;     }    }    //暂存第一次触摸到的牌    var touchedCard = {     index:index,     card:card    };    this.firstTouchedCard = touchedCard;    //暂存    this.pushTouchedCards(touchedCard.index,touchedCard.card);   }, this);     //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)   this.poker.on(cc.Node.EventType.TOUCH_MOVE, function (event) {    console.log('poker TOUCH_MOVE');    //先清除原先触摸到的牌    this.clearTouchedCards();    //保存第一张牌    this.pushTouchedCards(this.firstTouchedCard.index,this.firstTouchedCard.card);    //触摸点转换为card节点坐标    var nodeLocation = this.cards[0].convertTouchToNodeSpace(event);    console.log('touch nodeLocation:'+ JSON.stringify(nodeLocation));    var x = nodeLocation.x;    var y = nodeLocation.y;     //找到当前选中的牌    var currentCard = null;    for(var i=0;i< this.cards.length;i++){     var card = this.cards[i];     var cardX = card.x;     var cardY = card.y;     console.log('card x='+cardX+',y='+cardY);     //某张牌范围包括了鼠标位置,选中此牌与触摸开头的所有牌     var cardWidth = i==5 ? card.width:19;     var cardHeight = card.height;     if(cardX<=x && x <= cardX+cardWidth && cardY<=y && y<= cardY+cardHeight){      currentCard = card;          //暂存触摸到的牌      this.pushTouchedCards(i,card);            break;     }    }        //添加开头与此牌直接的所有牌    var startTouchLocation = this.touchStartLocation;    for(var i=0;i< this.cards.length;i++){     var card = this.cards[i];     var cardX = card.x;     //框选的范围包括了的牌     var min,max;     if(startTouchLocation.x < nodeLocation.x){      min = startTouchLocation.x;      max = nodeLocation.x;     }else{      min = nodeLocation.x;      max = startTouchLocation.x;     }     console.log('min='+min+', max='+max);     if(min <= cardX && cardX <= max){      //暂存触摸到的牌      this.pushTouchedCards(i,card);     }    }       }, this);    //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)  this.poker.on(cc.Node.EventType.TOUCH_END, function (event) {   console.log('poker TOUCH_END');   this.doSelectCard();  }, this);    //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)  this.poker.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {   console.log('poker TOUCH_CANCEL');   this.doSelectCard();  }, this);    //给所有的牌注册事件,会自动冒泡到poker节点  for(var i=0;i< this.cards.length;i++){   var cards = this.cards;   //闭包传递i值   (function(i){    var card = cards[i];    card.on(cc.Node.EventType.TOUCH_START, function (event) {     console.log('card TOUCH_START');    }, card);        card.on(cc.Node.EventType.TOUCH_MOVE, function (event) {     console.log('card TOUCH_MOVE');    }, card);    card.on(cc.Node.EventType.TOUCH_END, function (event) {     console.log('card TOUCH_END');    }, card);     card.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {     console.log('card TOUCH_CANCEL');    }, card);      })(i)     }   }, /**  * 暂存触摸到的牌  */ pushTouchedCards:function(index,card){  //构造牌对象  var cardObj = {   index:index,   name:card.name,   isSelected:card.y==this.cardInitY?false:true //高度不一样,表示选中  };    //防止重复添加  var existCard = this.touchedCards.find(function(obj){   if(obj.name == card.name){    return obj;   }else{    return null;   }  });  if(!existCard){   //添加暂存   this.touchedCards.push(cardObj);   //包含提示   this.addCardMask(card);  } }, /**  * 清除原先暂存的触摸到的牌  */ clearTouchedCards:function(){  for(var i=0;i<this.touchedCards.length;i++){   var cardIndex = this.touchedCards[i].index;   var card = this.cards[cardIndex];   card.removeChild(card.children[0]);  }  this.touchedCards = []; }, /**  * 选择牌  */ doSelectCard:function(){  this.selectedCards = [];  console.log(this.touchedCards);  //改变牌状态  for(var i = 0; i< this.touchedCards.length;i++){   var cardObj = this.touchedCards[i];   var card = this.cards[cardObj.index];   if(cardObj.isSelected){ //如果是选中改为不选中    card.y = card.y - 30;   }else{ //不选中改为选中状态    card.y = card.y + 30;   }  }  //重置  this.clearTouchedCards();  //显示选中的牌  this.showSelectedCards(); }, /**  * 包含牌遮罩  */ addCardMask:function(card){  var cardMask = cc.instantiate(this.cardMask);  cardMask.setPosition(cc.p(0, 0));  card.addChild(cardMask);  }, /** * 显示选中的牌 */ showSelectedCards:function(){  this.selectedCards = [];  for(var i=0;i< this.cards.length;i++){   var card = this.cards[i];   var isSelected = card.y==this.cardInitY?false:true;   if(isSelected){    this.selectedCards.push(card.name);   }  }  //输出  console.info("selected cards is: "+ JSON.stringify(this.selectedCards)); },  // called every frame, uncomment this function to activate update callback // update: function (dt) { // },});

 

效果