From 01c5d765869d2630ba12266d579145001ba4b22e Mon Sep 17 00:00:00 2001 From: JP Stringham Date: Sat, 7 Feb 2026 18:15:14 -0500 Subject: [PATCH] some physics --- src/main.rs | 72 +++++++++++++++++++++++++++++++++++++++++++------- src/physics.rs | 0 src/player.rs | 8 ++++-- 3 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 src/physics.rs diff --git a/src/main.rs b/src/main.rs index 46dc0f4..1f30823 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ mod ldtk; +mod physics; mod player; -use bevy::{image::Image, prelude::*}; +use bevy::{image::Image, math::I64Vec2, prelude::*}; use crate::player::Player; @@ -140,9 +141,9 @@ fn levelload( } li.entities.iter().for_each(|ei| { - let pos = IVec2 { - x: ei.position.x * 16, - y: 256 - ei.position.y * 16, + let pos = I64Vec2 { + x: ei.position.x as i64 * 16, + y: 256 - ei.position.y as i64 * 16, }; let mut spawned_ent = commands.spawn(( Name::from(ei.identifier.clone()), @@ -150,7 +151,10 @@ fn levelload( )); match ei.identifier.as_str() { "Player" => { - spawned_ent.insert(Player { pos }); + spawned_ent.insert(Player { + pos, + vel: I64Vec2::ZERO, + }); spawned_ent.insert(Sprite::from_color(Color::WHITE, vec2(16., 16.))); } "Parsnip" => { @@ -167,8 +171,13 @@ fn levelload( next_state.set(AppState::Main); } -fn gameloop(keyb: Res>, mut player: Single<(&mut Player, &mut Transform)>) { - let mut dir = IVec2::ZERO; +fn gameloop( + keyb: Res>, + mut player_sing: Single<(&mut Player, &mut Transform)>, +) { + const UNITS_TO_PX_SCALE: i64 = 100; + const MAX_SPEED: i64 = 2 * UNITS_TO_PX_SCALE; + let mut dir = I64Vec2::ZERO; if keyb.pressed(KeyCode::KeyA) || keyb.pressed(KeyCode::ArrowLeft) { dir.x += -1; @@ -186,8 +195,51 @@ fn gameloop(keyb: Res>, mut player: Single<(&mut Player, &m dir.y = -1; } - let p_pos = player.0.pos + dir; - player.0.pos = p_pos; + let player = player_sing.0.as_mut(); - *player.1 = Transform::from_xyz(p_pos.x as f32, p_pos.y as f32, 100.); + // player vel and pos are in px / 100 + let mut p_vel = player.vel + dir * UNITS_TO_PX_SCALE * MAX_SPEED; + if dir.length_squared() == 0 { + p_vel = (p_vel * 8) / 10; + info!("Slowing! {p_vel}"); + } else { + info!("Changing vel: {p_vel}") + } + + // want unit vector with int math + // normally this would be x / len, y / len + + // eg (2,2) -> length of 4 -> (0.5, 0.5) + // how to do with squares? + + // (2, 2) -> sqr length of 8 -> sqr x / 8 -> 0.5... yes? + // but we can't get half units obvs so we need to work in centi-units + // 200, 200 -> should become 50, 50 + + // max speed is 3 px per update + if p_vel.length_squared() >= MAX_SPEED.pow(2) { + let l = p_vel.length_squared(); + let x = p_vel.x * p_vel.x; + let y = p_vel.y * p_vel.y; + + p_vel.x = match p_vel.x { + ..0 => (x * -MAX_SPEED) / l, + _ => (x * MAX_SPEED) / l, + }; + p_vel.y = match p_vel.y { + ..0 => (y * -MAX_SPEED) / l, + _ => (y * MAX_SPEED) / l, + }; + + info!("Nerfed speed {p_vel}"); + } + + player.vel = p_vel; + player.pos += p_vel; + + *player_sing.1 = Transform::from_xyz( + (player.pos.x as f32) / UNITS_TO_PX_SCALE as f32, + (player.pos.y as f32) / UNITS_TO_PX_SCALE as f32, + 100., + ); } diff --git a/src/physics.rs b/src/physics.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/player.rs b/src/player.rs index 74ed61a..9888ff3 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,6 +1,10 @@ -use bevy::{ecs::component::Component, math::IVec2}; +use bevy::{ + ecs::component::Component, + math::{I64Vec2, IVec2}, +}; #[derive(Default, Debug, Component)] pub struct Player { - pub pos: IVec2, + pub pos: I64Vec2, + pub vel: I64Vec2, }