17cupsofcoffee / tetra

🎮 A simple 2D game framework written in Rust
MIT License
910 stars 63 forks source link

Investigate how Context could be broken up #209

Open 17cupsofcoffee opened 3 years ago

17cupsofcoffee commented 3 years ago

Summary: Tetra using a giant Context struct for all of its internal state is a bit of a pain - it makes it impossible for the internals of the renderer to use the public graphics API (because you can't pass ctx and something stored in ctx into the same method), and it's tricky to break it up into something that people can use in a custom game loop.

For me, the main constraints on making a change like this would be:

I'm not sure if there's an API that meets those criteria! But it's worth thinking about.

17cupsofcoffee commented 3 years ago

Been thinking about this some more, and I think I can articulate what's bugged me about my previous attempts at splitting up Context:

Say we broke up Context into Graphics/Window/Input structs. Cool, that feels more decoupled. But big chunks of a game are going to need access to more than one of those - heck, update could need all of them! So either Tetra or the end user has to pack them up in a struct to pass them around (in which case we're back to having a big Context object) or people have to pass down three arguments where they used to only pass one. I don't think that actually improves anything for end users; in fact if anything it makes their life harder...

rghartmann commented 3 years ago

Have you thought about attribute-based access? If an update() call needs the delta time, the user can request it by:

fn update(#[time] delta: Duration) -> tetra::Result {}

Otherwise, the function would have no parameters at all, and be called as is by Tetra as part of the loop.

I'm not sure if it'd complicate working with the State trait in any way, though (somewhat new to Rust myself). But I am taking inspiration from how Legion handles systems.