implemented right-click movement, up to speed with original c++ code
This commit is contained in:
100
src/main.rs
100
src/main.rs
@@ -4,13 +4,19 @@ fn main() {
|
|||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, rotate_cube)
|
.add_systems(Update, (handle_click, move_to_target))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct RotatingCube {
|
struct Player {
|
||||||
rotation_speed: f32,
|
move_speed: f32,
|
||||||
|
height_offset: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct MoveTarget {
|
||||||
|
position: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
@@ -29,8 +35,12 @@ fn setup(
|
|||||||
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
|
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
|
||||||
MeshMaterial3d(materials.add(Color::srgb(1.0, 0.0, 0.0))),
|
MeshMaterial3d(materials.add(Color::srgb(1.0, 0.0, 0.0))),
|
||||||
Transform::from_xyz(0.0, 1.0, 0.0),
|
Transform::from_xyz(0.0, 1.0, 0.0),
|
||||||
RotatingCube {
|
Player {
|
||||||
rotation_speed: 2.0,
|
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,
|
shadows_enabled: true,
|
||||||
..default()
|
..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
|
// Plane
|
||||||
@@ -51,27 +61,67 @@ fn setup(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rotate_cube(
|
fn handle_click(
|
||||||
mut query: Query<
|
mouse_button: Res<ButtonInput<MouseButton>>,
|
||||||
(
|
windows: Query<&Window>,
|
||||||
&mut Transform,
|
camera_query: Query<(&Camera, &GlobalTransform)>,
|
||||||
&RotatingCube,
|
mut target_query: Query<&mut MoveTarget>,
|
||||||
&MeshMaterial3d<StandardMaterial>,
|
|
||||||
),
|
|
||||||
Without<Camera3d>,
|
|
||||||
>,
|
|
||||||
time: Res<Time>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
) {
|
) {
|
||||||
for (mut transform, rotating, material_handle) in query.iter_mut() {
|
// Guard clause
|
||||||
transform.rotate_y(rotating.rotation_speed * time.delta_secs());
|
if !mouse_button.just_pressed(MouseButton::Right) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get mutable reference to the actual material
|
let Ok(window) = windows.single() else {
|
||||||
if let Some(material) = materials.get_mut(&material_handle.0) {
|
return;
|
||||||
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
|
let Some(cursor_position) = window.cursor_position() else {
|
||||||
material.base_color = color;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user