PistonDevelopers / piston

A modular game engine written in Rust
https://www.piston.rs
MIT License
4.62k stars 234 forks source link

Why is an &event required for draw_2d function? #1331

Closed CoNsTaRs closed 5 years ago

CoNsTaRs commented 5 years ago

How can I draw on the window without an event? Is there some way to invoke draw_2d base on a timer? Thanks.

bvssvni commented 5 years ago

The event loop handles user input and typical game logic such as when to render and update. It is completely optional and you can write your own logic. One place to start is to study the source code of Events.

CoNsTaRs commented 5 years ago

Thanks for your reply, I am aware of the use of Events and event loop, but what confused me was that why is an event generally necessary for updating a window? or is there any way to update/render without an event? Sorry if the question sounds stupid. I am using piston_window.

CoNsTaRs commented 5 years ago

Currently I am just passing a dummy Event::Loop(Loop::Render(RenderArgs{ext_dt,window_size,draw_size})) to draw_2d function, am I in the right direction?

bvssvni commented 5 years ago

In general, if you want to render you can just do it directly, but you have to swap buffers yourself. However, the events are going to queue up in the window backend since they are enabled. You can manipulate e.g. the underlying SDL2 window etc.

Everything that Piston does in the event loop is a sequence of instructions. Using the Window trait, you can replicate this sequence of instructions through other means. If you wonder whether an event is necessary, the answer is: Of course not. You don't have to do it the way the Piston event loop does it.

You can use the Piston event loop for some more advanced things, like disabling swapping of buffers and then ignore render events. You can just create your own based on a timer. A timer is easy to create: Just use a f64 which is subtracted by delta time from update events and then create your own custom render event when it reaches 0.0. Reset the timer and repeat. Remember to swap the buffer manually at the end of the render event.

bvssvni commented 5 years ago

The Piston event loop polls events for you, so I think disabling swapping of buffers might solve the problem for you without unexpected side effects.

You can also use https://docs.rs/piston/0.49.0/piston/trait.Window.html#tymethod.wait_event_timeout. It is a lot harder to get it right this way, but it should be possible.

It comes down to whether you are happy with the accuracy that a fixed time step loop gives you. In a fixed time step loop, you trade some accuracy against deterministic behavior. You can do smarter things based on what you need, but I can't help you with that since it requires more complex analysis.

bvssvni commented 5 years ago

The overhead of e.g. ignored render events with disabled buffer swapping is pretty low, so I would not be concerned about the overhead. What matters is the timing accuracy. However, timing accuracy depends on pretty much everything you do, which requires deeper analysis.

You must also watch out for triple buffering. Some window backends uses more than two drawing buffers, such that you need to render and swap multiple times before you get the thing you rendered on the screen.

bvssvni commented 5 years ago

The PistonWindow::draw_2d is just a piece of code that do some instructions, which you can copy and paste into your application to do the same thing and then modify it to your needs. If you don't want to generate a custom render event, I mean.

CoNsTaRs commented 5 years ago

Alright, thanks a lot for your help! I will try to figure things out as soon as I have time.

CoNsTaRs commented 5 years ago

Hi, I have dived into the source code for a little bit and decided to prototype with a fixed time loop first. (Since it's easier for now) Here is a question, what are the purpose/difference between a Loop:: Update and a Loop::Idel respectively? Which is more suitable for a fixed time loop? Is there any documentation/wiki/tutorial for Piston? I feel like digging into source code is a normal thing when working with Piston lol.

bvssvni commented 5 years ago

Idle events are emitted before the game loop goes to sleep. Since the game loop can predict how long it is going to sleep, it uses idle event as a way to tell that this is a good time to use the main thread for background tasks.

bvssvni commented 5 years ago

By a fixed time step I meant the Piston loop. Update events are using fixed time steps.

CoNsTaRs commented 5 years ago

Thanks, I almost finished prototyping my project. Btw, during these days working whit piston, I find that it will be good to support some sort of multi-threaded event pushing to help better separating game logic and user interface design.

Since this thread is being inactive for some days, and questions already got answers, I am closing this issue now.