Reputation: 6702
I'm very new to Rust and I'm having trouble figuring out how to handle ownership (and lifetime?) in this case. I'm not new to programming and I'm actually re-implementing something that already works in JS (https://sheraff.github.io/boids/).
In this context, Universe
is basically a "simulation" environment containing many Entity
. On each universe.tick()
, each Entity
needs to know which other Entity
it can "see". For that, entity.update()
takes a list of Entity
as an argument.
As a result, I have this piece of script that I can't seem to find a good ownership structure for:
for mut entity in self.entities {
entity.update(&self.entities);
}
How would you go about it?
I could tell you what I have tried but it feels like I have tried everything I could think of, including reading the Rust book, and I've had all the possible error messages... Sorry.
PS: of course, in time, it's not the entire list of entities that would be passed in entity.update
but a filtered list.
Below is a general simplification of the code structure:
pub struct Entity {
pub point: Point,
vision: Cone,
angle: Angle
}
impl Entity {
pub fn update(&mut self, entities: &Vec<Entity>) {
// ...
}
}
pub struct Universe {
pub entities: Vec<Entity>
}
impl Universe {
pub fn new() -> Universe {
let mut entities: Vec<Entity> = vec![];
for _ in 1..200 {
let mut entity = Entity::new();
entities.push(entity);
}
Universe {
entities
}
}
pub fn tick(&self) {
for mut entity in self.entities {
entity.update(&self.entities);
}
}
}
Upvotes: 0
Views: 109
Reputation: 9746
If each entity needs to know about each entity, then it seems like it's not the entity that's responsible for the update. You should probably refactor from a method on the entity to a function that operates on all entities.
Iterating over the entities in a nested loop is a bit difficult. One solution would be to iterate over one copy of the array and allow the other loop to take a mutable reference.
pub fn update_entities(entities: &mut Vec<Entity>) {
for a in entities.clone() {
for mut entity in entities.iter_mut() {
if entity.id == a.id { // If you can compare them, otherwise use indexed for loop and compare indices.
continue;
}
// Do stuff.
}
}
}
The reason why you need to copy is because of the golden rule of Rust: you can have either one mutable reference or any number of immutable references. Nested for loops break this rule because you need one mutable reference and one immutable.
Upvotes: 1