cocos creator Touch事件應(yīng)用(觸控選擇多個(gè)子節(jié)點(diǎn)的實(shí)例)
最近參與了cocos creator的研究,開發(fā)小游戲,結(jié)果被一個(gè)事件坑得不行不行的?,F(xiàn)在終于解決了,分享給大家。
原理
1.觸控事件是針對(duì)節(jié)點(diǎn)的
2.觸控事件的冒泡,是直接關(guān)系冒泡,父子可以,孫子不行,就是不能隔代冒泡
3.父節(jié)點(diǎn)不響應(yīng)觸控事件,肯定是被孩子節(jié)點(diǎn)遮擋了,只要孩子節(jié)點(diǎn)也監(jiān)聽一下事件,父節(jié)點(diǎn)就可以響應(yīng)了
4.觸控位置是絕對(duì)坐標(biāo),相對(duì)于整個(gè)canvas,節(jié)點(diǎn)位置相對(duì)于父節(jié)點(diǎn),相對(duì)位置可以與絕對(duì)坐標(biāo)相互轉(zhuǎn)化
5.節(jié)點(diǎn)是否被觸控到,touch start事件可以肯定被觸摸到,但是一個(gè)節(jié)點(diǎn)觸摸到必須等待其結(jié)束,另一個(gè)節(jié)點(diǎn)才能響應(yīng)touch事件
6.判斷是否框選中,根據(jù)坐標(biāo)計(jì)算相互交叉即是選中。就是說我從觸控起點(diǎn)->觸控終點(diǎn) 構(gòu)成的矩形區(qū)域,與節(jié)點(diǎn)的矩形存在重疊,就是被框選。本例中,采用比較粗略的算法實(shí)現(xiàn),根據(jù)橫坐標(biāo)的范圍是否包含子節(jié)點(diǎn)的橫坐標(biāo)判斷是否選中。
7.計(jì)算某個(gè)數(shù)值是否在某一范圍內(nèi),首先計(jì)算出范圍的最大值、最小值,然后作比較即可。
核心代碼
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(){
//父節(jié)點(diǎn)監(jiān)聽touch事件(直接子節(jié)點(diǎn)必須注冊(cè)同樣的事件方能觸發(fā))
this.poker.on(cc.Node.EventType.TOUCH_START, function (event) {
console.log('poker TOUCH_START');
//牌
var card = event.target;
//起始觸摸位置(和第一張card一樣,相對(duì)于poker的位置)
this.touchStartLocation = this.cards[0].convertTouchToNodeSpace(event);
console.log('touch start Location:'+ JSON.stringify(this.touchStartLocation));
//計(jì)算牌位置
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);
//父節(jié)點(diǎn)監(jiān)聽touch事件(直接子節(jié)點(diǎn)必須注冊(cè)同樣的事件方能觸發(fā))
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);
//觸摸點(diǎn)轉(zhuǎn)換為card節(jié)點(diǎn)坐標(biāo)
var nodeLocation = this.cards[0].convertTouchToNodeSpace(event);
console.log('touch nodeLocation:'+ JSON.stringify(nodeLocation));
var x = nodeLocation.x;
var y = nodeLocation.y;
//找到當(dāng)前選中的牌
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);
//某張牌范圍包括了鼠標(biāo)位置,選中此牌與觸摸開頭的所有牌
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);
//父節(jié)點(diǎn)監(jiān)聽touch事件(直接子節(jié)點(diǎn)必須注冊(cè)同樣的事件方能觸發(fā))
this.poker.on(cc.Node.EventType.TOUCH_END, function (event) {
console.log('poker TOUCH_END');
this.doSelectCard();
}, this);
//父節(jié)點(diǎn)監(jiān)聽touch事件(直接子節(jié)點(diǎn)必須注冊(cè)同樣的事件方能觸發(fā))
this.poker.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {
console.log('poker TOUCH_CANCEL');
this.doSelectCard();
}, this);
//給所有的牌注冊(cè)事件,會(huì)自動(dòng)冒泡到poker節(jié)點(diǎn)
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){
//構(gòu)造牌對(duì)象
var cardObj = {
index:index,
name:card.name,
isSelected:card.y==this.cardInitY?false:true //高度不一樣,表示選中
};
//防止重復(fù)添加
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);
//改變牌狀態(tài)
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{ //不選中改為選中狀態(tài)
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事件應(yīng)用(觸控選擇多個(gè)子節(jié)點(diǎn)的實(shí)例)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
微信小程序自定義tab實(shí)現(xiàn)多層tab嵌套功能
微信小程序非?;鸨?,今天腳本之家小編給大家?guī)淼奈⑿判〕绦蜃远xtab實(shí)現(xiàn)多層tab嵌套功能以及項(xiàng)目中遇到的問題及解決方法,感興趣的朋友一起看看吧2018-06-06
JavaScript 模塊的循環(huán)加載實(shí)現(xiàn)方法
本文介紹JavaScript語(yǔ)言如何處理"循環(huán)加載"。目前,最常見的兩種模塊格式CommonJS和ES6,處理方法是不一樣的,返回的結(jié)果也不一樣2015-12-12
頁(yè)面下沉抖動(dòng)效果-網(wǎng)站HTTP連接沒有效果-PC上有效果
頁(yè)面下沉抖動(dòng)效果實(shí)現(xiàn)代碼,代碼少,功能還可以2008-05-05
JavaScript數(shù)組去重算法實(shí)例小結(jié)
這篇文章主要介紹了JavaScript數(shù)組去重算法,結(jié)合實(shí)例形式總結(jié)分析了JavaScript數(shù)組去重相關(guān)的讀寫、遍歷、比較、排序等操作及算法改進(jìn)相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-05-05
使用iframe window的scroll方法控制iframe頁(yè)面滾動(dòng)
在頁(yè)面中如何控制內(nèi)嵌的iframe滾動(dòng)呢?方法是使用iframe window的scroll方法,大家可以參考下面的示例2014-03-03
JavaScript大數(shù)相加相乘的實(shí)現(xiàn)方法實(shí)例
這篇文章主要給大家介紹了關(guān)于JavaScript大數(shù)相加相乘的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
JavaScript統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)次數(shù)完整實(shí)例
這篇文章主要介紹了JavaScript統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)次數(shù)的方法,以完整實(shí)例形式分析了JavaScript針對(duì)字符串中字符的遍歷操作相關(guān)技巧,需要的朋友可以參考下2016-01-01
JavaScript返回0-1之間隨機(jī)數(shù)的方法
這篇文章主要介紹了JavaScript返回0-1之間隨機(jī)數(shù)的方法,涉及javascript中Math對(duì)象random方法的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04

