♻️ refactor: extract
parent
5509aece8f
commit
74251fcf37
|
@ -0,0 +1,136 @@
|
|||
use opengl_rust::{
|
||||
prelude::*,
|
||||
physics::PhysicsBody,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
LoadedLevel,
|
||||
StaticLevel,
|
||||
VirtualGamepad,
|
||||
};
|
||||
|
||||
#[derive (Clone, Default)]
|
||||
pub struct LogicState {
|
||||
pub player: PhysicsBody,
|
||||
player_jump_vec: Option <Vec3>,
|
||||
}
|
||||
|
||||
#[derive (Clone, Copy, Default)]
|
||||
pub struct LogicStepOutput {
|
||||
pub reset_level: bool,
|
||||
}
|
||||
|
||||
impl LogicState {
|
||||
pub fn reset_level (&mut self, level: &LoadedLevel) {
|
||||
self.player = Default::default ();
|
||||
self.player.pos = level.player_spawn;
|
||||
}
|
||||
|
||||
pub 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
|
||||
}
|
||||
}
|
|
@ -6,15 +6,16 @@ use anyhow::Result;
|
|||
|
||||
use opengl_rust::{
|
||||
prelude::*,
|
||||
physics::PhysicsBody,
|
||||
};
|
||||
|
||||
mod graphics;
|
||||
mod level_loader;
|
||||
mod logic;
|
||||
mod virtual_gamepad;
|
||||
|
||||
use graphics::Graphics;
|
||||
use level_loader::LoadedLevel;
|
||||
use logic::LogicState;
|
||||
use virtual_gamepad::VirtualGamepad;
|
||||
|
||||
pub struct GameState {
|
||||
|
@ -26,132 +27,6 @@ pub struct StaticLevel {
|
|||
tris: Vec <opengl_rust::physics::Triangle>,
|
||||
}
|
||||
|
||||
#[derive (Clone, Default)]
|
||||
pub 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) {
|
||||
self.player = Default::default ();
|
||||
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]
|
||||
async fn main () -> Result <()> {
|
||||
tracing_subscriber::fmt::fmt ()
|
||||
|
|
Loading…
Reference in New Issue