Skip to content

Instantly share code, notes, and snippets.

@SiegeLord
Created April 9, 2014 20:13
Show Gist options
  • Select an option

  • Save SiegeLord/10309720 to your computer and use it in GitHub Desktop.

Select an option

Save SiegeLord/10309720 to your computer and use it in GitHub Desktop.
Component system 2
#![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