Go, Go, Godot!
  • 0

A GDScript refactoring exercise

December 22, 2022

Arguably, more fun than writing code is removing code. I was assembling a split-screen multiplayer UI.

The goal behavior is to show/hide the appropriate displays for the players, depending on how many players there are.

Initially, the code to update the UI was very simple, because I started with two players. In that case, you can get away with just toggling the visibility of the second player’s display.

Once I added more scenarios, the code got lengthier. In order to support 0 – 4 players correctly, it ended up looking like this:

## Show the correct viewports based on player count
func _update_player_viewports():
    match num_players:
        0:
            %HBTop.visible = false
            %HBBottom.visible = false
        1:
            %HBTop.visible = true
            %HBTop/VPC1.visible = true
            %HBTop/VPC2.visible = false
            %HBBottom.visible = false
        2:
            %HBTop.visible = true
            %HBTop/VPC1.visible = true
            %HBTop/VPC2.visible = true
            %HBBottom.visible = false
        3:
            %HBTop.visible = true
            %HBTop/VPC1.visible = true
            %HBTop/VPC2.visible = true
            %HBBottom.visible = true
            %HBBottom/VPC1.visible = true
            %HBBottom/VPC2.visible = false
        4:
            %HBTop.visible = true
            %HBTop/VPC1.visible = true
            %HBTop/VPC2.visible = true
            %HBBottom.visible = true
            %HBBottom/VPC1.visible = true
            %HBBottom/VPC2.visible = true

If you’re familiar with the match statement syntax, this code is really quite straightforward. It’s a bit naïve verbose, but it is easy to follow and structured enough to be readable. But could it be shorter? The cases for three and four players look nearly identical.

Sometimes it can be risky to refactor something verbose for a bit more brevity. Some solutions might end up being “too clever”. I try to aim for clarity first unless there are specific performance demands.

Usually, it’s a matter of how to approach the problem. The code above very clearly divides up the use cases. If I’m dealing with three players, I know I need to look at the 3: block and that I can ignore the other blocks of code. It’s very light in terms of cognitive load.

This code snippet achieves that same behavior, but in only 8 lines of code instead of 30:

## Show the correct viewports based on player count
func _update_player_viewports():
    %HBTop.visible = num_players > 0
    %HBTop/VPC1.visible = num_players > 0
    %HBTop/VPC2.visible = num_players > 1
    %HBBottom.visible = num_players > 2
    %HBBottom/VPC1.visible = num_players > 2
    %HBBottom/VPC2.visible = num_players > 3

But is it as intuitive?

  1. The match statement is entirely gone.
  2. Each node is updated exactly once (but with a boolean expression instead of a boolean constant; arguably less declarative and needs computation by the reader).
  3. The order of nodes is specified so that the visibility is true until it’s false . Example for 2 players:
## Update the viewports to reflect the configured players
func _update_player_viewports():
    %HBTop.visible = num_players > 0
    %HBTop/VPC1.visible = num_players > 0
    %HBTop/VPC2.visible = num_players > 1
    %HBBottom.visible = num_players > 2
    %HBBottom/VPC1.visible = num_players > 2
    %HBBottom/VPC2.visible = num_players > 3

Well, it’s shorter anyway.

One final touch: I want to always show the first viewport, even when there are no players:

## Show the correct viewports based on player count
func _update_player_viewports():
    %HBTop.visible = num_players >= 0
    %HBTop/VPC1.visible = num_players >= 0
    %HBTop/VPC2.visible = num_players > 1
    %HBBottom.visible = num_players > 2
    %HBBottom/VPC1.visible = num_players > 2
    %HBBottom/VPC2.visible = num_players > 3
developer experienceobject-oriented Programmingprogramming
Posted in Godot.
Share
PreviousIs Godot is the Linux of Game Engines?
NextWhen not all strings are Strings. Detect bugs in your GDscript more easily with static typing

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related Posts

  • Godot Game Engine Logo
    September 15, 2022

    Godot Engine 4 reaches beta

    Just a couple of days ago, Godot 4.0 alpha 17 was announced. Today, Godot Engine 4.0 beta 1 was released. Be sure to check out the announcement. There are lots of improvements across the board; rendering, lighting, physics and navigation, animation, and scripting.

  • January 30, 2024

    Inventory System v1.1 available

    Hot on the heels of 1.0, version 1.1 allows for gaps in the inventory. This release also correctly bakes the release version into the PDF Guide.

  • July 17, 2023

    Terrain3D for Godot has been released

    The Terrain3D addon for Godot lets you create and manage 3D terrains within Godot. It looks quite promising for making landscapes, hills, valleys, and other natural environments. The addon provides tools for sculpting the terrain, and you can paint different textures like grass, dirt, or rock, and blend them smoothly. It also supports features like …

  • November 23, 2024

    Inventory System v1.18 available

    A new version of the Inventory System is available. This release includes a new structure placement feature and improves crafting. Structure Placement Players can now place structures from their inventory. When using an inventory item representing a structure, the player is prompted to select where to place it. The included demo lets players place an …

    © 2026 GoGoGodot.io. All rights reserved.