Created
April 9, 2014 20:13
-
-
Save SiegeLord/10309720 to your computer and use it in GitHub Desktop.
Component system 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![feature(macro_rules)] | |
| struct Location | |
| { | |
| x: f32, | |
| y: f32 | |
| } | |
| struct Velocity | |
| { | |
| vx: f32, | |
| vy: f32 | |
| } | |
| struct Entity | |
| { | |
| velocity: Option<~Velocity>, | |
| location: Option<~Location> | |
| } | |
| struct EntityRef<'l> | |
| { | |
| velocity: Option<&'l mut Velocity>, | |
| location: Option<&'l mut Location> | |
| } | |
| impl Entity | |
| { | |
| pub fn as_ref<'l>(&'l mut self) -> EntityRef<'l> | |
| { | |
| let Entity{ ref mut velocity, ref mut location } = *self; | |
| EntityRef | |
| { | |
| velocity: velocity.as_mut().map(|v| &mut **v), | |
| location: location.as_mut().map(|l| &mut **l), | |
| } | |
| } | |
| } | |
| struct PhysicsSystem | |
| { | |
| entities: Vec<uint> | |
| } | |
| impl PhysicsSystem | |
| { | |
| pub fn new() -> PhysicsSystem | |
| { | |
| PhysicsSystem{ entities: Vec::new() } | |
| } | |
| pub fn remove_entity(&mut self, entity_idx: uint) | |
| { | |
| let cur_pos = self.entities.as_slice().position_elem(&entity_idx); | |
| for &pos in cur_pos.iter() | |
| { | |
| println!("Removed {}", entity_idx); | |
| self.entities.swap_remove(pos); | |
| } | |
| } | |
| pub fn component_changed_event(&mut self, entity: &Entity, entity_idx: uint) | |
| { | |
| let cur_pos = self.entities.as_slice().position_elem(&entity_idx); | |
| if entity.location.is_some() && entity.velocity.is_some() | |
| { | |
| if cur_pos.is_none() | |
| { | |
| println!("Added {}", entity_idx); | |
| self.entities.push(entity_idx) | |
| } | |
| } | |
| else | |
| { | |
| for &pos in cur_pos.iter() | |
| { | |
| println!("Removed {}", entity_idx); | |
| self.entities.swap_remove(pos); | |
| } | |
| } | |
| } | |
| fn update(&self, entities: &mut [Entity]) | |
| { | |
| for &entity_idx in self.entities.iter() | |
| { | |
| match entities[entity_idx].as_ref() | |
| { | |
| EntityRef{ velocity: Some(ref mut vel), location: Some(ref mut loc) } => | |
| { | |
| loc.x += vel.vx; | |
| loc.y += vel.vy; | |
| println!("{} {} {}", entity_idx, loc.x, loc.y); | |
| }, | |
| _ => unreachable!() | |
| } | |
| } | |
| } | |
| } | |
| struct World | |
| { | |
| entities: Vec<Entity>, | |
| physics: PhysicsSystem, | |
| velocity_changes: Vec<(uint, Option<~Velocity>)>, | |
| location_changes: Vec<(uint, Option<~Location>)>, | |
| entity_additions: Vec<uint>, | |
| entity_removals: Vec<uint>, | |
| } | |
| impl World | |
| { | |
| pub fn new() -> World | |
| { | |
| World | |
| { | |
| entities: Vec::new(), | |
| physics: PhysicsSystem::new(), | |
| velocity_changes: Vec::new(), | |
| location_changes: Vec::new(), | |
| entity_additions: Vec::new(), | |
| entity_removals: Vec::new(), | |
| } | |
| } | |
| pub fn add_entity(&mut self, e: Entity) -> uint | |
| { | |
| // TODO: freelist | |
| self.entities.push(e); | |
| let idx = self.entities.len() - 1; | |
| self.entity_additions.push(idx); | |
| idx | |
| } | |
| pub fn remove_entity(&mut self, idx: uint) | |
| { | |
| // TODO: freelist | |
| self.entity_removals.push(idx); | |
| } | |
| pub fn set_velocity(&mut self, idx: uint, comp: Option<~Velocity>) | |
| { | |
| self.velocity_changes.push((idx, comp)); | |
| } | |
| pub fn set_location(&mut self, idx: uint, comp: Option<~Location>) | |
| { | |
| self.location_changes.push((idx, comp)); | |
| } | |
| pub fn update(&mut self) | |
| { | |
| println!("Update"); | |
| macro_rules! comp_change | |
| { | |
| ($e: expr) => | |
| { | |
| self.physics.component_changed_event(&*($e), idx); | |
| } | |
| } | |
| macro_rules! remove_entity | |
| { | |
| ($idx: expr) => | |
| { | |
| self.physics.remove_entity($idx); | |
| } | |
| } | |
| macro_rules! handle_comp_changes | |
| { | |
| ($changes: ident, $comp_name: ident) => | |
| { | |
| { | |
| for &(idx, ref mut comp) in self.$changes.mut_iter() | |
| { | |
| let e = &mut self.entities.as_mut_slice()[idx]; | |
| e.$comp_name = comp.take(); | |
| comp_change!(e); | |
| } | |
| self.$changes.clear(); | |
| } | |
| } | |
| } | |
| handle_comp_changes!(velocity_changes, velocity); | |
| handle_comp_changes!(location_changes, location); | |
| for &idx in self.entity_additions.mut_iter() | |
| { | |
| comp_change!(&self.entities.as_slice()[idx]); | |
| } | |
| self.entity_additions.clear(); | |
| for &idx in self.entity_removals.mut_iter() | |
| { | |
| remove_entity!(idx); | |
| } | |
| self.entity_removals.clear(); | |
| self.physics.update(self.entities.as_mut_slice()); | |
| } | |
| } | |
| fn main() | |
| { | |
| let mut world = World::new(); | |
| let e = world.add_entity(Entity{ location: None, velocity: None }); | |
| world.update(); | |
| world.set_location(e, Some(~Location{ x: 10.0, y: 10.0 })); | |
| world.set_velocity(e, Some(~Velocity{ vx: -1.0, vy: -1.0 })); | |
| world.update(); | |
| world.set_velocity(e, None); | |
| world.update(); | |
| world.set_velocity(e, Some(~Velocity{ vx: -1.0, vy: -1.0 })); | |
| world.remove_entity(e); | |
| world.update(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment