Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Gum Forms provides a collection of standardized, fully functional UI elements. MonoGame Gum includes the following types:
Button
CheckBox
ComboBox
ListBox
ListBoxItem (used by ListBox)
PasswordBox
RadioButton
ScrollView
Slider
TextBox
We can use all of the types above by adding instances of components which map to these controls.
This tutorial does not require any of the instances from the previous tutorial. It assumes that you still have a Gum project and that you have set up your Game class to include the necessary Initialize, Draw, and Update calls.
If you would like a simpler starting point, feel free to delete all content in your TitleScreen in Gum, and feel free to delete all code aside from the bare minimum for your project.
In other words, you can reset your game screen to be as shown in the following code:
If you have followed through the tutorial series, then your project should already have Forms components. If not, you need to add Forms components to your screen by using the Add Forms Components menu item.
For more information, see the Setup tutorial which provides step-by-step instructions for adding Forms to your project.
The previous tutorial showed how to add a Button instance to our screen. We can add other functional controls by drag+dropping instances into the TitleScreen. This tutorial shows how to interact with a ListBox, so you should drag+drop a ListBox instance into your screen. You can also add additional instances of other types if you would like to see them in action, such as CheckBox, ComboBox, Slider, and TextBox.
Our forms controls already have some functionality even before we write any code in our game.
We can interact with any of the Forms instances by using GetFrameworkElementByName
. For example, to interact with the ListBox that we added in the previous section, add the following code to your Initialize method to add items to the ListBox:
Forms types such as Button are associated with Gum components based on their category. For example, the following components can be used to create Button instances.
Although the prefix "Button" suggests that these controls are Forms Buttons, the name can change and these would still create buttons. At runtime the type of Forms control associated with a component is determined by the state categories defined in the component.
For example, each of these components has a state category named ButtonCategory.
Although we won't cover the details in this tutorial, you can customize the existing components or create new components which will map to the Forms types so long as they have the appropriate category. See the next tutorial for details about Forms control customization.
Forms component instances can be added and modified just like any other instance, but at runtime these types provide common properties and methods. To learn more about working with Forms in code, see the Forms documentation.
The Forms types and properties are based on the WPF syntax. Developers familiar with WPF may find that many of the same members exist in Gum Forms. However, keep in mind that Gum Forms are still using Gum for the layout engine, so any properties related to position or size follow the Gum rules rather than WPF rules.
This tutorial showed how to create Forms instances in a screen, interact with them in code, and how to work with the different forms types.
The next tutorial covers how to generate code for custom components.
Gum screens are top level items which can contain instances of Gum objects. We'll be creating our first Gum screen in this tutorial. We'll also load this screen in code and work with gum objects.
To add a new Screen:
Open the project in the Gum tool
Right-click on the Screens folder and select Add Screen
Name the screen TitleScreen and click OK
The newly created TitleScreen is now in the Screens folder.
We can add instances to Gum Screen by drag+dropping the files onto the Game screen.
Add a Text instance by dropping the Standard/Text onto TitleScreen.
Instances can also be created by selecting the TitleScreen, then drag+dropping the item in the editor window.
Add a ButtonStandard instance by dropping Components/Controls/ButtonStandard onto TitleScreen.
Be sure to select the TitleScreen first, then drag+drop. If you click the component instead, then it will be selected, so you must re-select the TitleScreen.
The Gum tool includes lots of functionality for creating and customizing UI. For a more complete tutorial covering the Gum tool, see the Gum Tool Intro Tutorials. Feel free to spend some time creating your TitleScreen.
To show the screen in game, modify the Initialize method as shown in the following snippet:
The game now displays the Gum screen.
If you attempt to interact with the button, it does not show highlighted/clicked states. This is because we haven't yet passed the Screen to the Update method where UI interaction is performed. We'll make these changes in the next section.
Our code now includes both the Initialize call and the ToGraphicalUiElement call.
The Initialize call is responsible for loading the .gumx file and all other Gum files into memory. This loads only the Gum files and it does not load any additional files such as .pngs or font files. This call only needs to happen one time in your game.
The ToGraphicalUiElement method is responsible for converting the Gum screen into a visual object. It loads all other files referenced by the Screen and its instances such as .png and font files. This method is called whenever you want to show a new GraphicalUiElement, and it may be called multiple times in a game. For example, ToGraphicalUiElement is called whenever transitioning between screens, which we will do in a future tutorial.
The addToManagers
parameter results in the screen being added to the Gum rendering system. By passing true
for this parameter, the Screen shows up automatically when Draw is called. Remember, Draw was added in the previous tutorial.
Games usually need to interact with Gum screens in code. By convention the Screen is stored in a variable named Root
. We can modify the Game project by:
Adding a Root member to Game
Assigning Root when calling ToGraphicalUiElement
Adding the Root to the Update call
The modified code is shown below in the following code snippet:
Notice that we've added the Root as a parameter to the Update call. By doing this, we get the built-in behavior for Forms control such as Button.
More complicated games may have multiple roots, such as situations where UI may exist on multiple layers for sorting or independent zooming. This tutorial does not cover this more-complex setup, but if your game needs multiple Roots spread out over multiple layers, you can pass a list of roots to Update as well.
This tutorial uses Game1 as the container for all Gum members and logic. You may want to move this code into other classes to fit the rest of your game's code structure.
Now that we have our screen stored in the Root object, we can access objects.
We can modify the displayed string by getting an instance of the Text and modifying its properties as shown in the following code:
The code above casts TextInstance to a TextRuntime. Each standard type in Gum (such as Text, Sprite, and Container) has a corresponding runtime type (such as TextRuntime, SpriteRuntime, and ContainerRuntime). Therefore, if we wanted to interact with a Sprite in code, we would cast it to a SpriteRuntime.
We can also interact with Forms objects in code. The base type for all Forms objects is FrameworkElement, so we can use the GetFrameworkElementByName extension method as shown in the following code:
Notice that the code above uses the GetFrameworkElementByName. This code returns an instance of a FrameworkElement (Forms instance). As we'll cover in the next tutorial, only some Components can be used as Forms instances.
This tutorial showed how to load a Gum screen in code and how to interact with objects. The next tutorial discusses Forms controls and explains the difference between GraphicalUielements and Forms controls.
This tutorial walks you through creating a brand new Gum project and adding it to an existing MonoGame project. The MonoGame project can be empty or it can be an existing game - the steps are the same either way.
This tutorial covers:
Adding Gum NuGet packages
Creating a new Gum project using the Gum tool
Modifying the game .csproj to include all Gum files
Loading the Gum project in your game
This tutorial presents the minimum amount of code necessary to work with Gum. You may need to adapt the code to fit in your game project.
Before writing any code, we must add the Gum nuget package. Add the Gum.MonoGame
package to your game. For more information see the Setup page.
Once you are finished, your game project should reference the Gum.MonoGame
project.
Next we'll create a project in the Gum UI tool. If you have not yet run the Gum tool, you can get setup instructions in the Gum Setup page.
Once you have the tool downloaded, run it. You should have an empty project.
We need to save our Gum project in the Content folder of our game. Gum projects include many files. it's best to keep a Gum project and all of its files in a dedicated folder.
Add a new folder to your Game's Content folder which will contain the Gum project, such as GumProject.
In the Gum tool click File -> Save Project.
Select the GumProject folder created earlier as the target location. Give your Gum project a name such as GumProject.
After your project is saved it should appear in Visual Studio.
We can add default Forms components to our project. Forms components are premade components for standard UI elements such as Button, TextBox, and ListBox. We'll use these components in later tutorials.
To add Gum Forms components in Gum, select Content -> Add Forms Components
This tutorial will not use the DemoScreenGum, so leave this option unchecked and press OK.
Forms components modify your default components (such as Text) for styling. Click OK to apply these changes.
Your project now includes Forms components.
Now that we have our Gum project created, we can load it in our game.
First, we'll set up our project so all Gum files are copied when the project is built. To do this:
Right-click on any Gum file in your project, such as GumProject.gumx
Select the Properties item\
Set the file to Copy if Newer. If using Android, see instructions below.
Double click your game's csproj file to open it in the text editor and find the entry for the file that you marked as Copy if newer.\
Modify the code to use a wildcard for all files in the Gum project. In other words, change Content\GumProject\GumProject.gumx
to Content\GumProject\**\*.*
\
Now all files in your Gum project will be copied to the output folder whenever your project is built, including any files added later as you continue working in Gum.
At the time of this writing, Gum does not use the MonoGame Content Builder to build XNBs for any of its files. This means that referenced image files (.png) will also be copied to the output folder.
Future versions may be expanded to support using either the .XNB file format or raw PNGs.
If you are using Android, then your files must be marked as Android Assets rather than copied files.
The steps to do this are:
Open your project file
Find the entry for the Gum project if you followed the previous section which copies file using wildcard
Change it to an Android Asset. For example your code might look like this:
Now that we have a Gum project added to the .csproj, we can load the Gum project. We need to add code to Initialize, Update, and Draw. A simplified Game class with these calls would look like the following code:
The code above has the following three calls on GumService:
Initialize - this loads the argument Gum project and sets appropriate defaults. Note that we are loading a Gum project here, but the gum project is optional. Projects which are using Gum only in code would not pass the second parameter.
Update - this updates the internal keyboard, mouse, and gamepad instances and applies default behavior to any components which implement Forms. For example, if a Button is added to the Screen, this code is responsible for checking if the cursor is overlapping the Button and adjusting the highlight/pressed state appropriately.
Draw - this method draws all Gum objects to the screen. Currently this method does not perform any drawing, but in the next tutorial we'll be adding a Gum screen which is drawn in this method.
If you've followed along, your project is now a fully-functional Gum project. We haven't added any screens to the Gum project yet, so if you run the game you'll still see a blank (cornflower blue) screen.
The next tutorial adds our first screen.
This series of tutorials covers how to work with Gum Forms in code. This tutorial does not use the Gum tool and it does not load any Gum files (such as .gumx).
Code-only projects can be useful if you are adding diagnostic tools to your game, if you are evaluating Gum Forms, or if you prefer to develop without the use of GUI-based tools such as the Gum tool.
This series of tutorials covers how to load a Gum project using all of the functionality provided by Gum for creating and maintaining MonoGame projects. This tutorial is intended for brand new users of MonoGame Gum. It covers the following topics:
Creating a new Gum project (.gumx)
Loading the Gum project (.gumx) in MonoGame
Displaying Screens
Interacting with Gum Forms UI
Accessing Gum instances in code
Working with Gum code generation for strongly-typed components
Managing multiple screens
This tutorial assumes a basic understanding of the Gum tool. Specifically it assumes you know how to:
Move and resize instances
Create Screens and Entities
Work with the Variables tab
If you are brand new to Gum, we recommend learning about how to work with the Gum tool by reading the Gum tool Intro Tutorials.
Forms controls are a collection of classes which provide common UI behavior. You will probably be familiar with many controls. The most common controls include:
Button
CheckBox
ComboBox
Image
Label
ListBox
RadioButton
ScrollViewer
Slider
TextBox
All controls are in the MonoGameGum.Forms.Controls
namespace.
All controls share a few common properties and characteristics. If you are familiar with these concepts then the following list may quickly get you familiar with forms controls. If the following list doesn't make sense don't worry, we'll cover each topic in this and following tutorials.
All can controls can be added to a StackPanel. Technically, any control can be added to any other control, but for this tutorial we'll keep things simple by adding only to a StackPanel.
All controls have a Visual property which can be used to position, size, and perform advance layout behavior. This Visual property is ultimately a GraphicalUiElement which provides access to all Gum layout properties.
All controls can receive input from the mouse (usually through the Gum Cursor object). Most controls can also receive focus and input from gamepads.
All controls support binding by assigning their BindingContext property. Children controls inherit BindingContext from their parents if the BindingContext is not explicitly assigned.
For the rest of this tutorial we'll add a few of the most common controls to our project and show how to work with them. Note that for this tutorial I've removed the Button control from the previous tutorial.
For the sake of brevity, we will add all of our controls to the Root object, and all code will be added to the game's Initialize method after the Root has been created. Of course a full game may require more advanced organization but we'll keep everything in the Game Initialize for simplicity.
Labels are text objects which can display a string. Labels do not have any direct interaction such as responding to clicks. The following code adds a label to the project:
The rest of this tutorial assumes that the Label is not removed. It is used to show when events have occurred.
Button controls are usually added when a user needs to perform a command. Buttons can be clicked with the mouse and gamepad, and their click event can be manually invoked for custom support such as pressing Enter on the keyboard.
The following code creates two buttons. One is disabled so it does not respond to click events:
Notice that the Label and two Buttons are stacked top-to-bottom. This is the default behavior layout behavior of StackPanels.
As mentioned earlier, layout-related properties can be accessed through a control's Visual property.
These tutorials focus on the Forms controls themselves but for more information you can look at the different properties available in the General Properties pages.
CheckBox controls allow the user to toggle a bool value by clicking on it. Just like Button, the CheckBoxes support clicking with mouse and gamepad and changing the IsChecked property in code.
The following code creates two CheckBoxes:
TextBox controls allow the user to see and edit string values. TextBoxes support typing with the keyboard, copy/paste, selection, and multiple lines of text.
TextBoxes are automatically focused when clicked, but IsFocused can be explicitly set to give focus.
UNDER CONSTRUCTION.....
The types used in the previous tutorials fall into two categories:
Standard runtime types like TextRuntime
Forms types like Button
Games often need to interact with custom components which do not fall into either of these two categories. This tutorial shows how to create custom classes, which we refer to as runtime types for custom components.
This tutorial does not require any of the instances from the previous tutorial. It assumes that you still have a Gum project and that you have set up your Game class to include the necessary Initialize, Draw, and Update calls.
If you would like a simpler starting point, feel free to delete all content in your TitleScreen in Gum, and feel free to delete all code aside from the bare minimum for your project.
For a full example of what your Game code might look like, see the start of the Gum Forms tutorial.
For this tutorial we'll create a component which can be used to display score. To do this:
Create a new component called ScoreComponent
Drag+drop a NineSlice for the background into ScoreComponent
Drag+drop a text for the "Score:" label into ScoreComponent
Drag+drop a text for the score value into ScoreComponent
Rearrange the instances so the two Text instances can be clearly seen as shown in the following image:
The exact layout of your component does not need to match the layout displayed in the image above. If you are new to Gum and would like to learn more about creating components, see the Components tutorial.
The NineSlice in the image above may look different than your default NineSlice. You can modify its appearance by changing its texture coordinates:
Select NineSliceInstance
Click the Texture Coordinates Tab
Check the Snap to Grid option
Set the grid snapping value to 8
Drag the Texture Coordinates box to the desired region
For more information on working with texture coordinates, see the NineSlice Texture Left and Texture Top pages.
If we add an instance of this component to our screen, we can interact with it as shown in code. First, we need to drag+drop an instance of the ScoreComponent into our Screen.
One way to interact with this element is to call GetGraphicalUiElementByName. You do not need to do this in your code, this is provided simply as an example of how we might interact with it without strongly typed classes:
Although this code is functional, it can be difficult to maintain in a larger project. We are relying on values like "ScoreValue"
to find the text object. If we spell this wrong, or if we change the name of our Text in Gum, this code breaks. Also, this code is quite verbose and it can be difficult to write from memory.
We can use strongly-typed classes to solve these problems.
The Gum tool supports code generation which allows us to interact with Gum components without needing to cast or use string names. We can enable code gen in Gum by checking the check boxes in the Code tab. Also, be sure to switch the Output Library to MonoGame.
This produces a fully-generated class named ScoreComponentRuntime. In this case, the code is using FullyInCode instantiation type, which means the generated code shows the code necessary to create this component without loading the gum project. If you would like to use generated code without loading a Gum file, then this approach might be useful. Usually this approach is useful if you would like to avoid file IO or if you cannot read from disk (such as on an embedded device).
Since our project loads from disk, we'll switch to using FindByName as our Object Instantiation Type. By switching to this Object Instantiation Type, the generated code is modified to look for instances by name.
The code should look similar to the following block:
We can enable automatic saving of generated code in Gum by specifying the location of our .csproj file. To do this, set Code Project Root to the full path of folder containing your .csproj:
We can force code generation once by clicking the Generate Code button.
This creates two code files - a generated code file and a custom code file:
The generated code file contains the same code as is shown in the code generation preview.
The custom code file can be used to customize the runtime class
See below for a more detailed discussion about generated and custom code.
This component can be used in code as shown in the following snippet:
Note that all screen and components default to a Generation Behavior of GenerateAutomaticallyOnPropertyChange. This means that any changes automatically result in re-generation of the .Generated.cs file.
As mentioned above, Gum code generation creates two files. These files are named using the following conventions:
{YourScreenOrComponentName}Runtime.cs
{YourScreenOrComponentName}Runtime.Generated.cs
The two files are each declared as partial
which allows a single class to be defined across multiple files. This allows you to write additional code without needing to worry about it being overwritten by Gum when a generation happens. For more information on partial classes, see the partial class documentation: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods
As the name suggests, the Generated code (ending in .Generated.cs) contains the code generated by Gum. Generated code includes the following:
A class name matching the name of your Screen or Component with the word Runtime appended
Inheritance if Inheritance Location is set to In Generated Code
Properties for all instances
Properties for exposed variables
Properties for setting the current state, one per category
Enumerations for each category type
Initialization code for your instances
If using Object Instantiation Type of FindByName, then the items are assigned by searching by name
If using Object Instantiation Type of FullyInCode, then the items are instantiated on the spot and properties are assigned matching the variables assigned in Gum
RegisterRuntimeType method which associates this Runtime class with its matching Gum Screen or Component
Generated code is re-generated whenever a change is made in Gum or whenever you press the Generate Code button.
Generated code is completely rewritten whenever a change is made or when pressing the Generate Code button. If you make any modifications to generated code, those will be lost the next time code is generated.
Feel free to make changes if you would like to quickly test changes, but any permanent changes should be made in Gum or in custom code.
If you have encountered a situation where you would like to change how generated code behaves, please file an issue on GitHub or contact the maintainers on Discord.
Since Gum can fully generate all generated code, you can choose whether you would like to include it in version control. By including generated code in version control, your project compiles on any new machine without needing to open Gum to perform any generation. However, if you make frequent changes to your Gum project, then you will also have a lot of generated code changes in your source control history.
If you would like to exclude generated code from git, you can open your .gitignore file and add the following line:
Custom code exists to allow for modifications to the generated code. Many components do not require any additional changes.
Any type of code can be written in your custom code file. Here are a few examples of the type of code you might add in custom code:
Creating internal event handlers such as playing a sound when a button is clicked
Exposing properties which are not generated, such as an int
value for a health bar which in turn modifies an internal Text's Text property
Dynamically creating instances according to game state, such as adding items to a ListBox for an inventory screen
Updating according to a state in your game, such as querying a game options service and setting volume sliders. Similarly, events can be added to UI such as when a Slider's Value property changes and pushing the new Value to the game options service.
By default your custom code file includes a single method named CustomInitialize
which allows you to perform initialization when the component is first created.
As mentioned above, if you do not need any customization for your control, you can leave this blank. In fact, the CustomInitialize
method is declared as partial which means you can even delete this method completely and your code will still compile and run without it.
Gum generates using statements in the generated code file. These using statements can be modified in the Code tab. Initially Gum includes a best-guess of the type of using statements needed in your project.
At times your generated code may include types which are not handled by using statements. If necessary you may need to add additional project-wide using statments as your Screens or Components grow.
Notice that initially Gum may be generating additonal statements which are not needed; however, as your project grows in complexity these using statements may be needed - especially if you are using an Object Instantiation Type of FullyInCode.
We can also create runtimes for screens. Once properties have been set up, adding additional runtimes is much easier. Just click the Generate Code button!
Once we have a runtime class for our Screen, we can delete code from Game1 and write it in the CustomInitialize method as shown in the following snippet:
This tutorial shows how to generate types for screens and components which are used automatically when loading a Gum project.
The next tutorial shows how to work with multiple screens.
This tutorial walks you through creating an empty Gum project which acts as a starting point for the rest of the tutorials.
This tutorial covers:
Adding Gum NuGet packages
Modifying your Game class to support Gum and Gum Forms
Adding your first Gum control (Button)
Before writing any code, we must add the Gum nuget package. Add the Gum.MonoGame package to your game. For more information see the Setup page.
Once you are finished, your game project should reference the Gum.MonoGame
project.
Gum requires a few lines of code to get started. A simplified Game class with the required calls would look like the following code:
The code above includes the following sections:
StackPanel Root - Games using Gum usually have a Root object which contains all other instances. In this case we create a StackPanel which will hold all of our controls.
Initialize - The contents of the Initialize method calls GumService.Default.Initialize which prepares Gum. It also creates a Root instance of type StackPanel. Finally, the StackPanel has its AddToManagers method called which tells Gum to draw the StackPanel and its children that we'll add later.
Update - this updates the internal keyboard, mouse, and gamepad instances and applies default behavior to any components which implement Forms. For example, if a Button is added to the Screen, this code is responsible for checking if the cursor is overlapping the Button and adjusting the highlight/pressed state appropriately. We pass the Root instance so that it and all of its children can receive input events.
Draw - this method draws all Gum objects to the screen. This method does not yet perform any drawing since StackPanels are invisible, but we'll be adding controls later in this tutorial.
We can run our project to see a blank (cornflower blue) screen.
Now that we have Gum running, we can add controls to our StackPanel (Root). The following code in Initialize adds a button which responds to being clicked by modifying its Text property:
Gum Forms controls provide standardized functionality which can be fully customized. Forms controls place very few restrictions on their appearance and behavior. Even though a typical Button has a Text and NineSlice, it could be made of anything (really).
This tutorial shows how to customize Forms controls
This tutorial continues from previous tutorials, but initially it deletes all instances from the TitleScreen except a single ButtonStandard instance.
This tutorial modifies the default Gum Forms components. You may want to make a copy of your current project or use version control such as Git to undo your changes in case in case you want to start over.
The simplest form of customization is to modify the instance directly in Gum. Since the ButtonStandardInstance is a regular Gum object, any of its properties can be modified as expected. For example we can modify its X, Y, Width, Height, and Button Display Text properties in Gum and these changes show up in game.
While we technically have modified variables on the ButtonStandardInstance, this is usually not what we mean by customizing.
We can make modifications to ButtonStandard directly in Gum. We can select the ButtonStandard in Gum to see its individual components.
Notice that by default the Default state is selected.
If we make modifications to the ButtonStandard, every instance reflects these changes. For example, we can select TextInstance and set the following values:
Font = Impact
Font Size = 18
Is Bold = false (unchecked)
Now our instance in TitleScreen also reflects these changes, both in Gum and also in our game
If we try to change the background color on our Button, it doesn't apply in our game. For example, we can change the Background's color value in Gum. the ButtonStandard background changes in Gum:
However, if we run the game, the color reverts back to the default teal color. This happens because the button has multiple colors, not just one. Which color is displayed depends on whether the button is enabled, disabled, hovered, or pressed. We can see some of these states by running the game, moving the mouse over the button, and clicking on it.
These colors are all controlled by the ButtonStandard's states inside of its ButtonCategory. We can expand the category and click on each of the states to preview them in the Editor tab.
Since one of the states is always active, the maroon color we set in the default state is overridden immediately by the Enabled state when the app runs.
Note that only the color value was overridden by the ButtonCategory states - the changes we made to Font and Font Size showed up in game. We can see which variables are modified by the ButtonCategory states by selecting ButtonCategory.
Any change we make to the ButtonStandard component can be either done in the Default state if it is not associated with a particular state, or it can be made in the specific ButtonCategory state.
We can modify the variables that are already set in the states, or we can remove the variables completely. For simplicity we will clear the states and start from scratch. To do this, select the ButtonCategory, then press the X button next to each variable to clear it from all states in that category.
Now we can select each of the states and modify the background color as desired. Feel free to experiment as you create states. Keep in mind you can modify anything on the ButtonStandard including TextInstance and Background. If you want to revert variable changes, select the ButtonCategory and press the X button to remove the variable assignments on all states.
As before, Gum lets us preview the states by selecting them.
Once these states have been changed, we can run the game and see the states in game.
All Forms components can be customized in Gum. As with the ButtonStandard component, the first thing to check is whether a component has states. For example, to modify TextBox, first check which variables are modified in TextBoxCategory.
After determining which variables are controlled by the TextBoxCategory, make the changes to the TextBox either in the default state (if the variable is not set in TextBoxCategory), or select the desired state in TextBoxCategory (if the variable is in TextBoxCategory).
For more information on states and categories, see the and tutorials.
So far we've been working with a single Screen. This tutorial covers how to work with multiple screens, including how to add and destroy screens in response to UI events.
This tutorial changes the screen which is loaded, so you must remove the code which accesses any instances in your Game class, such as textInstance
, button
, or listBox
.
This tutorial assumes that you still have a Gum project and that you have set up your Game class to include the necessary Initialize, Draw, and Update calls.
If you would like a simpler starting point, feel free to delete all content in your TitleScreen in Gum, and feel free to delete all code aside from the bare minimum for your project. Be sure to keep your Root object as we'll be using that in this tutorial.
For a full example of what your Game code might look like, see the start of the Gum Forms tutorial.
Before we write any code, we'll create two screens. A real game might have screens like a TitleScreen, OptionsScreen, GameScreen (which includes HUD and a pause menu), and a GameOverScreen. For this tutorial we'll create two simple screens, each with a single button and a Text.
First we'll create Screen1:
Add a new screen named Screen1
Drag+drop a Text standard element into Screen1
Set the Text property on the newly created TextInstance to Screen 1 so that you can tell that you are on Screen1 when it is active in your game
Drag+drop a ButtonStandard component into Screen1
Set the Text property on the newly created ButtonStandardInstance to Go to Screen 2
Arrange the two instances so they are not overlapping
Next we'll create Screen2:
Add a new Screen named Screen2
Drag+drop a Text standard element into Screen2
Set the Text property on the newly created TextInstance to Screen 2 so that you can tell that you are in Screen2 when it is active in your game
Drag+drop a ButtonStandard component into Screen2
Set the Text property on the newly created ButtonStandardInstance to Go to Screen 1
Arrange the two instances so they are not overlapping
Next we'll make the following modifications to Game1:
Change the first screen to Screen1
Make the Root property public static
so that it can be accessed by the Screens
A full game may keep the Root in a dedicated object which provides access to the Screens, but we're making it public static
to keep the tutorial simple.
The first part of your Game1 class might look like the following code:
Now we can modify both Screen1Runtime.cs and Screen2Runtime.cs to include code that links from one to the other as shown in the following code:
Each screen removes itself from managers when its button is clicked, then creates and adds the next screen to managers.
This tutorial assumes that a Gum screen is always displayed. Whenever the Screen changes, the Game1.Root is changed to a new screen.
Games can also completely remove Gum screens altogether. To do this:
Call Game1.Root.RemoveFromManagers();
Of course, if you have organized your code differently, you will need to access the Root object through whatever pattern you have implemented (such as a service).
Set Game1.Root = null;
So that you can check for null when calling Update.
No changes are needed to the Update method - GumService.Update
can receive a null Root object.
This tutorial showed how to switch between two screens by removing the old screen with RemoveFromManagers and creating a new screen with ToGraphicalUiElement.