This commit is contained in:
Quaternions 2024-02-01 00:04:07 -08:00
parent f38d990a54
commit fa97ab8c6d
6 changed files with 253 additions and 19 deletions

View File

@ -8,8 +8,9 @@ pub struct ContactingLadder{
#[derive(Clone,Hash,Eq,PartialEq)]
pub enum ContactingBehaviour{
Surf,
Cling,//usable as a zipline, or other weird and wonderful things
Ladder(ContactingLadder),
NoJump,
Cling,//usable as a zipline, or other weird and wonderful things
Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32
}
//you have this effect while intersecting

View File

@ -1,12 +1,23 @@
use std::collections::{HashSet,HashMap};
use crate::model::ModelId;
use crate::gameplay_style;
use crate::updatable::Updatable;
#[derive(Clone)]
pub struct StageElement{
stage:StageId,//which stage spawn to send to
force:bool,//allow setting to lower spawn id i.e. 7->3
behaviour:StageElementBehaviour
}
impl StageElement{
pub fn new(stage_id:u32,force:bool,behaviour:StageElementBehaviour)->Self{
Self{
stage:StageId(stage_id),
force,
behaviour,
}
}
}
#[derive(Clone,Hash,Eq,PartialEq)]
pub enum StageElementBehaviour{
@ -20,25 +31,63 @@ pub enum StageElementBehaviour{
Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both.
}
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
pub struct CheckpointId(usize);
#[derive(Clone,Hash,Eq,PartialEq)]
pub struct StageId(u32);
pub struct Stage{
spawn:ModelId,
//open world support lol
ordered_checkpoints_count:u32,
//other behaviour models of this stage can have
ordered_checkpoints:Vec<ModelId>,
ordered_checkpoints:HashMap<CheckpointId,ModelId>,
unordered_checkpoints:HashSet<ModelId>,
}
#[derive(Clone,Hash,Eq,PartialEq)]
pub enum ZoneBehaviour{
Finish,
Anitcheat,
#[derive(Default)]
pub struct StageUpdate{
//other behaviour models of this stage can have
ordered_checkpoints:HashMap<CheckpointId,ModelId>,
unordered_checkpoints:HashSet<ModelId>,
}
impl Updatable<&StageUpdate> for Stage{
fn insert(&mut self,update:&StageUpdate){
for (&checkpoint,&model) in &update.ordered_checkpoints{
self.ordered_checkpoints.insert(checkpoint,model);
}
for &checkpoint in &update.unordered_checkpoints{
self.unordered_checkpoints.insert(checkpoint);
}
}
fn remove(&mut self,update:&StageUpdate){
for (checkpoint,_) in &update.ordered_checkpoints{
self.ordered_checkpoints.remove(checkpoint);
}
for model in &update.unordered_checkpoints{
self.unordered_checkpoints.remove(model);
}
}
}
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
pub enum Zone{
Start,
Finish,
Anticheat,
}
#[derive(Clone,Hash,Eq,PartialEq)]
pub struct ModeId(u32);
impl ModeId{
pub const MAIN:Self=Self(0);
pub const BONUS:Self=Self(1);
pub const fn mode(mode_id:u32)->Self{
Self(mode_id)
}
}
pub struct Mode{
style:gameplay_style::StyleModifiers,
start:ModelId,
zones:HashMap<ModelId,ZoneBehaviour>,
stages:Vec<Stage>,
start:ModelId,//when you press reset you go here
zones:HashMap<ModelId,Zone>,
stages:Vec<Stage>,//when you load the map you go to stages[0].spawn
//mutually exlusive stage element behaviour
elements:HashMap<ModelId,StageElement>,
jump_limit:HashMap<ModelId,u32>,
@ -47,23 +96,25 @@ impl Mode{
pub fn get_spawn_model_id(&self,stage:StageId)->Option<ModelId>{
self.stages.get(stage.0 as usize).map(|s|s.spawn)
}
//TODO: put this in the SNF
pub fn denormalize_data(&mut self){
//expand and index normalized data
self.zones.insert(self.start,Zone::Start);
for (stage_id,stage) in self.stages.iter().enumerate(){
self.elements.insert(stage.spawn,StageElement{
stage:StageId(stage_id as u32),
force:false,
behaviour:StageElementBehaviour::SpawnAt,
});
for &model_id in &stage.ordered_checkpoints{
self.elements.insert(model_id,StageElement{
for (_,&model) in &stage.ordered_checkpoints{
self.elements.insert(model,StageElement{
stage:StageId(stage_id as u32),
force:false,
behaviour:StageElementBehaviour::Checkpoint,
});
}
for &model_id in &stage.unordered_checkpoints{
self.elements.insert(model_id,StageElement{
for &model in &stage.unordered_checkpoints{
self.elements.insert(model,StageElement{
stage:StageId(stage_id as u32),
force:false,
behaviour:StageElementBehaviour::Checkpoint,
@ -72,19 +123,102 @@ impl Mode{
}
}
}
//this would be nice as a macro
#[derive(Default)]
pub struct ModeUpdate{
zones:HashMap<ModelId,Zone>,
stages:HashMap<StageId,StageUpdate>,
//mutually exlusive stage element behaviour
elements:HashMap<ModelId,StageElement>,
jump_limit:HashMap<ModelId,u32>,
}
impl Updatable<&ModeUpdate> for Mode{
fn insert(&mut self,update:&ModeUpdate){
for (&model,&zone) in &update.zones{
self.zones.insert(model,zone);
}
for (stage,stage_update) in &update.stages{
if let Some(stage)=self.stages.get_mut(stage.0 as usize){
stage.insert(stage_update);
}
}
for (&model,stage_element) in &update.elements{
self.elements.insert(model,stage_element.clone());
}
for (&model,&limit) in &update.jump_limit{
self.jump_limit.insert(model,limit);
}
}
fn remove(&mut self,update:&ModeUpdate){
for (model,_) in &update.zones{
self.zones.remove(model);
}
for (stage,stage_update) in &update.stages{
if let Some(stage)=self.stages.get_mut(stage.0 as usize){
stage.remove(stage_update);
}
}
for (model,_) in &update.elements{
self.elements.remove(model);
}
for (model,_) in &update.jump_limit{
self.jump_limit.remove(model);
}
}
}
impl ModeUpdate{
pub fn zone(model_id:ModelId,zone:Zone)->Self{
let mut mu=Self::default();
mu.zones.insert(model_id,zone);
mu
}
pub fn stage(stage_id:StageId,stage_update:StageUpdate)->Self{
let mut mu=Self::default();
mu.stages.insert(stage_id,stage_update);
mu
}
pub fn element(model_id:ModelId,element:StageElement)->Self{
let mut mu=Self::default();
mu.elements.insert(model_id,element);
mu
}
pub fn jump_limit(model_id:ModelId,jump_limit:u32)->Self{
let mut mu=Self::default();
mu.jump_limit.insert(model_id,jump_limit);
mu
}
}
#[derive(Default)]
pub struct Modes{
modes:Vec<Mode>,
}
impl Modes{
pub fn clear(&mut self){
self.modes.clear();
pub fn new(modes:Vec<Mode>)->Self{
Self{
modes,
}
}
pub fn get_mode(&self,mode:ModeId)->Option<&Mode>{
self.modes.get(mode.0 as usize)
}
pub fn insert(&mut self,mode:Mode){
self.modes.push(mode);
}
pub struct ModesUpdate{
modes:HashMap<ModeId,ModeUpdate>,
}
impl Updatable<&ModesUpdate> for Modes{
fn insert(&mut self,update:&ModesUpdate){
for (mode,mode_update) in &update.modes{
if let Some(mode)=self.modes.get_mut(mode.0 as usize){
mode.insert(mode_update);
}
}
}
fn remove(&mut self,update:&ModesUpdate){
for (mode,mode_update) in &update.modes{
if let Some(mode)=self.modes.get_mut(mode.0 as usize){
mode.remove(mode_update);
}
}
}
}

View File

@ -1,8 +1,10 @@
pub mod bvh;
pub mod map;
pub mod aabb;
pub mod model;
pub mod zeroes;
pub mod integer;
pub mod updatable;
pub mod instruction;
pub mod gameplay_modes;
pub mod gameplay_style;

11
src/map.rs Normal file
View File

@ -0,0 +1,11 @@
use std::collections::HashMap;
use crate::model;
use crate::gameplay_modes;
//this is the current map data loaded in memory
pub struct Map{
modes:gameplay_modes::Modes,
models:model::Models,
//RenderPattern
textures:HashMap<u32,Vec<u8>>,
}

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use crate::integer::{Planar64Vec3,Planar64Affine3};
use crate::gameplay_attributes;
use crate::updatable::Updatable;
pub type TextureCoordinate=glam::Vec2;
pub type Color4=glam::Vec4;
@ -30,6 +32,8 @@ pub struct IndexedPhysicsGroup{
pub groups:Vec<GroupId>,
}
//This is a superset of PhysicsModel and GraphicsModel
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
pub struct IndexedModelId(u32);
pub struct IndexedModel{
pub unique_pos:Vec<Planar64Vec3>,//Unit32Vec3
pub unique_normal:Vec<Planar64Vec3>,//Unit32Vec3
@ -47,8 +51,28 @@ pub struct IndexedModel{
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
pub struct ModelId(u32);
pub struct Model{
pub model:ModelId,
pub model:IndexedModelId,
pub attributes:gameplay_attributes::CollisionAttributesId,
pub color:Color4,//transparency is in here
pub transform:Planar64Affine3,
}
pub struct Models{
indexed_models:HashMap<IndexedModelId,IndexedModel>,
models:HashMap<ModelId,Model>,
}
impl Updatable<Models> for Models{
fn insert(&mut self,update:Models){
self.indexed_models.extend(update.indexed_models);
self.models.extend(update.models);
}
fn remove(&mut self,update:Models){
for (indexed_model_id,_) in &update.indexed_models{
self.indexed_models.remove(indexed_model_id);
}
for (model_id,_) in &update.models{
self.models.remove(model_id);
}
todo!("stop cloning models for remove");
}
}

62
src/updatable.rs Normal file
View File

@ -0,0 +1,62 @@
pub trait Updatable<Updater>{
fn insert(&mut self,update:Updater);
fn remove(&mut self,update:Updater);
}
//what if do like this
//*
pub trait Updatable2<Updater>{
fn update(&mut self,update:Updater);
}
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
struct InnerId(u32);
#[derive(Clone)]
struct Inner{
id:InnerId,
enabled:bool,
}
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
struct OuterId(u32);
struct Outer{
id:OuterId,
inners:std::collections::HashMap<InnerId,Inner>,
}
enum Update<I,U>{
Insert(I),
Update(U),
Remove
}
struct InnerUpdate{
//#[updatable(Update)]
enabled:Option<bool>,
}
struct OuterUpdate{
//#[updatable(Insert,Update,Remove)]
inners:std::collections::HashMap<InnerId,Update<Inner,InnerUpdate>>,
//#[updatable(Update)]
//inners:std::collections::HashMap<InnerId,InnerUpdate>,
}
impl Updatable2<InnerUpdate> for Inner{
fn update(&mut self,update:InnerUpdate){
if let Some(enabled)=update.enabled{
self.enabled=enabled;
}
}
}
impl Updatable2<OuterUpdate> for Outer{
fn update(&mut self,update:OuterUpdate){
for (id,up) in update.inners{
match up{
Update::Insert(new_inner)=>self.inners.insert(id,new_inner),
Update::Update(inner_update)=>self.inners.get_mut(&id).map(|inner|{
let old=inner.clone();
inner.update(inner_update);
old
}),
Update::Remove=>self.inners.remove(&id),
};
}
}
}
//*/