implemented right-click movement, up to speed with original c++ code

This commit is contained in:
2025-12-28 11:43:24 +00:00
parent f88e5cead3
commit 01a94832a1

View File

@@ -4,13 +4,19 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, rotate_cube)
.add_systems(Update, (handle_click, move_to_target))
.run();
}
#[derive(Component)]
struct RotatingCube {
rotation_speed: f32,
struct Player {
move_speed: f32,
height_offset: f32,
}
#[derive(Component)]
struct MoveTarget {
position: Vec3,
}
fn setup(
@@ -29,8 +35,12 @@ fn setup(
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
MeshMaterial3d(materials.add(Color::srgb(1.0, 0.0, 0.0))),
Transform::from_xyz(0.0, 1.0, 0.0),
RotatingCube {
rotation_speed: 2.0,
Player {
move_speed: 10.0,
height_offset: 1.0,
},
MoveTarget {
position: Vec3::new(0.0, 0.0, 0.0),
},
));
@@ -41,7 +51,7 @@ fn setup(
shadows_enabled: true,
..default()
},
Transform::from_xyz(10.0, 10.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// Plane
@@ -51,27 +61,67 @@ fn setup(
));
}
fn rotate_cube(
mut query: Query<
(
&mut Transform,
&RotatingCube,
&MeshMaterial3d<StandardMaterial>,
),
Without<Camera3d>,
>,
time: Res<Time>,
mut materials: ResMut<Assets<StandardMaterial>>,
fn handle_click(
mouse_button: Res<ButtonInput<MouseButton>>,
windows: Query<&Window>,
camera_query: Query<(&Camera, &GlobalTransform)>,
mut target_query: Query<&mut MoveTarget>,
) {
for (mut transform, rotating, material_handle) in query.iter_mut() {
transform.rotate_y(rotating.rotation_speed * time.delta_secs());
// Guard clause
if !mouse_button.just_pressed(MouseButton::Right) {
return;
}
// Get mutable reference to the actual material
if let Some(material) = materials.get_mut(&material_handle.0) {
let blue = (time.elapsed_secs().sin() + 1.0) / 2.0;
let red = 1.0 - blue;
let color = Color::srgb(red, 0.0, blue); // cycling colours
material.base_color = color;
let Ok(window) = windows.single() else {
return;
};
let Some(cursor_position) = window.cursor_position() else {
return;
};
let Ok((camera, camera_transform)) = camera_query.single() else {
return;
};
let Ok(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
return;
};
// check for sky clicks
if ray.direction.y > 0.0 {
return;
}
// Calculate the distance that the intercept with the ground occurs
let t = -ray.origin.y / ray.direction.y;
// plug T into our formula
let intersection = ray.origin + ray.direction * t;
for mut target in target_query.iter_mut() {
target.position = intersection;
}
}
fn move_to_target(mut query: Query<(&mut Transform, &MoveTarget, &Player)>, time: Res<Time>) {
for (mut transform, target, player) in query.iter_mut() {
let adjusted_target = target.position + Vec3::Y * player.height_offset;
let direction = adjusted_target - transform.translation;
let distance = direction.length();
// stop divide by 0 errors
if distance < 0.001 {
continue;
}
let move_amount = player.move_speed * time.delta_secs();
// Snap
if distance < move_amount {
transform.translation = adjusted_target;
} else {
transform.translation += direction.normalize() * move_amount;
}
}
}