Slick Interfaces with 9-Slice | GameMaker Studio 2.3.2


Slick Interfaces with 9-Slice | GameMaker Studio 2.3.2

Hi there! In this blog post, we will be taking an in-depth look at Nine Slice (or 9-Slice), which is an exciting new feature in GameMaker Studio 2.3.2. This will be especially useful for those interested in creating smooth user interfaces and HUD.

Note: You can check the top-right corner of your GameMaker Studio 2 IDE to make sure that your version is 2.3.2 or newer, but if it isn’t, you can restart the IDE and download the update when you get the prompt. You can also download the latest version from this link: https://gms.yoyogames.com/ReleaseNotes.html 

What is Nine Slice?

Nine Slice is used to scale images in a way that preserves detail by stretching or tiling parts of the image to fit its new size. We achieve this by dividing the image into nine separate parts (or slices), as you can see below:

undefined

When an image is scaled using Nine Slice, its corners are moved without being resized, and the edge and center slices are stretched (or repeated) to fit the space between the corners. Below you can see a resized version of the image above, with its edge and center slices being repeated or tiled so the same resolution is kept after scaling:

undefined

Sprite Editor

This new release has an updated Sprite Editor that lets you set up the Nine Slice properties for a sprite and preview its scaling.

undefined

Four guides (seen above in magenta) are placed on a sprite dividing it into nine slices. You can then select a slice within the editor to see or change its “tile mode”, which controls how that slice appears after scaling. Here are all the tile modes that you are free to choose from:

undefined

“Stretch” should be fine if your slice doesn’t contain any details to be repeated, but if it does, you can use “Repeat” to tile it. You can also use “Mirror” to do the same but with every second tile being mirrored to create some variation.

When you’re done playing around with the Nine Slice options and previewing it in the panel on the right, make sure to enable “Activate Nine Slice” so you can see its effect in the game.

Note: You can read about the editor in more detail in the manual.

Using Nine Slice

Once you have Nine Slice enabled on a sprite, the technique will be used to scale that sprite in every instance. This includes any objects using that sprite, any Sequences or Asset Layers that contain that sprite, or any draw_sprite_ext() calls.

Let’s create a simple user interface using buttons. We’re going to import an spr_button image and set its Nine Slice properties, then create an obj_button object and place its instances in a room. If you try to scale them up, you will see that your Nine Slice settings are being respected and any form of stretching will preserve that sprite’s details:

undefined

Note: If you can’t see your Nine Slice settings in effect, make sure that “Activate Nine Slice” is enabled on your sprite.

If you hadn’t enabled Nine Slice for that sprite, this would have looked completely different:

undefined

Compare that with the previous image, and you will see exactly how the Nine Slice feature preserves the sprite’s details.

The GUI Layer

Let’s create a small example that draws our Nine Slice buttons to the GUI layer so that they stick to the window even when the in-game camera has moved. We’re also going to give our buttons some text for them to display.

The button object needs some variables first, so we’ll go into Variable Definitions and create one for the text it should display, and another for the color of that text:

undefined

We’re going to use the Draw GUI event to draw the button on the GUI layer. Before we start on that, we’ll add the regular Draw event and leave it empty, so the button isn’t automatically drawn inside the room.

undefined

Then in the Draw GUI event, we’re going to draw the button along with its text:

draw_self();

// Draw text
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_set_font(fnt_buttons);

draw_set_color(text_color);
draw_text(x + sprite_width / 2, y + sprite_height / 2, button_text);
draw_set_color(c_white);

draw_set_halign(fa_left);
draw_set_valign(fa_top);

In the above code, we’re simply drawing the button instance itself, then drawing the button text using center-middle alignment, a custom font and the text color specified in Variable Definitions. Now make sure to go into your room and give your buttons some unique text.

Note: When reading mouse input on the GUI layer, use  device_mouse_x_to_gui() and  device_mouse_y_to_gui() to get the mouse’s coordinates.

If you run the game now and it doesn’t have a moving camera, you will not notice a difference since the room and GUI coordinates are the same.

If we do add a moving camera, however, you will see how the buttons stay on the GUI layer even as the camera moves about in the room:

undefined

If we had used the regular Draw event, it simply would have drawn the buttons in the room: 

Note: If your window and camera have different resolutions, the GUI layer will use the resolution of the window. To change the resolution of the GUI layer to match that of the camera, use the following code in the Create event of any object:
display_set_gui_size(camera_get_view_width(view_camera[0]), camera_get_view_height(view_camera[0]))

Nine Slice in Sequences

As previously mentioned, Nine Slice will also work if you have placed a sprite or object in a Sequence. This means that you can design your interface within a Sequence and show it in the game at any time using  layer_sequence_create().

undefined 

Here we have a Sequence with our designed interface, with the origin of the Sequence set to its top-left corner. This way we can use some code to show the Sequence at (0, 0) in its layer and remove it if it already exists (note that sequence_element is initialized at -1):

if (!layer_sequence_exists("GUI", sequence_element)) {
    sequence_element = layer_sequence_create("GUI", 0, 0, seq_gui);
}
else {
    layer_sequence_destroy(sequence_element);
}

undefined

Since Sequences are created on a room layer, they’re always drawn in the room itself, but our buttons stick to the GUI layer because we used the Draw GUI event to draw them.

Nine Slice in GML

You can also use GML to modify a sprite’s Nine Slice settings at runtime and even enable it on sprites that don't have any Nine Slice settings. You can use sprite_get_nineslice() on a sprite which returns a struct containing all of its Nine Slice settings, and you can modify any values in this struct to change how the sprite is rendered. This also works on sprites that have no Nine Slice properties set or any new sprites created at runtime.

Read this manual page for more information on the Nine Slice GML functions.

Bonus Examples

Folding Button

Any sprites using Nine Slice can be scaled up or down at runtime and will always be drawn according to your Nine Slice settings. This means that you can have a folding area that grows and shrinks based on the user’s input, and it will always use the Nine Slice technique:

undefined

Health Bar

You can also use Nine Slice on a health bar sprite and have it scale according to the player’s health, which can result in a pretty good looking HUD!

undefined

Platformer Ground

The Nine Slice feature can now be used as an alternative to tiles for creating ground areas in platformers, as this would allow you to use regular object collisions instead of having to code tile collisions and can prove useful for quick prototypes.

undefined

Project

You can download the project shown above for the GUI/HUD examples by clicking here.

Summary

The Nine Slice feature will prove useful in many visual areas of your games and will be especially useful for creating GUI or HUD elements that should be resizable. As always we recommend reading through the manual to find information on this subject and many others.

Let us know what you think of this feature on Twitter  @YoYoGames, and you can also use the #GameMakerStudio2 hashtag when sharing your creations with the world.

Happy GameMaking!

 For more on GameMaker Studio 2.3.2, see: Easy Tweening with Animation Curve Library