Hello!
I'm building a 2D antfarm simulation on a grid. I have some ant sprites which move around and dig up dirt through an ant system. I also have a gravity system which causes dirt and ants to fall downward when they're above air.
I'm not sure if it's good practice, but I also have a "render" system. This is my attempt at separating model concerns from view concerns.
Both my ant system and my gravity system affect a Position component which is just an xy offset. Ants walk around on the surface and their Position's x-offset is updated. Ants/dirt fall from the sky and Position's y-offset is updated.
In both ant system and gravity system I am updating my model, the Position component, and have not reflected the changes visually by updating an associated Transform. I thought this would be a good role for my render system to fulfill.
My render system has this:
fn render_translation(
mut query: Query<
(
&mut Transform,
&Position,
),
Changed<Position>,
>,
) {
for (mut transform, &position) in query.iter_mut() {
transform.translation.x = position.x as f32;
transform.translation.y = -position.y as f32;
}
}
Here, I watch for changes to position and reflect the change in the UI.
A problem I experience with this approach is:
- Ant falls from the sky and is one unit above the ground both in the view and model.
- Gravity system runs such that ant model is now on the ground.
- Ant system runs such that ant takes a step forward.
- Render system runs and reflects the change visually.
This results in a visual glitch where the ant is never shown landing on the ground without having taken a step because the gravity system runs and the ant system runs before visuals are updated.
I'm curious what approaches I should consider to fix this issue. The most obvious solution is to abandon my render system and instead have any system that updates position also update transform. I was hesitant to take this approach because I'm trying to "think ECS" and it seemed good to have a generic query that handles rendering for all Position components instead of duplicating that effort inside of each system that updates position.
How am I thinking about this incorrectly? Thanks!