Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen layers #634

Closed
Closed

Conversation

Nathan-Fenner
Copy link
Contributor

This is a refactoring of how the screen state is "restored" when you want to hide something that was previously drawn.

Before this PR, the overlayDisplayBuffer optionally provided an rbuf parameter, which would be filled with the "old" screen. Then, later, a caller could "revert" to this version of the screen by drawing it over the current screen.

Obviously, this pattern worked, but it hides the real structure of the game's interface from the platform. In order to make it possible to enrich the display of the world, it should be possible to expose the structure of the layers of UI (e.g. confirmation window on top of inventory on top of dungeon).

This PR makes a partial step in this direction: pushNewScreenLayer(...) declares that you're about to draw a new layer of UI onto the screen. In a global variable, it stores the current displayBuffer, which can be reverted by calling popScreenLayer(...):

ScreenLayerHandle pushNewScreenLayer(ScreenLayerOptions options);
void popScreenLayer(ScreenLayerHandle layer);

In order to make debugging mismatched calls a little bit easier, these functions return a ScreenLayerHandle, which just tracks the index into the layers. In the future, we might want to include additional information in these. Likewise, each layer is given a name, and there's a (commented out right now - should probably guard with a #define instead) debug function that prints the current layer stack.


The overlayDisplayBuffer function has been rewritten to not support the rbuf parameter - all existing callers were rewritten to use the pushNewScreenLayer abstraction instead. A few of them are still quite messy (displayInventory in particular is quite complicated).


In follow-on PRs, I want to keep refactoring in this direction, of exposing the underlying state of the view to the platform (in addition to the backwards-compatible grid of symbols):

  • overlayDisplayBuffer will also store (transparent) versions of each layer, so that they can be composited by the platform directly
  • direct access to screenDisplayBuffer should be refactored out, so that layers can be composed "lazily" in the platform - this means you can't make a change to displayBuffer that's not also reflected in the transparent ui layer
  • ScreenLayerOptions should provide additional details about the layer, so that different layers can be treated differently by the platform without lots of hard-coding logic
  • More parts of the screen should be organized into layers, like making the status at the left separate from the dungeon

@tmewett
Copy link
Owner

tmewett commented Dec 7, 2023

This is an interesting idea, but I wondered if you had any specifics in mind for how this could be used?

For some context - some platforms do struggle to adapt the game, but not in this way. (The main concern that comes to mind is smaller screens. People have been asking about Brogue on smartphones for a while. Someone even recently did an experiment re-writing all the entire UI for a phone screen.)

A larger UI refactor I have been pondering for a while is actually a complete inversion of control, having the UI code outside/above/calling the game code. We could provide the default game outer layer with extra option hints/hooks like screen size, or this layer system, if needed. This has other benefits too, like making it possible to write proper gameplay tests. Any thoughts on this?

@Nathan-Fenner
Copy link
Contributor Author

The ideas here are better implemented in #646 and #656, so this PR isn't needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants