CocosCreator实战篇 | 制作一个物体围绕另一个物体旋转

阅读: 评论:0

CocosCreator实战篇 | 制作一个物体围绕另一个物体旋转

CocosCreator实战篇 | 制作一个物体围绕另一个物体旋转

  • 📢博客主页:

  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 📢本文由肩匣与橘编写,首发于CSDN🙉

  • 📢生活依旧是美好而又温柔的,你也是✨


🏳️‍🌈一个物体围绕另一个物体旋转

📢前言

🏳️‍🌈整体思路

🏳️‍🌈代码实现


📢前言

        在游戏开发过程中,可能会有让一个物体围绕另一个物体旋转的需求,就比如月球围绕着地球旋转,同时地球也在围绕着太阳旋转。本文给大家分享一个实现一个物体围绕另一个物体旋转的方案。


🏳️‍🌈整体思路

对于这类持续运动的实现,我们都可以在 update 中每帧进行操作。

首先假定有两个物体 A 与 B ,且二者处于同一层级或者将 A 作为 B 的父节点。我们每帧都根据 A 的位置、两者的角度以及他们之间的距离来计算 B 的位置,这样即使 A 的位置发生变化 B 也能在正确的轨道上运动。

并且我们可以根据二者之间的角度来让 B 的某一面始终指向 A 。


🏳️‍🌈代码实现

首先定义一个枚举 Axis 来作为旋转时的指向选项,同时导出给外部调用:

export enum Axis {PositiveX, // 正 X 轴PositiveY, // 正 Y 轴NegativeX, // 负 X 轴NegativeY, // 负 Y 轴
}

定义我们需要用到的属性和参数(只有 faceToTarget 为 true 时才会显示 faceAxis 选项):

@property({ type: cc.Node, tooltip: '围绕旋转的目标' })
public target: cc.Node = null;@property({ tooltip: '顺时针旋转' })
public clockwise: boolean = true;@property({ tooltip: '旋转一圈花费的时间' })
public timePerRound: number = 10;@property({ tooltip: '是否始终面向目标节点' })
public faceToTarget: boolean = false;@property({type: cc.Enum(Axis),tooltip: '面向目标节点的轴:n- PositiveX:正 X 轴n- PositiveY:正 Y 轴n- NegativeX:负 X 轴n- NegativeY:负 Y 轴',visible() { return this.faceToTarget }})
public faceAxis: Axis = Axis.NegativeY;@property({ tooltip: '自动开始旋转' })
public autoStart: boolean = false;public angle: number = 0; // 角度public radius: number = 0; // 半径private isRotating: boolean = false; // 标志位,是否正在旋转

然后我们需要一个 public 的 run 函数来作为启动函数,这样就可以在其他脚本主动调用该函数了。并且在启动函数里先获取初始的角度和半径:

/*** 开始围绕目标节点旋转* @param target 目标节点* @param clockwise 是否顺时针旋转* @param timePerRound 旋转一圈的时间* @param faceToTarget 是否始终面向目标节点* @param faceAxis 面向目标节点的轴*/
public run(target?: cc.Node, clockwise?: boolean, timePerRound?: number, faceToTarget?: boolean, faceAxis?: Axis) {if (target) this.target = target;if (clockwise) this.clockwise = clockwise;if (timePerRound) this.timePerRound = timePerRound;if (faceToTarget) this.faceToTarget = faceToTarget;if (faceAxis) this.faceAxis = faceAxis;if (!this.target) {cc.log('No target!');return;}// 计算初始角度和半径this.angle = Angle(Position(), Position());this.radius = Distance(Position(), Position());// 开始this.isRotating = true;
}

其中的 getAngle 函数用来计算两个点之间的角度:

/*** 获取两点间的角度* @param p1 点1* @param p2 点2*/
private getAngle(p1: cc.Vec2, p2: cc.Vec2): number {return Math.atan(p2.y - p1.y / p2.x - p1.x);
}

而 getDistance 函数用来计算两个点之间的距离:

/*** 获取两点间的距离* @param p1 点1* @param p2 点2*/
private getDistance(p1: cc.Vec2, p2: cc.Vec2): number {return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}

接下来在 update 中实现主要逻辑:

update(dt: number) {if (!this.isRotating || !this.target) return;// 将角度转换为弧度let radian = Math.PI / 180 * this.angle;// 更新节点的位置de.x = this.target.x + this.radius * s(radian);de.y = this.target.y + this.radius * Math.sin(radian);// 更新节点的角度if (this.faceToTarget) {switch (this.faceAxis) {case Axis.de.angle = this.angle + 180;break;case Axis.de.angle = this.angle + 90;break;case Axis.de.angle = this.angle;break;case Axis.de.angle = this.angle - 90;break;}}// 计算下一帧的角度let anglePerFrame = dt * (360 / this.timePerRound);if (this.clockwise) this.angle -= anglePerFrame;else this.angle += anglePerFrame;// 重置角度,避免数值过大if (this.angle >= 360) this.angle %= 360;else if (this.angle <= -360) this.angle %= -360;
}

在 start 中执行自动启动的逻辑:

start() {if (this.autoStart) this.run();
}

最后还需要一个 public 的 stop 函数来停止当前的旋转:

/*** 停止旋转*/
public stop() {this.isRotating = false;
}

本文发布于:2024-01-31 00:05:20,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170663072623804.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:AI小记(一)
下一篇:css布局技巧
标签:物体   实战篇   CocosCreator
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23