JavaScript

超轻量级php框架startmvc

cocos creator Touch事件应用(触控选择多个子节点的实例)

更新时间:2020-06-03 19:24:01 作者:startmvc
最近参与了cocoscreator的研究,开发小游戏,结果被一个事件坑得不行不行的。现在终于解决

最近参与了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) {

 // },
});

效果

以上这篇cocos creator Touch事件应用(触控选择多个子节点的实例)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

cocos creator 事件