#How to efficiently implement ticking tiles?

23 messages · Page 1 of 1 (latest)

quasi ferry
#

I'm working on a RimWorld-like game while also learning Rust, Bevy, and trying out ECS.

I'm trying to decide how to implement tiles.
I see two approaches -

Make each tile an entity and update only the ones that are With<Ticking>, and add relations (Planet -> Grid -> TileLayer -> Tile).

Make the grid a Vec<Vec<Tile>> and handle it the traditional way.

The first one seems to be the Bevy way of handling this, but I'm new to this and am cautious about performance.

The second one seems like it wouldn't allow Bevy to parallelize systems as easily, and would push that responsibility onto me. It would also separate the Tile from the ECS structure, making it just a value I can't add components to, unlike an entity.

What do you think guys?

runic totem
#

Make each tile an entity
this is the standard approach used by tilemap libraries

quasi ferry
#

Oh, so TileMap's aren't just 2d vecs of structs? I was cautious of them because I believed so, it seems I've been mistaken!

quasi ferry
# runic totem > Make each tile an entity this is the standard approach used by tilemap librari...

Thanks! Also, I know my next question is a bit off-topic from the original post, but:

How would you approach making a generic Animal (covering both living creatures and robots - using 'Animal' in the sense of 'Animate')?

I'm thinking of a tree-like structure of entities representing a Body, which consists of Limbs and Organs. These would be made of components like a LiquidContainer (for blood, goo, or oil).

Now I'm struggling with implementing Effects.
Imagine this situation: Stuart is shot twice, and the RNG determines that both shots hit his thigh. These are two separate wounds that should each cause his thigh's LiquidContainer to bleed 10 units of blood per tick. However, I can't assign two Bleeding components to the same LiquidContainer due to Bevy's ECS rules. I also don't want a single bleeding effect that just gets updated when Stuart is shot again—these are separate events. Two wounds should require two separate bandages and could heal at different rates.

My first idea was to make an Effects component holding a Vec<Effect>, which would sum up damage-over-time, buf and debuf effects in a deterministic order and apply them. Including innate values, like Stuart's Thighs initial blood volume that he got when he was spawned in. Is this the way to go?

runic totem
#

one option would be to use separate entities and relations to model those
so each Bleeding component is on its own Entity, but they each "point" to the same entity that also has a LiquidContainer component

quasi ferry
#

Hm, actually, I've never thought of doing that lol, my brain is still struggling with ECS's plasticity, thanks for the idea

runic totem
#

you might make something like ```rs
#[derive(Component)]
#[relationship(relation_target = AfflictedBy)]
struct Affliction {
to: Entity
}

#[derive(Component)]
#[relationship_target(relationship = Affliction)]
struct AfflictedBy(Vec<Entity>);

#[derive(Component)]
struct Bleeding {
rate: f32
}
// and other statuses

#

then you could ```rs
commands.spawn((
Affliction { to: player_part_entity },
Bleeding { rate: 10. }
));

quasi ferry
#

And then I could do something like a GroupEffect (Gunshot wound) as a single entity that describes a bunch of effects, like bruising and bleeding that occured after a single event! Wow thats cool

runic totem
#

unless you want each effect to have its own Affliction component

#

a dummy component with a hook that despawns itself and spawns an Affliction for each needed effect is another way
or a custom command type

quasi ferry
#

and then in a diff system Affliction With<AnotherEffect>

#

Or smth like that

runic totem
#

but you might also have a timer for how long the Affliction lasts
that would be another component on the same Entity

#

putting both effects on the same entity would require them to have the same timer in that case

quasi ferry
#

Hm. I could measure time in ticks, and tick down some Bleeding's value, then remove that component or set rate to 0

#

But that sounds like something that must be a sep component

#

as it's used across multiple effects

#

I guess i would need yet another entity to describe what i wanted, like an EffectGroup { Vec<Entity> } ig

#

And since it is almost never updated it should become a perofrmance issue

#

Thanks!