Open DomtronVox opened 4 years ago
Here is a quick example of something I want to do that needs Game::load to have a mutable window.
I'm adding in ECS, specifically Specs. My rendering system needs a value put into the ECS world object that the render function can draw to. That value should be initialised in the load function. I was going to use Batch. To create a batch you need an image and to create an image you need a gpu.
fn load(_window: &Window) -> Task<MyGame> {
let player = ... //same as above
let world = World::new();
//insert data into the world
let bg_img = Image::from_image(_window.gpu(),
DynamicImage::new_rgba8(_window.width(), _window.height()))
.expect("Error creating batch image.");
world.insert(Batch::new(bg_img));
Task::succeed(|| MyGame {
player,
world,
})
}
//....
fn draw(&mut self, frame: &mut Frame, _timer: &Timer) {
// Clear the current frame
frame.clear(Color::BLACK);
let mut screen_batch = self.world.write_resource::<Batch>();
screen_batch.clear();
//run render system which uses the batch object to draw to
//something like this to draw to screen.
screen_batch.draw(&mut frame.as_target());
}
EDIT
Ok, I seemed to have figured out how to do this. It still feels kinda hacky to me though and would be simplified by Game::load getting a mut window. This is my new Game::load function:
fn load(_window: &Window) -> Task<MyGame> {
(
Image::load("assets/sara-atlas.png"),
Task::using_gpu(|gpu| {
Ok(Batch::new(
Image::from_colors(gpu, &[Color::BLACK])
.expect("Failed to creat batch image.")
))
})
).join()
.map(|(player_atlas, render_system_batch)| {
let player = SpriteSheet::new(player_atlas, 5, 5);
let mut world = World::new();
ecs::register_components(&mut world);
//insert data into the world
world.insert(render_system_batch);
MyGame { player, world }
})
}
Is this an abuse of the task system or more or less the intended use?
EDIT 2 I realize now I'm misusing Batch. I thought it was something to draw images to. I now realize it is for drawing the same image/image segment multiple times. However, I also cannot use Canvas for this as it needs a gpu for the as_target() and I cannot seem to get the gpu into my system. But this is getting off topic from the original ticket.
So this may be a dumb question as it is very similar to #130 (I copied the title and tweaked it slightly even).
I'm having some trouble understanding Tasks, so this may just be stemming from that. I have this code that does not work because Game::load receives an immutable window ref.
The issue is, I want to load this image now then pass it into the MyGame object at the end of the load function. But Task::run function needs gpu and the Window::gpu function wants a mutable Window which load doesn't get.
In #103 you said it is by design that Game::update doesn't get a mutable window because only game logic should happen there and you don't want it to be changing the window itself, but I assume the same doesn't apply to Game::load, or am I wrong?
This is likely me just being confused about Tasks. When do Tasks actually get run? From the looks of it, it seems whatever calls Game::load runs the task(s), but if I have 100 images to load and I'm only supposed to return a Task\<Game> from load how am I supposed to load all those images? Also, down the road I want to have an AssetDatabase struct that holds lookup tables for all loaded assets (sprite sheets, dialogue trees, etc). And I want to load those assets after the main menu when the player selects one of the campaigns to play. That means it won't be happening in Game::load. But I also don't want some 'if' statement stuck in my Game::draw function being checked every tick. Should it go in Game::interact? (i've yet to mess with interact and input so I'm not sure)
Finally, thanks for making and maintaining this project. It's been very nice to work with so far.