繼續繼續。
上一篇地址:【Cocos Creator 實戰】06 - 如何給拼圖遊戲添加計時器
概覽
主要內容
在上一篇結尾的時候,我們引用了以爲同學的話:
在拼圖遊戲中,如果幾塊拼圖都重合在一個錨點,感覺會降低遊戲體驗。可是如何做到移動圖片至已經存在圖片的錨點時,將後來的圖片彈到其他區域(也就是說有圖片的錨點不能吸附新的圖片)。這種功能該怎麼實現呢?
今天我們就來解決這個問題。
來看看這個問題修改之前的效果:
再來看看修改之後的效果:
可以看到,效果還是很明顯的。
具體的內容大家可以在下面的演示地址中體驗。
項目資源
推薦大家先把項目 clone 到本地,然後參考着代碼來看本篇文章。
我的每篇文章會對應一個分支,大家直接看對應的分支就可以,master 對應的是最新的內容,會整合各個分支。
演示地址也是對應每篇文章獨立部署的,直接點擊前往即可。
開搞
今天我們修改的內容比較簡單,總共就改了一個文件。
原理
咱們先想一下,如果是你來設計,你準備怎麼實現上面的功能。
能用白話把邏輯描述清楚就行。
這裏停頓 30s。
這裏停頓 30s。
這裏停頓 30s。
我來說一下我設計的實現原理:
1、拿起圖片的時候記錄下位置
2、放下圖片的時候判斷,將要自動吸附(移動)到的位置上是否已經有其他圖片
- 如果有,那剛剛放下的圖片自動移動到拿起時的位置(歸位)
- 如果沒有,那執行自動吸附操作
沒了。
簡單吧。
來看看代碼實現。
核心代碼
修改 item-manager.js
文件中的 __moveStart
方法:
__moveStart(node) {
console.info('start');
let itemManager = node.parent.getComponent('item-manager');
// 在這裏記錄拿起時圖片的位置
itemManager.itemStartPos = cc.v2({x: node.position.x, y: node.position.y});
itemManager.maxIndex++;
node.zIndex = itemManager.maxIndex;
cc.loader.loadRes('sound/pick', cc.AudioClip, function (err, clip) {
cc.audioEngine.playEffect(clip, false);
});
},
修改 item-manager.js
文件中的 __adsorption
方法:
__adsorption(node) {
let picHeight = node.height;
let picWidth = node.width;
let nodeVec = cc.v2({x: node.position.x, y: node.position.y});
let conditions = [
{x: picWidth, y: 0},
{x: (-1) * picWidth, y: 0},
{x: 0, y: picHeight},
{x: 0, y: (-1) * picHeight},
];
for (let i = 0; i < this.items.length; i++) {
let itemNode = this.items[i].node;
let itemPos = itemNode.position;
let isMoved = false;
for (let j = 0; j < conditions.length; j++) {
let con = conditions[j];
let targetVec = cc.v2({
x: itemPos.x + con.x,
y: itemPos.y + con.y
});
let distance = targetVec.sub(nodeVec).mag();
if (distance > 100) continue;
isMoved = true;
// 目標位置上已經有其他節點
if (this.__isPosHasItem(node, targetVec)) {
let action = cc.moveTo(0.1, this.itemStartPos);
node.runAction(action);
}
// 目標位置上沒有其他節點
else {
let finished = cc.callFunc(this.__checkWin, this);
let action = cc.moveTo(0.1, targetVec);
let seq = cc.sequence(action, finished);
node.runAction(seq);
}
break;
}
if (!isMoved) continue;
console.info('自動吸附條件成立!!!!');
break;
}
},
在 item-manager.js
文件中增加一個 __isPosHasItem
方法,用於判斷目標位置上是否已經有其他圖片:
__isPosHasItem(node, targetVec) {
for (let i = 0; i < this.items.length; i++) {
let item = this.items[i];
if (item.node._id == node._id) continue;
if (Math.abs(item.node.position.x - targetVec.x) > 1) continue;
if (Math.abs(item.node.position.y - targetVec.y) > 1) continue;
return true;
}
return false;
}
簡單吧。
只要想清楚了原理,實現起來都很簡單。
這裏多說一嘴 __isPosHasItem
方法中的第四行:
if (item.node._id == node._id) continue;
這裏判斷了一下,這個節點是不是我們正在移動的節點,因爲我們正在移動的節點有可能剛好移動到了目標吸附位置,那你再彈回去,就尷尬了不是。
下面的兩行代碼:
if (Math.abs(item.node.position.x - targetVec.x) > 1) continue;
if (Math.abs(item.node.position.y - targetVec.y) > 1) continue;
這裏之所以沒有使用全等,是因爲兩個位置之間的差距極小極小(但不是0),你自己跑一下就知道了,所以我用了一個範圍:只要在 1個像素
範圍內,都算重疊。
大家可以想一下,我這裏使用的是座標位置計算的,還可以使用什麼方法?
我們在之前第四篇文章 【Cocos Creator 實戰】04 - 如何給拼圖加上吸附效果 中學習的計算兩個節點間的距離的方法是不是也可以?
好了,這回真沒了。
總結
知識點
1、像素點與圖片位置計算
下一步
這篇文章內容很簡單,也很好理解,希望大家不要侷限於我使用的方法,自己思考一下,不妨將你的方案發出來,大家討論一下。