distributed_physics_test/src/game/runtime.rs
Michael Bradley 27b4644730
All checks were successful
CI / Formatting (push) Successful in 32s
Update to Bevy 0.17.2
2025-10-13 15:17:23 -04:00

83 lines
2.8 KiB
Rust

use core::f32;
use avian2d::prelude::*;
use bevy::{
input::mouse::{AccumulatedMouseScroll, MouseScrollUnit},
math::curve::EaseFunction::SmoothStep,
prelude::*,
};
use super::objects::{Player, Radius};
/// Move the player character based on the keyboard input
pub fn move_player(
time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>,
mut query: Single<(&mut LinearVelocity, &Radius), With<Player>>,
) {
let (ref mut velocity, radius) = *query;
let acceleration_energy = 150000.0;
// Although it would arguably be more accurate to divide by pi to get the actual mass (or include the density
// somehow), `acceleration_energy` is in arbitrary units so we can just pretend it's proper physics
let delta_v = acceleration_energy * time.delta_secs() / radius.0.powi(2);
let mut direction = Vec2::ZERO;
if keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]) {
direction.y += 1.0;
}
if keyboard_input.any_pressed([KeyCode::KeyS, KeyCode::ArrowDown]) {
direction.y -= 1.0;
}
if keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]) {
direction.x -= 1.0;
}
if keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]) {
direction.x += 1.0;
}
// This would be easier if I could compare floats with 0 and still sleep at night
let circularize = if direction.x.abs() > 0.0 && direction.y.abs() > 0.0 {
f32::consts::FRAC_1_SQRT_2
} else {
1.0
};
// Kinda annoying I have to manually assign the fields here but I'll leave it in case I remember a better way later
velocity.x += direction.x * delta_v * circularize;
velocity.y += direction.y * delta_v * circularize;
}
/// Neatly exit game
pub fn quit(mut exit: MessageWriter<AppExit>) {
exit.write(AppExit::Success);
}
/// Follow the player character with the camera
pub fn move_camera(
time: Res<Time>,
mut camera: Single<&mut Transform, (Without<Player>, With<IsDefaultUiCamera>)>,
player: Single<&Transform, (With<Player>, Without<IsDefaultUiCamera>)>,
) {
camera.translation = camera.translation.lerp(
player.translation,
SmoothStep.sample_clamped(time.delta_secs() * 15.0),
);
}
/// Adjust the camera zoom based on the scroll wheel input
pub fn zoom_camera(
mut camera: Single<&mut Projection, With<IsDefaultUiCamera>>,
scroll: Res<AccumulatedMouseScroll>,
) -> Result {
let Projection::Orthographic(ref mut projection) = **camera else {
return Err("Default camera was not orthographic".into());
};
let scroll_type_multiplier = match scroll.unit {
MouseScrollUnit::Line => 0.1,
MouseScrollUnit::Pixel => 0.001,
};
projection.scale = (projection.scale - scroll.delta.y * scroll_type_multiplier).clamp(0.1, 4.0);
Ok(())
}