cocos creator Touch事件應(yīng)用(觸控選擇多個(gè)子節(jié)點(diǎn)的實(shí)例)
最近參與了cocos creator的研究,開發(fā)小游戲,結(jié)果被一個(gè)事件坑得不行不行的?,F(xiàn)在終于解決了,分享給大家。
原理
1.觸控事件是針對節(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.觸控位置是絕對坐標(biāo),相對于整個(gè)canvas,節(jié)點(diǎn)位置相對于父節(jié)點(diǎn),相對位置可以與絕對坐標(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)必須注冊同樣的事件方能觸發(fā))
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));
//計(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)必須注冊同樣的事件方能觸發(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)必須注冊同樣的事件方能觸發(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)必須注冊同樣的事件方能觸發(fā))
this.poker.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {
console.log('poker TOUCH_CANCEL');
this.doSelectCard();
}, this);
//給所有的牌注冊事件,會自動冒泡到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)造牌對象
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í)例)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript如何一次性展示幾萬條數(shù)據(jù)
本文主要介紹了JavaScript一次性展示幾萬條數(shù)據(jù)的實(shí)現(xiàn)方法。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-03-03
JavaScript連接組件實(shí)現(xiàn)打印功能
這篇文章主要為大家詳細(xì)介紹了JavaScript如何連接連接抖音打印組件實(shí)現(xiàn)打印小票功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-04-04
詳解js根據(jù)百度地圖提供經(jīng)緯度計(jì)算兩點(diǎn)距離
這篇文章主要介紹了js根據(jù)百度地圖提供經(jīng)緯度計(jì)算兩點(diǎn)距離,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JavaScript實(shí)現(xiàn)拼圖式滑塊驗(yàn)證功能
滑塊驗(yàn)證碼是在網(wǎng)站、APP等應(yīng)用中常見的一種驗(yàn)證方式,通過按照一定規(guī)則滑動滑塊到指定位置完成驗(yàn)證,才可以進(jìn)行下一步操作,本文給大家分享基于JavaScript實(shí)現(xiàn)拼圖式滑塊驗(yàn)證功能,感興趣的朋友一起看看吧2022-06-06
ie與firefox下的event使用說明與詳細(xì)區(qū)別
event是ie自帶的一個(gè)對象,而ff中不存在該對象,只能通過傳遞參數(shù)(并且惟一)的方式來實(shí)現(xiàn)event.2009-10-10

