diff --git a/crate.png b/crate.png index 6c19367..32838ae 100644 Binary files a/crate.png and b/crate.png differ diff --git a/src/bin/platformer/main.rs b/src/bin/platformer/main.rs index 243eb22..5562c10 100644 --- a/src/bin/platformer/main.rs +++ b/src/bin/platformer/main.rs @@ -154,8 +154,12 @@ async fn main () -> Result <()> { margin: 0.00125, }; - let player_speed = 2.0; - let player_jump_speed = 8.0; + let player_acc = 1.0; + let player_acc_air = 0.125; + let player_max_speed = 4.0; + let player_max_speed_air = 8.0; + let player_jump_speed = 12.0; + let kill_z = -3.0; let mut player_jump_vec: Option = None; game_state.reset_level (&level); @@ -184,35 +188,71 @@ async fn main () -> Result <()> { let kb_state = event_pump.keyboard_state (); - let player_speed = if let Some (v) = player_jump_vec.as_ref () { - if v.z > 0.5 { - game_state.player.vel.x = 0.0; - game_state.player.vel.y = 0.0; - player_speed - } - else { - 0.125 - } - } - else { - 0.125 - }; + let mut wanted_dir = Vec3::default (); if kb_state.is_scancode_pressed (Scancode::Left) { - game_state.player.vel.x -= player_speed; + wanted_dir.x -= 1.0; } if kb_state.is_scancode_pressed (Scancode::Right) { - game_state.player.vel.x += player_speed; + wanted_dir.x += 1.0; } if kb_state.is_scancode_pressed (Scancode::Up) { - game_state.player.vel.y += player_speed; + wanted_dir.y += 1.0; } if kb_state.is_scancode_pressed (Scancode::Down) { - game_state.player.vel.y -= player_speed; + wanted_dir.y -= 1.0; } + let wanted_dir = if wanted_dir.length_squared () >= 1.0 { + wanted_dir.normalize () + } + else { + wanted_dir + }; + + let old_vel = game_state.player.vel; + let old_vel_2 = old_vel * Vec3::new (1.0, 1.0, 0.0); + + let new_vel_2 = match player_jump_vec.as_ref () { + Some (v) => { + // Ground + let acc = player_acc * v.z * v.z; + let wanted_vel = wanted_dir * player_max_speed; + let diff = wanted_vel - old_vel_2; + + if diff.length_squared () < acc * acc { + // We're near the wanted velocity, so snap to it + wanted_vel + } + else { + // We're not near the wanted velocity, so accelerate + old_vel_2 + diff.normalize_or_zero () * acc + } + }, + // Air + None => { + let proposed_vel = old_vel_2 + wanted_dir * player_acc_air; + + if old_vel_2.length_squared () < player_max_speed_air * player_max_speed_air { + // Air control is normal below player_max_speed + proposed_vel + } + else { + // If the player's input would push them beyond player_max_speed, + // apply drag to preserve overall energy + proposed_vel * old_vel_2.length () / proposed_vel.length () + } + }, + }; + + game_state.player.vel = new_vel_2; + game_state.player.vel.z = old_vel.z; + + dbg! (game_state.player.vel); + if player_wants_to_jump { if let Some (normal) = player_jump_vec.clone () { + game_state.player.vel.z = 0.0; game_state.player.vel += normal * player_jump_speed; } } @@ -220,8 +260,10 @@ async fn main () -> Result <()> { let phys_result = opengl_rust::physics::step (&phys_params, &game_state.phys_tris, &[], 0.5, &game_state.player); game_state.player = phys_result.body; + if game_state.player.pos.z < kill_z { + game_state.reset_level (&level); + } // tracing::debug! ("player pos: {}", game_state.player.pos); - // dbg! (player_jump_vec); player_jump_vec = None; for normal in &phys_result.normals_hit { @@ -238,6 +280,8 @@ async fn main () -> Result <()> { }); } + // dbg! (player_jump_vec); + window.gl_make_current (&gl_ctx).unwrap (); graphics.draw (&game_state, &mut gl_state, &level); @@ -286,7 +330,6 @@ impl LoadedLevel { } else if let Some (mesh) = node.mesh () { - println! ("Node {:?} is a mesh", node.name ()); for (i, prim) in mesh.primitives ().enumerate () { let positions = match prim.get (&Semantic::Positions) { None => continue, @@ -312,9 +355,6 @@ impl LoadedLevel { None => continue, Some (x) => x, }; - dbg! (positions.offset (), pos_view.offset (), pos_view.stride ()); - dbg! (normals.offset (), norm_view.offset (), norm_view.stride ()); - dbg! (indices.offset (), indices.data_type (), indices_view.offset (), indices_view.stride ()); } } }