Closed beetrootpaul closed 1 year ago
Hello! I'm also excited to get bevy 0.10 support up and running. I've just created a WIP PR where I've got it working. See #16.
However I still want to make some improvements to usages of system sets and schedules before releasing a new version of this crate. I also want to take this opportunity to support multiple windows now that windows are entities in bevy 0.10, this will likely change the public API in a major way.
However I still want to make some improvements to usages of system sets and schedules before releasing a new version of this crate
I ended up in a state where I wouldn't use bevy_pixels
in the end, because of to which schedules do I add my systems. I mean: I want my systems run on a fixed FPS (like old games, with movement based on constant increments of time). Just in case you are planning to go into direction which would allow such solution:
I define only a custom "render" system set and place it after CoreSet::PostUpdate
: https://github.com/beetrootpaul/poc--bevy-pixels-web-game/blob/5a40f2773bc629dcb723ea944384ad428e526b45/src/pixel_canvas/plugin.rs#L33-L34
Then I put most of my systems not in a custom "draw" system set, but in CoreSchedule::FixedUpdate
: https://github.com/beetrootpaul/poc--bevy-pixels-web-game/blob/5a40f2773bc629dcb723ea944384ad428e526b45/src/game/mod.rs#L48-L72
I tried to create my own fixed timestep schedule within module which is my modification of bevy_pixels
(to imitate how would it look like as part of a library API), but I failed. Probably it's doable, but I didn't manage to put all puzzle pieces together. So, I ended up reusing built-in Bevy's CoreSchedule::FixedUpdate
and, sadly, chaining all systems together in that schedule (I failed to understand how to put any base system set to that schedule so I would be able to create a complex graph of systems there, with parallel systems instead of everything chained).
To be clear: if you do not plan to go such road nor add ability for a fixed timestamp solution in bevy_pixels
, then I am totally OK with that. I am just sharing my use case and am OK with having my own implementation of pixels
usage 🙂
I've just created a WIP PR where I've got it working.
I took a look and, just in case, want to hint the importance of "system sets" vs "base system sets". I made a mistake of using .in_set
and ended up having my systems added to both my desired system set and CoreSet::Update
, which made my app panic and run my systems in a wrong place of the whole game loop. Then I learnt about necessity to use "base system sets" (but still don't "feel" the topic). For more info please see this forum thread on Bevy Discord: https://discord.com/channels/691052431525675048/1083571454404214885/1083571454404214885
I would like bevy_pixels
to support all use cases of pixels
within bevy
, thus I want to support your usage of fixed update game logic. I imagine bevy_pixels
should be constantly rendering the pixel buffer to the window at display frame rate (eg. 60 fps) but maybe only if it detects changes since the previous frame. Game logic would be independent and can run on it's own schedule not necessarily linked to display frame rate where the pixel buffer is being updated from. If this is not possible or desirable, perhaps users of bevy_pixels
can be given the ability to tweak the schedule somehow.
I still need to read more on the changes in bevy 0.10 to understand all the possibilities.
Thanks for your advice and tips.
Hi @beetrootpaul, I've just released 0.9 with support for Bevy 0.10.
I've taken the opportunity to make big changes to the API. I've replaced PixelsResource
with a PixelsWrapper
component that lives on the window entity. I've also done some reading around system sets and I think I understand how they work. You're correct about the base sets. I've created PixelsSet
with three variants configured like this to map to the following base sets.
configure_sets((
PixelsSet::Update.in_base_set(CoreSet::Update),
PixelsSet::Draw.in_base_set(CoreSet::PostUpdate),
PixelsSet::Render.in_base_set(CoreSet::Last),
))
The idea is simulation logic would occur in PixelsSet::Update
while the buffer is written to in PixelsSet::Draw
. However if using CoreSchedule::FixedUpdate
systems for your logic, I imagine it would still work fine. I've not tried it myself though. Keen to see how you go.
@dtcristo thx for letting me know! 👍
The idea is simulation logic would occur in PixelsSet::Update while the buffer is written to in PixelsSet::Draw. However if using CoreSchedule::FixedUpdate systems for your logic, I imagine it would still work fine.
I think I would need to add both my drawing (buffer write) and rendering to FixedUpdate as well in order to maintain a fixed FPS look&feel of e.g. 30 FPS 🤔
Or, maybe it won't be visible so much in practice and having draw and render in the regular CoreSet
? I don't know.
I wonder if it would be possible to have a bevy_pixels
plugin defined in a way, that once can:
configure_sets
block exectuedPixelSet::Update
etc. to the user to add to their preferred system sets on their own.Maybe I will try to do such in my own custom implementation, just for exploratory reasons (in my next repo I intentionally split game into "base" and "game" packages, hoping to force on myself kind of engine vs game separation, with a single direction dependency, with pixels support in "base" and systems being added to its sets in "game")
Keen to see how you go.
This is how I did it in my most recent PoC: https://github.com/beetrootpaul/poc--bevy-pixels-web-game/blob/11111f5a4fe99243492838b20f25be9012a0f93a/src/game/mod.rs#L119-L173
My sets are defined as follows:
app.edit_schedule(CoreSchedule::FixedUpdate, |schedule| {
schedule.configure_sets(
(FixedFpsSpawning, FixedFpsUpdate, FixedFpsDraw, FixedFpsLast).chain(),
);
// …
});
This is one of reasons I probably cannot just plug-in bevy_pixels
, since I am using all those fixed timestamp system sets.
BTW I probably have one more reason to rely on my custom implementation for now (but haven't checked how would it be with your version yet: I have some window-resize reacting logic which let's my game react to it by changing where in-game controls are positioned (pixels buffer has to adapt to either landscape or portrait layout). Here I support it in what is customization of your previous bevy_pixels
implementation: https://github.com/beetrootpaul/poc--bevy-pixels-web-game/blob/a3b6a698698276ca8b60ee436f4f12b7347bd160/src/pixel_canvas/plugin.rs#L66-L171 (PixelCanvas
is kind of your PixelWrapper
I think).
Especially, I expose values calculated from:
pixels.context().scaling_renderer.clip_rect()
(in order to calculate where pixels are inside window and how big are they)winit_window.scale_factor()
(OK, this one I could access outside the bevy_pixels
plugin if needed)Then, later on, I use those values in order to calculate touch position in in-game coordinates: https://github.com/beetrootpaul/poc--bevy-pixels-web-game/blob/24b41c887aff70812379aa716e442792f3af9ca8/src/pixel_canvas/mod.rs#L32-L45
(sorry for a lot of type::try_from(value).unwrap()
noise in my code. I wrote it before I learnt that value as type
would work perfectly fine for me)
UPDATE: apparently, in terms of canvas portrait/landscape layout change I was able to use your crate 🙂 (here is my commit where I do it: https://github.com/beetrootpaul/hen-rescue-hero/commit/4a4d205efc01fd0e587dd50bd39958fe4e99ee05 )
I was able to do it mostly thanks to your public exposure of PixelsOptions
and auto_resize_*
flags. I set them to false
and re-implemented window resize handling on my own 👍
So, the only last thing that I miss is to be able to put everything into a fixed timestamp systems sets. But maybe I will ditch my intention to do fixed FPS and just do updates on floating point, then drawing based on values rounded to integers 🤔 😄 Will see what I managed to do on my side 🙂
I was trying to use
bevy_pixels
in my new Bevy 0.10 project, but it didn't work, which is totally understandable, since Bevy 0.10 was released, like, this week 🙂I might try to create Pull Request to this repository at some point, but for now I only re-created parts of this crate in my own repo (link).