原始碼獲取方式在最下面
先看效果
如何使用
原理講解
一共需要四個節點
寫指令碼
先來介紹下屬性(不包括剛剛說的那四個節點)
max_R
型別是 number
搖桿移動的最大半徑
speed
型別是 number
玩家移動速度
不建議太大,1-10最好
rotation
型別是 number
玩家的旋轉角度
vector
型別是cc.Vec2
移動向量,通過修改這個平面向量來控制角色的移動
is_rotation
型別是 Boolean
角色是否根據搖桿的方向旋轉
is_forbidden
型別是 Boolean
是否禁用搖桿
禁用後搖桿將不能使用
新建一個指令碼,把下面的程式碼複製貼上到裡面
const {ccclass, property} = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
@property(cc.Node)
bg: cc.Node = null;//搖桿背景
@property(cc.Node)
joystick: cc.Node = null;//搖桿 也就是中心點
@property(cc.Node)
player: cc.Node = null;//角色
@property(cc.Node)
parent: cc.Node = null;//搖桿和背景的父節點
@property
max_R: number = 135;//搖桿移動的最大半徑
@property
speed: number = 10;//角色移動速度
//不建議太大,1-10最好
@property
rotation: number = 0;//角色的旋轉角度 不要輕易改
@property
vector: cc.Vec2 = cc.v2(0,0);//移動向量
@property
is_rotation: boolean = true;//角色是否根據搖桿的方向旋轉
@property
is_forbidden: boolean = false;//是否禁用搖桿
onLoad(){
//繫結事件
//因為搖桿很小,如果給搖桿繫結事件玩家將很難控制,搖桿的背景比較大,所以把事件都繫結在背景上是不錯的選擇
this.bg.on(cc.Node.EventType.TOUCH_MOVE,this.move,this);//當手指在背景上移動時觸發move事件
this.bg.on(cc.Node.EventType.TOUCH_MOVE,this.move_palyer,this);//當手指在背景上移動時觸發move_player事件
this.bg.on(cc.Node.EventType.TOUCH_END,this.finish,this);//當手指在目標節點區域內離開螢幕時觸發finish事件
this.bg.on(cc.Node.EventType.TOUCH_CANCEL,this.finish,this);//當手指在目標節點區域外離開螢幕時觸發finish事件
}
update(){
let x = this.player.x + this.vector.x;
let y = this.player.y + this.vector.y;//每幀獲取角色的座標加上移動向量
this.player.position = cc.v3(x, y);//讓角色的座標每幀為自身的座標加上移動的向量
//求出角色的旋轉角度
if(this.vector.y < 0){//當搖桿在原點下方時
//角度是負的
this.rotation = (-this.vector.angle(cc.v2(1, 0))) / Math.PI * 180;//根據向量先求出弧度,再求出角度
}else{//如果搖桿在原點上方時
//角度是正的
this.rotation = (this.vector.angle(cc.v2(1, 0))) / Math.PI * 180;//根據向量先求出弧度,再求出角度
}
}
move(event: cc.Event.EventTouch){//負責移動搖桿 手指移動時呼叫
if(this.is_forbidden == false){//如果沒有禁用搖桿
let pos = new cc.Vec2(event.getLocationX(), event.getLocationY());//獲取觸點的座標
let pos_0 = this.parent.convertToNodeSpaceAR(pos);//將一個點轉換到節點 (區域性) 空間座標系,這個座標系以錨點為原點。
//pos_0.mag()是這個觸點的長度
if(pos_0.mag() < this.max_R){//如果觸點長度小於我們規定好的最大半徑
this.joystick.x = pos_0.x;//搖桿的座標為觸點座標
this.joystick.y = pos_0.y;
}else{//如果不
let pos = pos_0.normalizeSelf();//將觸點歸一化
let x = pos.x * this.max_R;//歸一化的觸點座標 × 最大半徑
let y = pos.y * this.max_R;
this.joystick.x = x;//給搖桿座標賦值
this.joystick.y = y;
}
}
}
move_palyer(){//負責移動角色 手指移動時呼叫
if(this.is_forbidden == false){//如果沒有禁用搖桿
let dir = this.joystick.position.normalizeSelf();//dir為搖桿座標的歸一化
this.vector.x = dir.x * this.speed;//給移動向量賦值
this.vector.y = dir.y * this.speed;//移動向量為方向 × 速度
if(this.is_rotation == true){//如果角色可以旋轉
this.player.angle = this.rotation;//根據搖桿的方向旋轉角色
}
}
}
finish(){//搖桿彈回原位置
//搖桿座標和移動向量都為(0,0)
this.joystick.position = cc.v3(0, 0);
this.vector = cc.v2(0, 0);
}
}
繫結好節點
每句程式碼我都寫了詳細的註釋哦
先來實現搖桿的移動
這就是表現上的內容,在拉動搖桿的時候角色並沒有動,只是搖桿在動,先來實現這個
需要給背景繫結事件,其實應該給搖桿繫結事件,因為搖桿很小,如果給搖桿繫結事件玩家將很難控制,搖桿的背景比較大,所以把事件都繫結在背景上是不錯的選擇
這就是給背景繫結的事件,當手指在背景上移動時觸發
首先獲取觸點座標,轉化為parent節點區域性空間座標系
我們只希望搖桿在規定好的max_R(最大半徑)的範圍內,不希望搖桿超出這個範圍
所以要判定一下觸點的座標在不在我們制定的最大半徑範圍內,通過mag獲取觸點座標的長度,也就是觸點距離原點的長度
比如我想求點A座標的長度,求出的結果就是綠色線段的長度
再來實現功能內容(控制角色移動)
把搖桿的座標歸一化,然後 × 速度,賦值給vector,如果可以旋轉還要讓角色旋轉
update
根據vector求出夾角弧度,再求出角度,判斷角度正負
公式
角度轉弧度 π/180×角度
弧度變角度 180/π×弧度
最後一定要在鬆開搖桿時讓搖桿彈回原處
原始碼在群裡面
Cocos技術交流Q群:1130122408
歡迎進群閒聊、技術交流都歡迎
製作不易,感謝你的觀看
Thank You~~