diff --git a/src/body.rs b/src/body.rs index 496beb7..d5d4e9c 100644 --- a/src/body.rs +++ b/src/body.rs @@ -257,28 +257,70 @@ fn get_control_dir(controls: u32) -> glam::Vec3{ return control_dir } -pub struct PhysicsState { - pub body: Body, - pub hitbox_halfsize: glam::Vec3, - pub contacts: std::collections::HashSet::, +pub struct GameMechanicsState{ + pub spawn_id:u32, + //jump_counts:HashMap, +} +impl std::default::Default for GameMechanicsState{ + fn default() -> Self { + Self{ + spawn_id:0, + } + } +} + +pub struct WorldState{} + +pub struct StyleModifiers{ + pub controls_mask:u32,//controls which are unable to be activated + pub controls_held:u32,//controls which must be active to be able to strafe + pub mv:f32, + pub walkspeed:f32, + pub friction:f32, + pub walk_accel:f32, + pub gravity:glam::Vec3, + pub strafe_tick_num:TIME, + pub strafe_tick_den:TIME, + pub hitbox_halfsize:glam::Vec3, +} +impl std::default::Default for StyleModifiers{ + fn default() -> Self { + Self{ + controls_mask: !0&!(CONTROL_MOVEUP|CONTROL_MOVEDOWN), + controls_held: 0, + strafe_tick_num: 100,//100t + strafe_tick_den: 1_000_000_000, + gravity: glam::vec3(0.0,-100.0,0.0), + friction: 1.2, + walk_accel: 90.0, + mv: 2.7, + walkspeed: 18.0, + hitbox_halfsize: glam::vec3(1.0,2.5,1.0), + } + } +} + +pub struct PhysicsState{ + pub time:TIME, + pub body:Body, + pub world:WorldState,//currently there is only one state the world can be in + pub game:GameMechanicsState, + pub style:StyleModifiers, + pub contacts:std::collections::HashSet::, //pub intersections: Vec, - pub models: Vec, //camera must exist in state because wormholes modify the camera, also camera punch - pub camera: Camera, - pub mouse_interpolation: MouseInterpolationState, - pub controls: u32, - pub time: TIME, - pub strafe_tick_num: TIME, - pub strafe_tick_den: TIME, - pub tick: u32, - pub mv: f32, - pub walk: WalkState, - pub walkspeed: f32, - pub friction: f32, - pub walk_accel: f32, - pub gravity: glam::Vec3, - pub grounded: bool, - pub spawn_point: glam::Vec3, + pub camera:Camera, + pub mouse_interpolation:MouseInterpolationState, + pub controls:u32, + pub walk:WalkState, + pub grounded:bool, + //all models + pub models:Vec, + + pub stages:Vec, + //the spawn point is where you spawn when you load into the map. + //This is not the same as Reset which teleports you to Spawn0 + pub spawn_point:glam::Vec3, } #[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)] @@ -390,10 +432,22 @@ impl Aabb { type TreyMeshFace = AabbFace; type TreyMesh = Aabb; +enum PhysicsCollisionAttributes{ + Contact{//track whether you are contacting the object + contacting:crate::model::ContactingAttributes, + general:crate::model::GameMechanicAttributes, + }, + Intersect{//track whether you are intersecting the object + intersecting:crate::model::IntersectingAttributes, + general:crate::model::GameMechanicAttributes, + }, +} + pub struct ModelPhysics { //A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es //in this iteration, all it needs is extents. mesh: TreyMesh, + attributes:PhysicsCollisionAttributes, } impl ModelPhysics { @@ -522,7 +576,7 @@ impl PhysicsState { } fn next_strafe_instruction(&self) -> Option> { return Some(TimedInstruction{ - time:(self.time*self.strafe_tick_num/self.strafe_tick_den+1)*self.strafe_tick_den/self.strafe_tick_num, + time:(self.time*self.style.strafe_tick_num/self.style.strafe_tick_den+1)*self.style.strafe_tick_den/self.style.strafe_tick_num, //only poll the physics if there is a before and after mouse event instruction:PhysicsInstruction::StrafeTick }); @@ -572,7 +626,7 @@ impl PhysicsState { self.body.acceleration=a; self.walk.state=WalkEnum::Reached; }else{ - let accel=self.walk_accel.min(self.gravity.length()*self.friction); + let accel=self.style.walk_accel.min(self.style.gravity.length()*self.style.friction); let time_delta=target_diff.length()/accel; let mut a=target_diff/time_delta; self.contact_constrain_acceleration(&mut a); @@ -601,7 +655,7 @@ impl PhysicsState { fn mesh(&self) -> TreyMesh { let mut aabb=Aabb::new(); for vertex in Aabb::unit_vertices(){ - aabb.grow(self.body.position+self.hitbox_halfsize*vertex); + aabb.grow(self.body.position+self.style.hitbox_halfsize*vertex); } aabb } @@ -945,7 +999,7 @@ impl crate::instruction::InstructionConsumer for PhysicsStat }, PhysicsInstruction::CollisionEnd(c) => { self.contacts.remove(&c);//remove contact before calling contact_constrain_acceleration - let mut a=self.gravity; + let mut a=self.style.gravity; self.contact_constrain_acceleration(&mut a); self.body.acceleration=a; //check ground @@ -961,8 +1015,8 @@ impl crate::instruction::InstructionConsumer for PhysicsStat let camera_mat=self.camera.simulate_move_rotation_y(self.mouse_interpolation.interpolated_position(self.time).x-self.mouse_interpolation.mouse0.x); let control_dir=camera_mat*get_control_dir(self.controls); let d=self.body.velocity.dot(control_dir); - if d for PhysicsStat self.body.velocity=glam::Vec3::ZERO; //manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))} self.contacts.clear(); - self.body.acceleration=self.gravity; + self.body.acceleration=self.style.gravity; self.walk.state=WalkEnum::Reached; self.grounded=false; refresh_walk_target=false; @@ -1020,7 +1074,7 @@ impl crate::instruction::InstructionConsumer for PhysicsStat if refresh_walk_target_velocity{ let camera_mat=self.camera.simulate_move_rotation_y(self.mouse_interpolation.interpolated_position(self.time).x-self.mouse_interpolation.mouse0.x); let control_dir=camera_mat*get_control_dir(self.controls); - self.walk.target_velocity=self.walkspeed*control_dir; + self.walk.target_velocity=self.style.walkspeed*control_dir; } self.refresh_walk_target(); } diff --git a/src/main.rs b/src/main.rs index 3ebc278..3d8152a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -503,22 +503,16 @@ impl framework::Example for GraphicsData { spawn_point:glam::vec3(0.0,50.0,0.0), body: body::Body::with_pva(glam::vec3(0.0,50.0,0.0),glam::vec3(0.0,0.0,0.0),glam::vec3(0.0,-100.0,0.0)), time: 0, - tick: 0, - strafe_tick_num: 100,//100t - strafe_tick_den: 1_000_000_000, - gravity: glam::vec3(0.0,-100.0,0.0), - friction: 1.2, - walk_accel: 90.0, - mv: 2.7, + style:body::StyleModifiers::default(), grounded: false, - walkspeed: 18.0, contacts: std::collections::HashSet::new(), models: Vec::new(), walk: body::WalkState::new(), - hitbox_halfsize: glam::vec3(1.0,2.5,1.0), camera: body::Camera::from_offset(glam::vec3(0.0,4.5-2.5,0.0),(config.width as f32)/(config.height as f32)), mouse_interpolation: body::MouseInterpolationState::new(), controls: 0, + world:body::WorldState{}, + game:body::GameMechanicsState::default(), }; //load textures diff --git a/src/model.rs b/src/model.rs index 8dea948..2475587 100644 --- a/src/model.rs +++ b/src/model.rs @@ -65,6 +65,111 @@ pub struct IndexedModelInstances{ //object_index for spawns, triggers etc? pub spawn_point:glam::Vec3, } +//stage description referencing flattened ids is spooky, but the map loading is meant to be deterministic. +pub struct StageDescription{ + pub start:u32,//start=model_id + pub spawns:Vec,//spawns[spawn_id]=model_id + pub ordered_checkpoints:Vec,//ordered_checkpoints[checkpoint_id]=model_id + pub unordered_checkpoints:Vec,//unordered_checkpoints[checkpoint_id]=model_id +} + +//you have this effect while in contact +#[derive(Clone)] +pub struct ContactingSurf{} +#[derive(Clone)] +pub struct ContactingLadder{ + pub sticky:bool +} +//you have this effect while intersecting +#[derive(Clone)] +pub struct IntersectingWater{ + pub viscosity:i64, + pub density:i64, + pub current:glam::Vec3, +} +#[derive(Clone)] +pub struct IntersectingAccelerator{ + pub acceleration:glam::Vec3 +} +//All models can be given these attributes +#[derive(Clone)] +pub struct GameMechanicJumpLimit{ + pub count:u32, +} +#[derive(Clone)] +pub struct GameMechanicBooster{ + pub velocity:glam::Vec3, +} +#[derive(Clone)] +pub enum ZoneBehaviour{ + //Start is indexed + //Checkpoints are indexed + Finish, + Anitcheat, +} +#[derive(Clone)] +pub struct GameMechanicZone{ + pub mode_id:u32, + pub behaviour:ZoneBehaviour, +} +// enum TrapCondition{ +// FasterThan(i64), +// SlowerThan(i64), +// InRange(i64,i64), +// OutsideRange(i64,i64), +// } +#[derive(Clone)] +pub enum StageElementBehaviour{ + //Spawn,//The behaviour of stepping on a spawn setting the spawnid + SpawnAt, + Trigger, + Teleport, + Platform, + //Speedtrap(TrapCondition),//Acts as a trigger with a speed condition +} +#[derive(Clone)] +pub struct GameMechanicStageElement{ + pub mode_id:u32, + pub stage_id:u32,//which spawn to send to + pub force:bool,//allow setting to lower spawn id i.e. 7->3 + pub behaviour:StageElementBehaviour +} +#[derive(Clone)] +pub struct GameMechanicWormhole{//(position,angles)*=origin.transform.inverse()*destination.transform + pub model_id:u32, +} +#[derive(Default,Clone)] +pub struct GameMechanicAttributes{ + pub jump_limit:Option, + pub booster:Option, + pub zone:Option, + pub stage_element:Option, + pub wormhole:Option,//stage_element and wormhole are in conflict +} +#[derive(Default,Clone)] +pub struct ContactingAttributes{ + pub elasticity:Option,//[1/2^32,1] 0=None (elasticity+1)/2^32 + //friction? + pub surf:Option, + pub ladder:Option, +} +#[derive(Default,Clone)] +pub struct IntersectingAttributes{ + pub water:Option, + pub accelerator:Option, +} +//Spawn(u32) NO! spawns are indexed in the map header instead of marked with attibutes +pub enum CollisionAttributes{ + Decoration,//visual only + Contact{//track whether you are contacting the object + contacting:ContactingAttributes, + general:GameMechanicAttributes, + }, + Intersect{//track whether you are intersecting the object + intersecting:IntersectingAttributes, + general:GameMechanicAttributes, + }, +} pub fn generate_indexed_model_list_from_obj(data:obj::ObjData,color:[f32;4]) -> Vec{ let mut unique_vertex_index = std::collections::HashMap::::new();