Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Ian Sly
@uzkbwza
Cool, I'd like to see how you've implemented it, if you don't mind. I've gone through a couple different implementations but I'm not happy with anything I've written so far.
FlorentKl
@FlorentKl
Hi. Maybe i am an idiot, but i'm pretty new to Rust, and can't figure out how to import the saveload module. I use "use specs::saveload::{SimpleMarker, SimpleMarkerAllocator};", but keep getting an error : "could not find saveload in specs" or "no saveload in the root" for "use specs::saveload;". In Cargo.toml, i have 0.15.1 version. Thanks all.
WaDelma
@WaDelma
You need to enable serde feature in your Cargo.toml. Here is the documentation on how to do it.
FlorentKl
@FlorentKl
Thanks, it work now.
Bastczuak
@Bastczuak
Hello guys, I am new here and I have a general questions regarding specs and maps. This stuff is all new for me and I don't really know if it is a good approach to use ECS for map rendering? For example right now I use a "map" as a component. This map contains lines, points and so on. For each map I then create entities which represents a "level". And one system which is responsible for handling the rendering in the end? Why I am asking? Because technically a map is not a entity. Right, or do I miss something?
Troels Jessen
@Sheepyhead
Hey friends, this is somewhat of a long shot, but I'm at my wit's end with specs. How do you folks manage to draw anything inside a system? I stumbled upon the ability to define thread local systems, but the system isn't the problem, the problem is the resource. To draw something generally you need a graphics context, and generally that context absolutely cannot be shared between threads, and I cannot seem to find a way to add a resource like that. All I want is to use a Draw system to render my entities based on their Position and Sprite components, but at this point I have no idea how to do this. Right now I'm using ggez as my game engine, but I had the same problem when I was using Piston.
I'm currently looking through the docs for Amethyst, since none of the specs examples seem to have any actual rendering happening, but I figured it wouldn't hurt to ask here.
What I was expecting to work was to insert the resource using world.insert or a variant that works with thread local systems, but I can't seem to find anything in the docs that appear to be what I need to pass a graphics context into a rendering system. Is it simply that I shouldn't be using systems to render things?
Troels Jessen
@Sheepyhead
No that can't be it, the chapter on rendering explicitly has a system named RenderSys, which sounds like it should be a rendering system. Unfortunately it neglects to display how such a system would actually do any rendering https://specs.amethyst.rs/docs/tutorials/10_rendering.html
Seems the only mention of this RenderSys in the repo is that one markdown file. I might be missing something obvious, but this seems like a major oversight to me. In any case I would really love some help with this, as it's currently blocking my entire game project from proceeding :(
Dmitriy
@dpogretskiy
RenderSys is a part of rendering bundle, you should probably dig the sources a bit to understand what's up with it, cause the one is used in amethyst tutorials is aready built in.
https://docs.rs/crate/amethyst_rendy/0.3.0/source/src/bundle.rs
2 interesting bits here are builder.add_barrier() and builder.add_thread_local()
Dmitriy
@dpogretskiy
from my understanding barrier suggests that all other systems should be finished by the time you actually run what comes next, and probably some explicit synchronization steps, to not get race conditions on resources and such, and add_thread_local would probably just run the system on current thread
Dmitriy
@dpogretskiy
so direct solution would be to slap your own bundle together and put the level rendering system before the actual rendering system, that doesn't seem too complicated
or something more hacky, creating a system that makes level entity from resource before the rendering, or if your level is not terribly dynamic, just leave it as an entity forever
Troels Jessen
@Sheepyhead
@dpogretskiy If you're talking to me, I'm looking through those docs right now, it's pretty complicated but I'll put in some more reading when I have time. In any case I feel like there should be at least somewhat of a documented approach to having a system that can render things based on a sprite component, for instance. I'm new to specs, but I can't seem to find out how you would achieve rendering while the context cannot be threaded, and as such needs to be given into a system to run the system in some sequential manner.
WaDelma
@WaDelma
@Sheepyhead In our game the rendering system own a hashmap that has as it's values the actual graphical resource and everybody else just refers to them by strings. Not sure if this helps your case
@Bastczuak I am not sure what is your map. Is it like minimap or overworld or some static map or?
Troels Jessen
@Sheepyhead
@WaDelma My problem isn't storing the Sprite/Texture/whatever, my problem is rendering it. To render it, at least using the engine I'm using (ggez), it requires a graphics context which I cannot pass in as a resource because of threading limitations on the context. To my knowledge most rendering systems has such a context at some level of the engine, so I'm just not sure how others manage to render anything in a specs system
Dmitriy
@dpogretskiy
oh, so you're using ggez with specs, that's what i did too
vblanco20-1
@vblanco20-1
@Sheepyhead i solved that problem on my own with some evil hackery
struct ContextWrapper{
pub ctx: *mut Context
}

impl ContextWrapper{
    fn get(&self) -> &mut Context
    {
        unsafe{
            &mut *self.ctx
        }
    }
}
unsafe impl Sync for ContextWrapper{}
unsafe impl Send for ContextWrapper{}
Dmitriy
@dpogretskiy
and my demo is a bit messy, but there's your answer, https://github.com/dpogretskiy/specs-ggez-showcase/blob/master/src/game.rs#L138
you just run the rendering system outside of specs dispatcher and can put whatever you want into it
also you run in whatever thread you want and it works
Troels Jessen
@Sheepyhead
Oh my god, thank you so much Dmitriy, I can't believe I didn't think of that! I'm gonna go implement that right now!
vblanco20-1
@vblanco20-1
in mine, i run it as a specs system
not outside of it
Troels Jessen
@Sheepyhead
I actually prefer it the other way around, it also saves me from having to separate my draw system so I can run it in the render loop
Dmitriy presented precisely what I was trying to do, but I appreciate your input too!
Troels Jessen
@Sheepyhead
Hmm seems like there are some things I can't really understand out of your code @dpogretskiy , I'm unsure where the run_now function on RenderingSystem comes from, and I'm not sure what World.res is supposed to be
Troels Jessen
@Sheepyhead
Also I've failed harshly in trying to get the project to compile so I can't use RLS to see where it's coming from either :sweat_smile:
Dmitriy
@dpogretskiy
It's a pretty dated code, that used old versions of specs and ggez
that's probably what you want, it runs the system, but now it uses &mut World instead of res whatever it was at the date apparently
Troels Jessen
@Sheepyhead
I actually found that trait but for some reason RLS was still complaining. I got it to work now though! Thank you so much!! :D
Mark
@markvandieren

Hey, does anyone have experience using the saveload module with bincode? First issue: the Serializer struct that needs to be passed to the serialize function is private. I bypassed that by cloning the repository and making it public, but that's not really a nice solution.

Second issue, I get this error: Bincode can only encode sequences and maps that have a knowable size ahead of time

So bincode can't be used with saveload?

Jochen Görtler
@grtlr
Hi everybody! I'm new to specs and have a question: If I create entities with create_iter, is it guaranteed that these entities will be joined later on in the same order as they are created? Thank you very much!
Dmitriy
@dpogretskiy
absolutely no @grtlr :)
altho you can just put them in the sorted set as you go through, and then do your thing, not perfect, but if it will cause issues you'd probably find a 'less naive' solution
Jochen Görtler
@grtlr
@dpogretskiy Thank you for the quick reply, I'll go ahead and do it that way!
Arnold Loubriat
@DataTriny

Hello there, I'm coming back to creating a text-based game using Specs and I can't figure out a good way to handle input. In my mind, a command (like attack) is composed of selectors (CreatureSelector and WeaponSelector in this case) that are responsible for associating a slice of input to something in the world. Those selectors must run in a given order defined by each command, and they all have very different needs in terms of storage reading. The most practical way I've found is to create custom system traits and my own dispatcher like so:

pub trait Command<'a> {
    type Data: SystemData<'a>;
    fn get_selectors(&self) -> &[Box<dyn ExecuteSelector>];
    fn run(&self, args: Vec<Selectable>, game: &Game, data: Self::Data) -> CommandResult;
    fn setup(&self, world: &mut World);
}
pub trait ExecuteCommand<'a> {
    fn get_selectors(&self) -> &[Box<Selector>];
    fn run(&self, args: Vec<Selectable>, game: &Game, world: &'a World) -> CommandResult;
    fn setup(&self, world: &mut World);
}
impl<'a, T> ExecuteCommand<'a> for T
    where T: Command<'a>
{ ... }
pub trait Selector<'a> {
    type Data: SystemData<'a>;
    fn parse(&self, input: &str, game: &Game, data: Self::Data) -> ParsingResult<(usize, Selectable)>;
    fn setup(&self, res: &mut World);
}
pub trait ExecuteSelector<'a> { ... }
impl<'a, T> ExecuteSelector<'a> for T
    where T: Selector<'a>
{ ... }
pub struct CommandDispatcher<'a> {
    commands: Vec<Box<dyn ExecuteCommand<'a>>>
}
impl<'a> CommandDispatcher<'a> {
    pub fn dispatch(&self, input: &str, game: &Game<'a>, world: &'a mut World) -> Result<(), DispatchingError> {
        // Find which command to trigger based on the start of the input and strip the matching part.
        // For each command's selector, run it and remove the matching part of the input. Add the results to a list of arguments.
        // Run the command and pass it the list of arguments.
    }
}

Of course this is a simplified version. But I think that this defeats the purpose of an ECS...
Does anyone have an idea on how to put it differently? Many thanks in advance!

Bastczuak
@Bastczuak
Hello people! Can I access joined storages by index? For example like this:
    let position_storage = self.ecs.read_storage::<Position>();
    let rotation_storage = self.ecs.read_storage::<Rotation>();
    let something = (&position_storage, &rotation_storage).join().collect()[0];
Oscar Aguinagalde
@OAguinagalde

Hey people, I'm following the specs book, and I'm finding plenty of problems. Even if I just copy and paste the examples to follow, not even the first ones compile. Most of them seem to be related to how the modules are imported, but there are plenty of things I don't get.
For instance, while doing this

use specs::{Component, ReadStorage, System, VecStorage, World, RunNow, WorldExt, Join};

// a bunch of code...

let entity = world
        .create_entity()
        .with(Position { x: 4.0, y: 7.0 }) // ERROR: no method named `with` found for type `specs::world::EntityBuilder<'_>`
        .build();

I encounter that problem.
Which apparently gets fixed when "using" specs::world::* (not World)
I also needed to add WorldExt to the mix, because World::new() was not recognized. That is also not in the example of the book.

Also, even after fixing these 2 problems, I still cant compile:

let mut hello_world = HelloWorld;
hello_world.run_now(&world.res);
// ERROR: no field `res` on type `shred::world::World`

Here is the system pretty much the same as it is in the book:

struct HelloWorld;

impl<'a> System<'a> for HelloWorld {
    type SystemData = ReadStorage<'a, Position>;

    fn run(&mut self, position: Self::SystemData) {

        for position in position.join() {
            println!("Hello, {:?}", &position);
        }
    }
}

Not sure how I should make the "use" statements or what am I doing wrong. In any case, the book, while very easy to follow, it's examples straight up don't work, so that's something to keep in mind

Jean Manguy
@jeanmanguy
Hello there, is it possible to add and/or remove components to an entity in a system to later it's functioning in an ulterior system? What's the proper way to achieve something similar is it's not possible?
Christopher Sabater Cordero
@cs-cordero

Is there a way to specify a generic lifetime on a system?

struct Foo<'a> {
    something: Bar<'a>
}

impl<'a> System<'a> for Foo<'a> {
    ...
}

I get errors when I try to move the system into a DispatcherBuilder

Matt H
@cobalthex
is there a way to remove a component from an entity while iterating? or remove a component from all entities matched in a join iter
Oscar
@tcmal

are there any examples of using a generic resource in a system? for example:

trait IsALevelThing: Send + Sync {}
struct LevelThing;

struct Renderer<T> {
    _a: PhantomData<T>,
}

impl<'a, T: 'a + IsALevelThing> System<'a> for Renderer<T> {
    type SystemData = Read<'a, T, PanicHandler>;

    fn run(&mut self, data: Self::SystemData) {
        // TODO
    }
}

seems like it should work but it gives the parameter typeTmay not live long enough, consider adding an explicit lifetime bound T: 'static. not sure why this is since from what i understand it just needs to live for 'a