(3D小游戏相关) 在update中计算出沿着圆移动的路径
问题:从点A移动到点B,要求移动的路径为圆弧形式
思路:做一个圆,使AB都处于这个圆上,沿着圆移动即可走出圆弧路径。AB相连做直线,取直线AB的垂线C,所需圆的圆心位于直线C上。然后根据具体需求,取出所需要的圆即可
举例:已知AB坐标,获取A到B的圆弧路径。要求AB路线的弧度所对应的角度为45度
注:以下算法仅针对游戏中的具体需求,提出一种思路和解,算法步骤并不完美,可根据实际问题优化
Laya + TypeScript 代码实现:
已知点A点B坐标和圆弧路径角度
1 2 3
| const A = new Laya.Vector3(0, 0, 0) const B = new Laya.Vector3(9, 9, 9) const Angle = 45
|
计算出AB所走圆的圆心与半径
注意:
由于AB点处于三维空间,AB两点无法确定一个平面,而计算出路径是在平面之中,所以需要第3个点,或着一个方向,来帮助确定路径所在的平面。具体确定平面的方法,根据具体需求来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| let center = null let radius = null
let b = Laya.Vector3.distance(A, B) / 2
let c = b / Math.sin(Angle)
let a = Math.sqrt(c * c - b * b)
let C = new Laya.Vector3( (A.x + B.x) / 2, (A.y + B.y) / 2, (A.z + B.z) / 2 )
let up = new Laya.Vector3(0, 1, 0)
center = new Laya.Vector3 Laya.Vector3.scale(up, -a, up) Laya.Vector3.add(C, up, center) radius = c
|
取得路径圆的圆心和半径之后,可以开始计算圆的切线方向。在每一帧移动中,使移动方向为切线方向,即可走出圆弧路径。
以下代码计算圆的切线方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| let cur = sp3.transform.position
let dir_a_b = new Laya.Vector3 Laya.Vector3.subtract(B, A, dir_a_b) Laya.Vector3.normalize(dir_a_b, dir_a_b)
let dir_cur_c = new Laya.Vector3 Laya.Vector3.subtract(c, cur, dir_cur_c) Laya.Vector3.normalize(dir_cur_c, dir_cur_c)
let dir_v1 = new Laya.Vector3 Laya.Vector3.cross(dir_a_b, dir_cur_c, dir_v1) Laya.Vector3.normalize(dir_v1, dir_v1)
let dir_v2 = new Laya.Vector3 Laya.Vector3.cross(dir_cur_c, dir_v1, dir_v2) Laya.Vector3.normalize(dir_v2, dir_v2)
|
每一帧的移动都沿着圆的切线方向进行
1 2 3 4
| let dis = speed * Laya.timer.delta let tag = new Laya.Vector3 Laya.Vector3.scale(dir_v2, dis, tag) Laya.Vector3.add(cur, tag, tag)
|
取得每一帧的目标位置后,还需要对目标位置做一个修正。防止跳帧或移动距离过大的情况下,走出的路径偏离圆弧
1 2 3 4 5 6 7 8 9 10 11
| if (Laya.Vector3.distance(tag, center) > radius) { let dir = new Laya.Vector3 Laya.Vector3.subtract(tag, center, dir) Laya.Vector3.normalize(dir, dir) Laya.Vector3.scale(dir, radius, dir) Laya.Vector3.add(center, dir, tag) }
|
以上算法思路在游戏中实现了:
- 人物荡秋千路径
- 向前跳跃落地路径
- 45度圆角转弯寻路