2d 中的 Bevy 旋转
Bevy rotation in 2d
我正在尝试使用 Bevy 0.3,并且我能够通过 Camera2dComponents::default()
轻松使用内置转换。
这是自上而下的 2d.
问题是试图将玩家的旋转与鼠标同步:
for event in evreader.iter(&cursor_moved_events) {
println!("{:?}", transform);
transform.look_at(Vec3::new(event.position.x(), event.position.y(), 0.0), Vec3::new(0.0, 0.0, 1.0));
println!("{:?}", transform);
}
在这个变换中当然是我的玩家的变换。
输出结果如下:
Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.0, 0.0, 0.0, 1.0), scale: Vec3(1.0, 1.0, 1.0) }
Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.5012898, -0.49870682, -0.49870682, 0.5012898), scale: Vec3(1.0, 1.0, 1.0) }
我对 2d 中 look_at 中的 up
感到有点困惑,但我尝试了几个不同的值,结果总是一样的:一旦 look_at 运行,播放器从视图中消失。
为什么在那之后相机再也看不到玩家了,我做错了什么look_at?
谢谢
当您使用时 Camera2dComponents
which is intended for 2D, Transform
不是。 Transform
更 一般 ,并且还包括 3D 所需的内容。
在你的例子中,它听起来像 look_at()
might not do what you think it does. It creates a 3D look at matrix which computes a view matrix which is "at
" a position (self.translation
) 并且看向 target
(第一个参数)。 up
是“world up”的 3D 矢量。以便它可以计算旋转校正。
更新的解决方案:
如果您想旋转自上而下的 2D 播放器,即让播放器的一侧看朝向光标。然后你需要计算你的球员的位置和目标之间的角度。您可以使用 Vec2::angle_between()
.
轻松做到这一点
let pos: Vec2 = ...;
let target: Vec2 = ...;
let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);
取决于玩家本身的方向,即如果您使用的是精灵,则默认方向可能是向左或向上“看”。那么您可能需要偏移 angle
。你可以通过例如添加 + FRAC_PI_2
(或者需要多少。)
假设 transform.translation
是玩家的中心位置,那么它将看起来像这样:
use bevy::math::{Quat, Vec2};
let pos = transform.translation.truncate();
let target = event.position;
let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);
旧答案:
因为您想在自上而下的 2D 视图中将相机放置在光标上方。然后你必须使用 from_translation()
or simply shift self.translation
,这是你的相机的位置。
transform.translation = Vec3::new(event.position.x(), event.position.y(), 0.0);
如果你想让光标位置在屏幕的中心,那么你可能需要减去一半的屏幕尺寸。
对于未来的用户,我在 Bevy v0.5 中遇到了类似的问题(让 2d sprite 面对鼠标点击位置)并且出于某种原因我无法获得可接受的答案。
我通过 Unity 线程中的这个实现解决了它:https://answers.unity.com/questions/650460/rotating-a-2d-sprite-to-face-a-target-on-a-single.html
代码示例:
let diff = targ.translation - pos.translation;
let angle = diff.y.atan2(diff.x); // Add/sub FRAC_PI here optionally
pos.rotation = Quat::from_axis_angle(Vec3::new(0., 0., 1.), angle);
我正在尝试使用 Bevy 0.3,并且我能够通过 Camera2dComponents::default()
轻松使用内置转换。
这是自上而下的 2d.
问题是试图将玩家的旋转与鼠标同步:
for event in evreader.iter(&cursor_moved_events) {
println!("{:?}", transform);
transform.look_at(Vec3::new(event.position.x(), event.position.y(), 0.0), Vec3::new(0.0, 0.0, 1.0));
println!("{:?}", transform);
}
在这个变换中当然是我的玩家的变换。 输出结果如下:
Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.0, 0.0, 0.0, 1.0), scale: Vec3(1.0, 1.0, 1.0) }
Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.5012898, -0.49870682, -0.49870682, 0.5012898), scale: Vec3(1.0, 1.0, 1.0) }
我对 2d 中 look_at 中的 up
感到有点困惑,但我尝试了几个不同的值,结果总是一样的:一旦 look_at 运行,播放器从视图中消失。
为什么在那之后相机再也看不到玩家了,我做错了什么look_at?
谢谢
当您使用时 Camera2dComponents
which is intended for 2D, Transform
不是。 Transform
更 一般 ,并且还包括 3D 所需的内容。
在你的例子中,它听起来像 look_at()
might not do what you think it does. It creates a 3D look at matrix which computes a view matrix which is "at
" a position (self.translation
) 并且看向 target
(第一个参数)。 up
是“world up”的 3D 矢量。以便它可以计算旋转校正。
更新的解决方案:
如果您想旋转自上而下的 2D 播放器,即让播放器的一侧看朝向光标。然后你需要计算你的球员的位置和目标之间的角度。您可以使用 Vec2::angle_between()
.
let pos: Vec2 = ...;
let target: Vec2 = ...;
let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);
取决于玩家本身的方向,即如果您使用的是精灵,则默认方向可能是向左或向上“看”。那么您可能需要偏移 angle
。你可以通过例如添加 + FRAC_PI_2
(或者需要多少。)
假设 transform.translation
是玩家的中心位置,那么它将看起来像这样:
use bevy::math::{Quat, Vec2};
let pos = transform.translation.truncate();
let target = event.position;
let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);
旧答案:
因为您想在自上而下的 2D 视图中将相机放置在光标上方。然后你必须使用 from_translation()
or simply shift self.translation
,这是你的相机的位置。
transform.translation = Vec3::new(event.position.x(), event.position.y(), 0.0);
如果你想让光标位置在屏幕的中心,那么你可能需要减去一半的屏幕尺寸。
对于未来的用户,我在 Bevy v0.5 中遇到了类似的问题(让 2d sprite 面对鼠标点击位置)并且出于某种原因我无法获得可接受的答案。
我通过 Unity 线程中的这个实现解决了它:https://answers.unity.com/questions/650460/rotating-a-2d-sprite-to-face-a-target-on-a-single.html
代码示例:
let diff = targ.translation - pos.translation;
let angle = diff.y.atan2(diff.x); // Add/sub FRAC_PI here optionally
pos.rotation = Quat::from_axis_angle(Vec3::new(0., 0., 1.), angle);