Im trying to write some code in rust but im stuck on the borrow checker. I have a vector of plant structs and want to run on every plant the update function that checks for collision.
This is programmed the way i did in python or c#. As far as i understand the problem is that i cant borrow game.plants[p]
and the also pass the &game.plants
as second borrow. I assume this is to prevent iteration error that happen is i change the vec<Plant>
while iterating over it. In c# this always results in a crash.
error[E0499]: cannot borrow `game.plants` as mutable more than once at a time
--> src/main.rs:143:50
|
143 | game.plants[p].update(&mut game.map, &mut game.plants, &game.plant_data);
| ----------- ------ ^^^^^^^^^^^^^^^^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
Here i call on every plant the update and pass the map(no problem), the vector i´m iterating over to let the function know where all the plants are and the plant data which is just data and makes no problem
for p in 0..game.plants.len() {
game.plants[p].update(&mut game.map, &game.plants, &game.plant_data);
}
fn update(&mut self, map: &Map, plants: &Vec<Plant>, plant_data: &PlantData){
if self.check_plant_plant_collision(&plants){
self.grow(&map, &plant_data);
}
}
How do i check collisions in rust? I need to iterate the vector of plants and the collision function needs to know where the other plants are.
fn check_plant_plant_collision(&self, plants: &Vec<Plant>) -> bool {
for other_plant in plants {
if self.position != other_plant.position {
let distance = self.position.distance_to(other_plant.position);
let combined_radius = self.radius + other_plant.radius;
if distance < combined_radius {
return true; // Collision detected
}
}
}
false // No collision detected
}
Am i thinking too much in objects? Here are the used Structs.
struct Game{
map: Map,
plants: Vec<Plant>,
plant_data: PlantData,
}
struct Plant {
position: Vector2,
radius: f32,
color: Color,
}
struct PlantData{
initial_size: f32,
max_size: f32,
growth_rate: f32,
}
It seems not reasonable to copy the vector of plants to satisfy the borrow checker. And to clone the plant, do the checks and then set the vector index to the copied plant seems a strange way to do this. What is the rust way of doing this? Is the way i structure my data ok or will i run into a lot more problems this way?