Hello All,
This is a moderately large request, so I’ve put most of the historical info at the bottom. At a high level, I’d like to request the following:
Proposal
- A new layer type, named “GUI Layer” be added to the IDE. Users should have a button to add a GUI layer just like they do to add a Lighting layer.
- A new Game Resolution Resize mode named “GUI Resize with Asset Zoom” or something similar to project properties.
- If this mode is selected:
- Another set of resolution fields should be displayed underneath for “Game asset resolution width” and “Game asset resolution height”
- Another field should be displayed underneath those named “Scale type” with “Scale based off Width” or “Scale based off Height”
- A backend calculation occurs to calculate the Asset Zoom and the GUI Scale/Zoom to be used in later calculations.
- Asset zoom calculates based off the Game’s Current Resolution divided by the defined Game Asset Resolution Width/Height.
- e.g. Game project is set to 1280x720p resolution. The game is running and hasn’t resized. The game asset resolution is defined as 320x180. The user defined to scale off height. 720/180 = 4x Asset zoom. If the player resized the game to 1920x1080, asset zoom updates to (1080/180) 6x zoom.
- GUI Scale or zoom calculates based off the the Game’s current resolution compared to the Game’s project defined resolution.
- e.g. Game project is set to 1280x720p. The player has resized the game to 1920x1080. The GUI Zoom is calculated as (1080/720) 1.5x
- Asset zoom calculates based off the Game’s Current Resolution divided by the defined Game Asset Resolution Width/Height.
- All NON-GUI Layers are automatically zoomed by the Asset Zoom level. This makes them zoom in as if they were made at the game project resolution. I have completed testing and this has no quality or performance loss compared to using scaling methods.
- All objects on GUI Layers have their positions, sizes/scales, font sizes, etc, automatically multiplied by the GUI Scale/Zoom. These sizes are recalculated upon resizing the game/changing the resolution.
- e.g. The game project is set to 1280x720. The player’s HP/Max HP text is set to be at 100 X 150 Y. The font size is 60 px. The player has resized the game to 1080p. The game window is actually increased to 1080p instead of scaled. The HP/Max HP text is now positioned at 150 X 225 Y (original * 1.5), the font size is now 90 px. To the player, the UI is actually positioned exactly as it was before proportionally, the game is just bigger.
- All events that occur to GUI Layer objects take this GUI Zoom/Scale into account.
- e.g. The user making the game always only has to enter 100 X 150 Y. The backend should see these values as 100 * GUI Scale Factor X, 150 * GUI Scale Factor Y.
- Expressions should be added to obtain the project resolution, the asset zoom factor, and the GUI Scale/Zoom factor
- Pixel Rounding/Position Rounding should be added as a project setting.
- Regardless of this setting, Text on the GUI Layer should always have it’s font size rounded.
- An option to disable/hide the toolbar in preview should be added. Due to how Pixi/GDevelop forces the resolution to include the toolbar, it gives an inaccurate representation of games in fullscreen.
Benefits
- This fixes all font scaling issues with any text on a GUI layer, since they’re not being scaled, just resized and repositioned.
- This makes it so game assets can be at a MUCH smaller resolution than the native resolution, allowing for much smaller projects and in many cases better memory and CPU utilization.
- Implementing this eliminates a lot of very difficult math for newer users in order to replicate this functionality, and makes it seamless in the background.
- This should be renderer agnostic if GDevelop ever switches to/adds other renderers.
Drawback
- We’ll need clear documentation both in the engine and in the wiki that explains asset resolution vs game resolution (I’m happy to build this out if this is implemented)
- This requires addition to both the IDE and backend code. I know it is possible since I’m doing it in the event system, but I don’t know the complexity.
Example Project
GDevelop GUI Layer Example by Silver-Streak (GUI Layer Proposal Project.zip)
Here’s the example project folder, I’ve added a ton of comments on the general events (yellow comments), and more details on the proposal (red/pink comments).
Example Compiled Game
GDevelop GUI Layer Example by Silver-Streak (GUI Layer Example Build.zip)
Default Platformer Controls (Directional Pad)
Press P to resize to 1600x900 window.
Press O to resize to 1280x720 window.
Press M to fullscreen the game.
Press N to restore to window.
Background
I’ve been doing as much research as I can and wracking my brain to try and figure out the difference between how GDevelop scales assets and how other cross-platform/HTML5 engines do.
For other PixiJS engines (Construct and Phaser), it seems like they’ve heavily branched from Pixi to establish their own methods. I don’t think changing renderers is a reasonable request or a relatively easy task, so I kept digging.
I started looking into how Defold does it, and how Game Maker Studio’s system handles it. What I’ve discovered is that both of them implement “GUI Layers” and “Non-GUI Layers”. GUI Layers are rendered at native resolution, while Non-GUI Layers can be any resolution and are scaled/zoomed in to match the native resolution.
With that knowledge in mind, I’ve been plugging away at the event system trying to figure out if, and how, this could be done in GDevelop. I’ve now confirmed that it can be done, so I’d like to request this be implemented as an actual engine feature. I feel that the math involved is pretty complex, and would be difficult for new users to replicate on their own. However, if this is implemented, users can have perfect pixel fonts, text, and other objects regardless of their game size.
References
Defold GUI Layers: GUI scenes in Defold
Game Maker Studio’s GUI Layers: Gui Layer Secrets