Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Zakarum
@omni-viral
Making them into entities is a waste
+ you still need a resource for collision detection (attempt to place X or O into occupied cell should fail)
which will hold almost all the data
So here is what you get
/// Resource
struct Board { cells: [[Option<Entity>; 3]; 3] }
#[derive(Component)]
struct X;
#[derive(Component)]
struct O;

impl System {
  fn run((input, board, xs, os): ...) {
    ...
  }
}
Looks awful but this is how tic tac toe game will look in ECS spirt
lowercase1024
@lowercase1024
Wow, I didn't realize tic tac toe was that bad for ECS :D
Ok then, thank you! I'll try and search for some ECS examples to get more into it.
Zakarum
@omni-viral
In any case you are encouraged to put "business"-logic in the systems
And only small pieces in the type's impls
As the rule of thumb if more than 1 system needs it - put it into type's impl or free function
But, for example, checking winning condition should be in WinningConditionSystem
Another system can read input events and place new Xs and Os
Surely, small systems that tied together can be merged into one, but two separate system illustrate ECS approach better
dmitsuki
@dmitsuki
Is it possible to iterate over all component types in a world? For normal functions the ecs system model works great, but I'm trying to make an inspector that exist outside of the purview of the ecs and needs to show data for all components an entity might implement. It happens before the ecs dispatcher actually runs, so I don't care about the mutability or anything of particular component stores, I just need a way to check if an entity has a certain component, and get the values from the components stored in world
Right now I'm thinking I might have to register component types with a macro and iterate over a list of strings, but I'd rather avoid that :P
Zakarum
@omni-viral
How you imagine that working? World stores components type erased, you need actual type to downcast storage value
Can you, for example, write signature for function that will "iterate over all component types in a world"?
dmitsuki
@dmitsuki
Can't you get a resource with try_fetch_internal or get_mut_raw? If so, you can have a function like "register_component_with_inspector" that takes the world its registering to, and also has a vec of typeID's, and save the type id for the type that you are adding, and then at runtime iterate over a list of those typeid's using try_fetch_internal or get_mut_raw, or am I misunderstanding somethign?
Zakarum
@omni-viral
Even if you get resource's typeids, you will only get Box<Any>
You still need an actual type
What you can do is to prepare a closure for each registered resource/storage
Which can downcast and do some predefined operations with it
dmitsuki
@dmitsuki
Do you mean something like having a map of closures, which take a type id as a key and return a closure that returns a type and cast teh Box<Any> to the type?
Zakarum
@omni-viral
I suggest map TypeId to FnMut(&mut Any)
i.e gives you closure that internally knows the type, casts and does what it needs to be done
It can't return downcasted type, cuz, you know, all those closures should have same signature
XBagon
@XBagon_gitlab
hey! does someone have any advice how I would efficiently get the amount of entities in a join and probably then cache and update it accordingly?
WaDelma
@WaDelma
I am not sure what you are asking. Can you give some simple example or more details?
XBagon
@XBagon_gitlab
hm, well I thought about trying to combine specs with some methods to "bulk simulate" find entities that have specific components and instead of doing something for each of them, do it for the amount of them instead and save the relative change to then be able to lazyily retrieve it when acting on a single entity for example. Though I'm not sure how feasible that is and how big the performance improvement really could be. especially when you have to save these things for 1000s of component combinations and also have to calculate changes for broader combinations, when having changes to more specific ones... maybe I got a bit carried away
Ghost
@ghost~5d4078b1d73408ce4fc75281
Hi! I'm trying to wrap my head around specs and specs-hierarchy. In specs is it possible to add a component to an existing entity? If so, how?
WaDelma
@WaDelma
@danaugrs_twitter You can use https://docs.rs/specs/0.15.0/specs/storage/struct.Storage.html#method.insert to add components to existing entities.
Ghost
@ghost~5d4078b1d73408ce4fc75281
Figured it out - thanks!
Is there any way to modify the order that entities/components are obtained from a .join() iterator? e.g. for z-ordering?
WaDelma
@WaDelma
@torkleyy Is there reason for not implementing Send for Dispatcher? I asked this in slide-rs/shred#147 but never got answer and now it's merged
David Komer
@dakom
Is specs suitable for wasm where there's no real multithreading (yet)?
Martin Jensen
@malynome
Hey everyone, sorry if this is a noob question(or if there is an example somewhere, although I couldnt find any), but how would I go about "comparing" entities to each other when running a system, i.e. pairwise iteration, for something like collision detection? If i also want to mutate in that system? Or is it better to separate collision detection and collision handling into 2 systems? - Thanks in advance if anyone is able to help!
Roman Holovin
@roman-holovin

Hi, I've been working on the movement system and got an issue:

impl<'a> System<'a> for DestinationMovement {
    type SystemData = (
        Entities<'a>,
        WriteStorage<'a, Position>,
        ReadStorage<'a, Speed>,
        ReadStorage<'a, Destination>,
        ReadExpect<'a, Timings>,
        ReadExpect<'a, Map>,
    );

    fn run(
        &mut self,
        (entities, mut positions, speeds, destinations, timings, map): Self::SystemData,
    ) {
                for (_entity, speed, destination, position) in
            (&entities, &speeds, &destinations, &mut positions).join()
        {
                let destination_position = positions.get(destination.0).cloned().unwrap();

                // rest of the code is irrelevant
        }
    }
}

Some entities have a destination, which is wrapper over Entity, and to calculate a path to destination I need to retrieve destination's position. Naturally, I also want to have own position of the current entity itself.

Issue is that iterator mutably borrows positions, so I cannot use it inside loop. For me it looks like a very common issue, so maybe there is known solution for this problem?

I could remove positions dependency from join and get both entity and destination position inside loop, but I don't like that it will relax component requirements for this system. Another potential solution I can think of, but haven't tried, is to collect all new positions into separate Vec and then assign them with another loop. I don't like performance implications of this approach and unsoundness of it.

Is there anything else I can do?

WaDelma
@WaDelma
@dakom Specs can be used in wasm if you disable parallel feature
David Komer
@dakom
yup! got it working :D
WaDelma
@WaDelma
@roman-holovin I think you can use mask method and get similar dependency for join, but without access to component and then get the positions. I am not sure how restrict* are supposed to be used actually. Maybe those could also be used?
WaDelma
@WaDelma
@malynome You can do join within join by using just Entities to get both entities, then compare them for inequality and then access storages. In our game I think we first did that, but now were doing simple sweep-and-prune by using flagged storage to maintain internal data structure.
David Komer
@dakom
looking at the Rendering example in the docs, for Piston, does "actual dispatching" mean to run a system that would then drain the ResizeEvents and modify the required components?
Yusuf Bera Ertan
@yusdacra_gitlab

Hello, i have a question about joining. How can i join a storage with an entity? Like this

(&mut world.write_storage::<Enemy>(), &enemy_entity).join()

enemy_entity is an specs::Entity. When i do that, compiler gives a trait bound error.

Or is there another way to get components of an entity if you know the entity already?
Yusuf Bera Ertan
@yusdacra_gitlab

Nvm, i just found it. The thing i was looking for was

world.write_storage::<Enemy>().entry(enemy_entity)

Sorry for not reading the docs.

Aaron DeVore
@adevore
Hey, I'm maintainer of the Rudy crate. At this point, I'm not really putting any development time into Rudy, so I don't think it will ever be faster than the built-in data structures. I was wonder about whether specs should remove its support.
For that matter, it's unclear as to whether Judy arrays (the data structure that Rudy aims to implement) are even any faster. They were designed a while ago, so modern CPU's might have different performance bottlenecks.
Aleksi Juvani
@aleksijuvani
is there any reason for insert in World to require Resources to have a 'static lifetime? it seems to me like this should be the lifetime of the World instead
Aleksi Juvani
@aleksijuvani
this is what i end up doing right now which is kinda gross
world.insert(unsafe { transmute::<&'_ DebugOverlay, &'static DebugOverlay>(surface.debug_overlay()) });