I'm trying to use Bevy 0.3, and I'm able to use the built-in transforms easily with Camera2dComponents::default()
.
This is top-down 2D.
The issue is trying to synchronise the player's rotation to the mouse:
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);
}
In this transform is my player's Transform, of course. Here's what this outputs:
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) }
I'm a bit confused by what up
is in look_at in 2D, but I tried a few different values and the result is always the same: as soon as that look_at runs, the player disappears from view.
Why is the camera not seeing the player anymore after that, and what am I doing wrong with this look_at?
While you're using Camera2dComponents
which is intended for 2D, Transform
is not. Transform
is more general, and includes what's needed for 3D as well.
In your case, it sounds like 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
) and looks towards a target
(the first argument). The up
is then a 3D vector of what the "world up" is. So that it can calculate the rotation correction.
Updated Solution:
If you want to rotate the top-down 2D player, i.e. having one side of the player look towards the cursor. Then you need to calculate the angle between the position of your player and the target. You can do that easily using Vec2::angle_between()
.
let pos: Vec2 = ...;
let target: Vec2 = ...;
let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);
Depending on the orientation of the player itself, i.e. if you're using a sprite, the default orientation could be "looking" to the left or up. Then you might need to offset the angle
. You can do that by e.g. adding + FRAC_PI_2
(or however much is needed.)
Assuming transform.translation
is the center position of the player, then it will look something like this:
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);
Old Answer:
Since you want to position your camera over the cursor in a top-down 2D view. Then instead you have to use from_translation()
or simply shift self.translation
, which is the position of your camera.
transform.translation = Vec3::new(event.position.x(), event.position.y(), 0.0);
If you want the cursor position to be at the center of the screen, then you might have to subtract half the screen size.