日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Cocos Creator制作一个虚拟摇杆

發(fā)布時(shí)間:2023/12/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cocos Creator制作一个虚拟摇杆 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Cocos Creator制作一個(gè)虛擬搖桿

  • 1. 演示
    • 版本:v2.4.3
    • 語(yǔ)言:TS
    • 演示GIF
  • 2. 實(shí)現(xiàn)過(guò)程
    • 素材
    • 期望效果
    • 過(guò)程
      • (1)搖桿跟隨觸摸
      • (2)搖桿自動(dòng)歸位
      • (3)限制搖桿不出界
        • 原理:
      • (4)添加箭頭
        • 原理:
    • 主腳本編寫
      • (1)主腳本部分實(shí)現(xiàn)功能
      • (2)演示
      • (3)實(shí)現(xiàn)
        • 搖桿腳本部分
        • 主腳本部分
  • 第一次發(fā)文章,若有錯(cuò)誤望大佬們指正。
    • 源碼

1. 演示

版本:v2.4.3

語(yǔ)言:TS

演示GIF

2. 實(shí)現(xiàn)過(guò)程

素材



期望效果

  • 類似于王者榮耀的那種小搖桿
  • 搖桿中心位置為屏幕點(diǎn)擊的位置
  • 搖桿點(diǎn)擊部分不會(huì)出界

過(guò)程

(1)搖桿跟隨觸摸

this.Joystick = this.node.getChildByName("Joystick");// 此處監(jiān)聽的joystick為搖桿this.Joystick.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);onTouchMove(e: cc.Event.EventTouch) {this.JoystickMove(e)}JoystickMove(e: cc.Event.EventTouch) {// 移動(dòng)let delta = e.getDelta();let moveDistance = cc.v3(delta.x / this.node.scale, delta.y / this.node.scale) // 此處增加縮放參數(shù)為了方便,使用時(shí)可以直接縮放大小this.Joystick.setPosition(this.Joystick.position.add(moveDistance)) }


此時(shí)可以實(shí)現(xiàn)觸摸點(diǎn)跟隨手指或者鼠標(biāo)移動(dòng)。getDelta函數(shù)是獲取觸點(diǎn)距離上一次事件移動(dòng)的距離對(duì)象,返回的是一個(gè)Vec2。但此時(shí)搖桿不會(huì)自動(dòng)歸位。

(2)搖桿自動(dòng)歸位

this.Joystick.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);this.Joystick.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);onTouchEnd(e: cc.Event.EventTouch) {this.JoystickReset()}onTouchCancel(e: cc.Event.EventTouch) {this.JoystickReset()}JoystickReset() {cc.tween(this.Joystick).to(0.05, {x: 0, y: 0}).start()}

TOUCH_END, TOUCH_CANCEL代表的狀態(tài)為當(dāng)手指在目標(biāo)節(jié)點(diǎn)區(qū)域內(nèi)離開屏幕時(shí),當(dāng)手指在目標(biāo)節(jié)點(diǎn)區(qū)域外離開屏幕時(shí)。使用緩動(dòng)使動(dòng)畫更流暢。

(3)限制搖桿不出界

原理:

此處思路來(lái)源于CSDN章魚仔,通過(guò)三角形的相似等比。

完善JoystickMove代碼

JoystickMove(e: cc.Event.EventTouch) {// 移動(dòng)let delta = e.getDelta();let moveDistance = cc.v3(delta.x / this.node.scale, delta.y / this.node.scale)// 加上縮放參數(shù),更加方便實(shí)用this.Joystick.setPosition(this.Joystick.position.add(moveDistance)) // 轉(zhuǎn)換坐標(biāo)let touchPos = e.getLocation(); // 以當(dāng)前屏幕左下角為坐標(biāo)系原點(diǎn)所獲得的的位置let touchPosInNode = this.node.convertToNodeSpaceAR(touchPos)let distanceBetweenTouchPosToJoystick = touchPosInNode.mag() * this.node.scale; // 此處縮放參數(shù)作用與前邊同理// 限制移動(dòng) < 半徑if (distanceBetweenTouchPosToJoystick > this.radius) {let lengthScale = this.radius / distanceBetweenTouchPosToJoystick;this.Joystick.x = touchPosInNode.x * lengthScale;this.Joystick.y = touchPosInNode.y * lengthScale;}}


此時(shí)移動(dòng)不會(huì)出界,而且可以任意調(diào)整縮放倍數(shù)都可以保持不出界狀態(tài)!
注意getLocation()函數(shù)返回的坐標(biāo)是以屏幕左下角為坐標(biāo)中心的坐標(biāo),并不是世界坐標(biāo)!
節(jié)點(diǎn).convertToNodeSpaceAR(位置)返回的是這個(gè)位置在這個(gè)節(jié)點(diǎn)下的位置。

(4)添加箭頭


完善代碼

onTouchMove(e: cc.Event.EventTouch) {this.JoystickMove(e)this.arrowDirection()}arrowDirection() {// 設(shè)置箭頭大小this.setArrowLength()// 計(jì)算夾角this.setArrow(cc.v2(this.Joystick.position))}setArrowLength() {let arrowParamScale = this.Joystick.position.mag() * this.node.scale / this.radius;this.arrow.width = this.arrowMaxLenth * arrowParamScale; // 箭頭長(zhǎng)度this.arrow.opacity = 255 * arrowParamScale; // 箭頭透明度}/*** * @param JoystickPos 搖桿節(jié)點(diǎn)坐標(biāo) */setArrow(JoystickPos: cc.Vec2) {let dir = JoystickPos.sub(cc.v2(0, 0))let vec = cc.v2(0, 1); // 水平向右的對(duì)比向量let radian = dir.signAngle(vec); // 求方向向量與對(duì)比向量間的弧度let rotate = cc.misc.radiansToDegrees(radian); // 將弧度轉(zhuǎn)換為角度this.arrow.angle = -rotate - 90; // ***此處rotate正負(fù)值以及減去的角度根據(jù)自己的圖片去修改***}

再完善一下?lián)u桿回彈時(shí)的動(dòng)畫,讓箭頭可以復(fù)原!

JoystickReset() {let time: number = 0.05;let arrowReset = cc.tween(this.arrow).to(time, {width: 0, opacity: 0})cc.tween(this.Joystick).call(() => {arrowReset.start()}).to(time, {x: 0, y: 0}).start()}

原理:

首先dir是搖桿的向量與搖桿中心的一個(gè)帶方向的向量差,若是求向量夾角必須有另外一個(gè)參考向量,此處定義為(0, 1),求出的值為弧度所以需要將弧度轉(zhuǎn)換為我們要的角度。

弧度轉(zhuǎn)角度公式: 角度 = 弧度 * 180 / PI
cocos中可以直接使用cc.misc.radiansToDegrees()

singAngle()函數(shù)源碼部分如下,如果對(duì)向量的叉乘、點(diǎn)乘的幾何意義不熟悉可以看一下:

/** 帶方向的夾角的弧度。該方法僅用做兼容 2D 計(jì)算。*/signAngle (vector) {cc.warnID(1408, 'vec3.signAngle', 'v2.1', 'cc.v2(selfVector).signAngle(vector)');let vec1 = new Vec2(this.x, this.y);let vec2 = new Vec2(vector.x, vector.y);return vec1.signAngle(vec2);}/** 帶方向的夾角的弧度。*/signAngle (vector: Vec2): number {let angle = this.angle(vector);return this.cross(vector) < 0 ? -angle : angle;}/** 夾角的弧度。*/angle (vector: Vec2): number {var magSqr1 = this.magSqr();var magSqr2 = vector.magSqr();if (magSqr1 === 0 || magSqr2 === 0) {console.warn("Can't get angle between zero vector");return 0.0;}var dot = this.dot(vector);var theta = dot / (Math.sqrt(magSqr1 * magSqr2));theta = misc.clampf(theta, -1.0, 1.0);return Math.acos(theta); // 反余弦函數(shù)}/** 當(dāng)前向量與指定向量進(jìn)行叉乘。*/cross (vector: Vec2): number {return this.x * vector.y - this.y * vector.x;}/***當(dāng)前向量與指定向量進(jìn)行點(diǎn)乘。*/dot (vector: Vec2): number {return this.x * vector.x + this.y * vector.y;}/** 限定浮點(diǎn)數(shù)的最大最小值。* 數(shù)值大于 max_inclusive 則返回 max_inclusive。* 數(shù)值小于 min_inclusive 則返回 min_inclusive。* 否則返回自身。*/misc.clampf = function (value, min_inclusive, max_inclusive) {if (min_inclusive > max_inclusive) {var temp = min_inclusive;min_inclusive = max_inclusive;max_inclusive = temp;}return value < min_inclusive ? min_inclusive : value < max_inclusive ? value : max_inclusive;};

主腳本編寫

(1)主腳本部分實(shí)現(xiàn)功能

  • 更改觸摸范圍為全屏
  • 跨腳本調(diào)用搖桿
  • 移動(dòng)物體

(2)演示

(3)實(shí)現(xiàn)

搖桿腳本部分

// 返回給調(diào)用者需要用到的參數(shù)returnArrowAngle() {let radin = cc.misc.degreesToRadians(-this.arrow.angle - 90);cc.log(this.arrow.angle)let vec = cc.v2(0, 1);let targetVec = vec.rotate(-radin);let data = {angle: this.arrow.angle, // 角度vec: targetVec,speedScale: this.arrow.width / this.arrowMaxLenth,moveState: this.Joystick.x != 0 && this.Joystick.y != 0 ? true : false,}return data;}

原理與計(jì)算朝向原理差不多,只是這次將角度轉(zhuǎn)為弧度,再通過(guò)將參考的向量旋轉(zhuǎn)指定弧度(radin)后,即可得出指定已知角度的向量!

主腳本部分

@property({type: cc.Node, displayName: "可點(diǎn)擊區(qū)域"})touchArea: cc.Node = null;@property({type: cc.Node, displayName: "搖桿"})joystick: cc.Node = null;@property({type: cc.Node, displayName: "移動(dòng)物體"})thing: cc.Node = null;// 此腳本腳本全局函數(shù)區(qū)joystickCom: joystick;moveSpeed = 0.5;moveRotate: number;// 設(shè)置點(diǎn)擊區(qū)域監(jiān)聽onLoad () {this.joystickCom = this.joystick.getComponent(joystick);this.touchArea.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);this.touchArea.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);this.touchArea.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);}onTouchStart(e: cc.Event.EventTouch) {this.joystickCom.onTouchStart(e);}onTouchMove(e: cc.Event.EventTouch) {this.joystickCom.onTouchMove(e);}onTouchEnd(e: cc.Event.EventTouch) {this.joystickCom.onTouchEnd(e);}// 移動(dòng)實(shí)現(xiàn)thingMove() {let joystickFun = this.joystickCom.returnArrowAngle()this.thing.angle = joystickFun.angle + 90; // 自行調(diào)整if (joystickFun.moveState) {this.thing.setPosition(this.thing.position.add(cc.v3(joystickFun.vec.x * 5 * joystickFun.speedScale, joystickFun.vec.y * 5 * joystickFun.speedScale)))}}update (dt) {this.thingMove();} }

第一次發(fā)文章,若有錯(cuò)誤望大佬們指正。

源碼

密碼: agzg

總結(jié)

以上是生活随笔為你收集整理的Cocos Creator制作一个虚拟摇杆的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。