♻️ refactor: extract logic step function
parent
2c41ea1e6b
commit
6ccae593d3
|
@ -216,7 +216,7 @@ impl Graphics {
|
||||||
) = camera.transform.clone ().decomposed ();
|
) = camera.transform.clone ().decomposed ();
|
||||||
|
|
||||||
let cam_trans = Vec3::from (cam_trans);
|
let cam_trans = Vec3::from (cam_trans);
|
||||||
let cam_trans = Vec3::new (cam_trans.x.max (state.player.pos.x + 4.0), cam_trans.y, cam_trans.z);
|
let cam_trans = Vec3::new (cam_trans.x.max (state.logic.player.pos.x + 4.0), cam_trans.y, cam_trans.z);
|
||||||
|
|
||||||
let view_mat =
|
let view_mat =
|
||||||
Mat4::from_quat (Quat::from_array (cam_rot).inverse ()) *
|
Mat4::from_quat (Quat::from_array (cam_rot).inverse ()) *
|
||||||
|
@ -244,7 +244,7 @@ impl Graphics {
|
||||||
self.texture_earth.bind ();
|
self.texture_earth.bind ();
|
||||||
|
|
||||||
let mvp = view_mat *
|
let mvp = view_mat *
|
||||||
Mat4::from_translation (state.player.pos) *
|
Mat4::from_translation (state.logic.player.pos) *
|
||||||
Mat4::from_scale ((0.5, 0.5, 0.5).into ());
|
Mat4::from_scale ((0.5, 0.5, 0.5).into ());
|
||||||
glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp);
|
glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp);
|
||||||
glezz::uniform_3fv (unis [&u::ALBEDO], &white);
|
glezz::uniform_3fv (unis [&u::ALBEDO], &white);
|
||||||
|
@ -340,9 +340,9 @@ impl Graphics {
|
||||||
if true {
|
if true {
|
||||||
// Raycast for player shadow
|
// Raycast for player shadow
|
||||||
let coll = opengl_rust::physics::get_candidate (
|
let coll = opengl_rust::physics::get_candidate (
|
||||||
&state.phys_tris, &state.aabbs,
|
&state.static_level.tris, &[],
|
||||||
state.player.pos,
|
state.logic.player.pos,
|
||||||
state.player.pos + Vec3::new (0.0, 0.0, -100.0),
|
state.logic.player.pos + Vec3::new (0.0, 0.0, -100.0),
|
||||||
0.0
|
0.0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,148 @@ mod graphics;
|
||||||
mod virtual_gamepad;
|
mod virtual_gamepad;
|
||||||
|
|
||||||
use graphics::Graphics;
|
use graphics::Graphics;
|
||||||
|
use virtual_gamepad::VirtualGamepad;
|
||||||
|
|
||||||
#[derive (Default)]
|
|
||||||
pub struct GameState {
|
pub struct GameState {
|
||||||
player: PhysicsBody,
|
logic: LogicState,
|
||||||
aabbs: Vec <opengl_rust::physics::Aabb>,
|
static_level: StaticLevel,
|
||||||
phys_tris: Vec <opengl_rust::physics::Triangle>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameState {
|
impl GameState {
|
||||||
|
fn step (&mut self, phys_params: &opengl_rust::physics::Params, p_gp: VirtualGamepad) -> LogicStepOutput
|
||||||
|
{
|
||||||
|
self.logic.step (&self.static_level, phys_params, p_gp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StaticLevel {
|
||||||
|
tris: Vec <opengl_rust::physics::Triangle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive (Clone, Default)]
|
||||||
|
struct LogicState {
|
||||||
|
player: PhysicsBody,
|
||||||
|
player_jump_vec: Option <Vec3>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive (Clone, Copy, Default)]
|
||||||
|
struct LogicStepOutput {
|
||||||
|
reset_level: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogicState {
|
||||||
fn reset_level (&mut self, level: &LoadedLevel) {
|
fn reset_level (&mut self, level: &LoadedLevel) {
|
||||||
self.player = Default::default ();
|
self.player = Default::default ();
|
||||||
self.player.pos = level.player_spawn;
|
self.player.pos = level.player_spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn step (&mut self, static_level: &StaticLevel, phys_params: &opengl_rust::physics::Params, p_gp: VirtualGamepad) -> LogicStepOutput
|
||||||
|
{
|
||||||
|
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 output = LogicStepOutput::default ();
|
||||||
|
let mut wanted_dir = Vec3::default ();
|
||||||
|
|
||||||
|
if p_gp.d_left.any_press () {
|
||||||
|
wanted_dir.x -= 1.0;
|
||||||
|
}
|
||||||
|
if p_gp.d_right.any_press () {
|
||||||
|
wanted_dir.x += 1.0;
|
||||||
|
}
|
||||||
|
if p_gp.d_up.any_press () {
|
||||||
|
wanted_dir.y += 1.0;
|
||||||
|
}
|
||||||
|
if p_gp.d_down.any_press () {
|
||||||
|
wanted_dir.y -= 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wanted_dir = if wanted_dir.length_squared () >= 1.0 {
|
||||||
|
wanted_dir.normalize ()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wanted_dir
|
||||||
|
};
|
||||||
|
|
||||||
|
let wanted_dir = wanted_dir;
|
||||||
|
|
||||||
|
let old_vel = self.player.vel;
|
||||||
|
let old_vel_2 = old_vel * Vec3::new (1.0, 1.0, 0.0);
|
||||||
|
|
||||||
|
let new_vel_2 = match self.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 ()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
self.player.vel = new_vel_2;
|
||||||
|
self.player.vel.z = old_vel.z;
|
||||||
|
|
||||||
|
// dbg! (self.player.vel);
|
||||||
|
|
||||||
|
if p_gp.jump.pressed {
|
||||||
|
if let Some (normal) = self.player_jump_vec.clone () {
|
||||||
|
self.player.vel.z = 0.0;
|
||||||
|
self.player.vel += normal * player_jump_speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let phys_result = opengl_rust::physics::step (&phys_params, &static_level.tris, &[], 0.5, &self.player);
|
||||||
|
|
||||||
|
self.player = phys_result.body;
|
||||||
|
if self.player.pos.z < kill_z {
|
||||||
|
output.reset_level = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracing::debug! ("player pos: {}", self.player.pos);
|
||||||
|
|
||||||
|
self.player_jump_vec = None;
|
||||||
|
for normal in &phys_result.normals_hit {
|
||||||
|
self.player_jump_vec = Some (match self.player_jump_vec {
|
||||||
|
None => *normal,
|
||||||
|
Some (old) => {
|
||||||
|
if normal.z > old.z {
|
||||||
|
*normal
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
old
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -161,23 +290,19 @@ async fn main () -> Result <()> {
|
||||||
let mut graphics = Graphics::new ();
|
let mut graphics = Graphics::new ();
|
||||||
|
|
||||||
let mut gl_state = Default::default ();
|
let mut gl_state = Default::default ();
|
||||||
let mut game_state = GameState::default ();
|
let mut game_state = GameState {
|
||||||
|
logic: Default::default (),
|
||||||
|
static_level: StaticLevel {
|
||||||
|
tris: phys_tris,
|
||||||
|
},
|
||||||
|
};
|
||||||
let phys_params = opengl_rust::physics::Params {
|
let phys_params = opengl_rust::physics::Params {
|
||||||
dt: 1.0 / 60.0,
|
dt: 1.0 / 60.0,
|
||||||
gravity: (0.0, 0.0, -0.5).into (),
|
gravity: (0.0, 0.0, -0.5).into (),
|
||||||
margin: 0.00125,
|
margin: 0.00125,
|
||||||
};
|
};
|
||||||
|
|
||||||
let player_acc = 1.0;
|
game_state.logic.reset_level (&level);
|
||||||
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 <Vec3> = None;
|
|
||||||
|
|
||||||
game_state.reset_level (&level);
|
|
||||||
game_state.phys_tris = phys_tris;
|
|
||||||
|
|
||||||
let mut next_upf_print = 60;
|
let mut next_upf_print = 60;
|
||||||
let mut last_upf_instant = Instant::now ();
|
let mut last_upf_instant = Instant::now ();
|
||||||
|
@ -193,7 +318,7 @@ async fn main () -> Result <()> {
|
||||||
break 'running
|
break 'running
|
||||||
},
|
},
|
||||||
Event::KeyDown { keycode: Some (Keycode::R), .. } => {
|
Event::KeyDown { keycode: Some (Keycode::R), .. } => {
|
||||||
game_state.reset_level (&level);
|
game_state.logic.reset_level (&level);
|
||||||
},
|
},
|
||||||
Event::KeyDown { scancode: Some (Scancode::Space), repeat: false, .. } => {
|
Event::KeyDown { scancode: Some (Scancode::Space), repeat: false, .. } => {
|
||||||
player_gamepad.jump.pressed = true;
|
player_gamepad.jump.pressed = true;
|
||||||
|
@ -237,99 +362,12 @@ async fn main () -> Result <()> {
|
||||||
|
|
||||||
let p_gp = player_gamepad;
|
let p_gp = player_gamepad;
|
||||||
|
|
||||||
let mut wanted_dir = Vec3::default ();
|
let logic_step_output = game_state.step (&phys_params, p_gp);
|
||||||
|
if logic_step_output.reset_level {
|
||||||
if p_gp.d_left.any_press () {
|
game_state.logic.reset_level (&level);
|
||||||
wanted_dir.x -= 1.0;
|
|
||||||
}
|
|
||||||
if p_gp.d_right.any_press () {
|
|
||||||
wanted_dir.x += 1.0;
|
|
||||||
}
|
|
||||||
if p_gp.d_up.any_press () {
|
|
||||||
wanted_dir.y += 1.0;
|
|
||||||
}
|
|
||||||
if p_gp.d_down.any_press () {
|
|
||||||
wanted_dir.y -= 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let wanted_dir = if wanted_dir.length_squared () >= 1.0 {
|
// dbg! (game_state.logic.player.pos);
|
||||||
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 p_gp.jump.pressed {
|
|
||||||
if let Some (normal) = player_jump_vec.clone () {
|
|
||||||
game_state.player.vel.z = 0.0;
|
|
||||||
game_state.player.vel += normal * player_jump_speed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
player_jump_vec = None;
|
|
||||||
for normal in &phys_result.normals_hit {
|
|
||||||
player_jump_vec = Some (match player_jump_vec {
|
|
||||||
None => *normal,
|
|
||||||
Some (old) => {
|
|
||||||
if normal.z > old.z {
|
|
||||||
*normal
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
old
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbg! (game_state.player.pos);
|
|
||||||
|
|
||||||
window.gl_make_current (&gl_ctx).unwrap ();
|
window.gl_make_current (&gl_ctx).unwrap ();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use glam::{Vec2, Vec3};
|
use glam::{Vec2, Vec3};
|
||||||
use partial_min_max::{min, max};
|
use partial_min_max::{min, max};
|
||||||
|
|
||||||
#[derive (Debug, Default, PartialEq)]
|
#[derive (Clone, Copy, Debug, Default, PartialEq)]
|
||||||
pub struct PhysicsBody {
|
pub struct PhysicsBody {
|
||||||
pub pos: Vec3,
|
pub pos: Vec3,
|
||||||
pub vel: Vec3,
|
pub vel: Vec3,
|
||||||
|
|
Loading…
Reference in New Issue