Skip to content

Instantly share code, notes, and snippets.

@46bit
Created October 4, 2020 21:17
Show Gist options
  • Save 46bit/aca9571c67c553c7223c1f9f1c61d879 to your computer and use it in GitHub Desktop.
Save 46bit/aca9571c67c553c7223c1f9f1c61d879 to your computer and use it in GitHub Desktop.
use std::mem;
use rand::prelude::*;
#[derive(Copy, Clone, Debug, Default)]
pub struct Vector {
pub x: f32,
pub y: f32,
}
impl Vector {
pub fn new(x: f32, y: f32) -> Vector {
Vector { x, y }
}
pub fn from_magnitude_and_direction(magnitude: f32, direction: f32) -> Vector {
let x = magnitude * direction.sin();
let y = magnitude * direction.cos();
Vector { x, y }
}
pub fn random(world_size: usize) -> Vector {
let x = random::<f32>() * world_size as f32;
let y = random::<f32>() * world_size as f32;
Vector{ x, y }
}
}
#[derive(Clone, Debug)]
pub struct MovementComponent {
pub entity_limit: usize,
pub current: Vec<MovementEntityData>,
pub next: Vec<MovementEntityData>,
}
impl MovementComponent {
pub fn new(entity_limit: usize) -> MovementComponent {
MovementComponent {
entity_limit,
current: vec![MovementEntityData::default(); entity_limit],
next: vec![MovementEntityData::default(); entity_limit],
}
}
pub fn update<'a, I: Iterator<Item = &'a usize>>(&mut self, active_entity_ids: I) {
for entity_id in active_entity_ids {
let movement = Vector::from_magnitude_and_direction(
self.next[*entity_id].velocity,
self.next[*entity_id].direction,
);
let previous_position = self.current[*entity_id].position;
let new_position = Vector{
x: previous_position.x + movement.x,
y: previous_position.y + movement.y,
};
self.next[*entity_id].position = new_position;
}
}
pub fn switch_to_next_data(&mut self) {
mem::swap(&mut self.next, &mut self.current);
}
}
#[derive(Clone, Debug, Default)]
pub struct MovementEntityData {
position: Vector,
velocity: f32,
direction: f32,
}
fn main() {
let world_size = 1000;
let entity_limit = 1000;
let mut active_entity_ids: Vec<usize> = vec![];
let mut unused_entity_ids: Vec<usize> = (0..1000).into_iter().collect();
let mut movement = MovementComponent::new(entity_limit);
for f in 0..10000 {
if f % 100 == 0 {
let new_entity_id = unused_entity_ids.pop().expect("exceeding entity limit");
active_entity_ids.push(new_entity_id);
movement.current[new_entity_id].position = Vector::random(world_size);
movement.current[new_entity_id].velocity = 0.0;
movement.current[new_entity_id].direction = random();
println!("{} created at {:?}", new_entity_id, movement.current[new_entity_id].position);
}
// Have all entities move towards (0, 0)
for entity_id in &active_entity_ids {
let position = movement.current[*entity_id].position;
let dx = -position.x;
let dy = -position.y;
movement.next[*entity_id].velocity = 0.1;
movement.next[*entity_id].direction = dx.atan2(dy);
}
movement.update(active_entity_ids.iter());
// Kill off entities that reach (0, 0)
let mut remove_entity_id_indexes = vec![];
for (i, entity_id) in active_entity_ids.iter().enumerate() {
if movement.next[*entity_id].position.x.abs() < 0.5
&& movement.next[*entity_id].position.y.abs() < 0.5
{
println!("{} reached (0, 0)", entity_id);
remove_entity_id_indexes.push(i);
}
}
for i in remove_entity_id_indexes {
active_entity_ids.remove(i);
}
movement.switch_to_next_data();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment