User Interfaces

by @Pattentrick

Welcome to the exciting and wonderful world of UI elements! Impact++ offers a variety of simple UI elements right out of the box. There are ready to use elements for buttons, displaying text, meters, overlays and much more. In this guide we will take a closer look at the idea behind UI elements in Impact++ and how you can use them for your game.

ui

The Basics

First of all, please keep in mind that the UI elements of Impact++ should be used for simple user interfaces. If you need something big and complicated, you should consider to use the good old DOM instead. Using the DOM is a lot cheaper regarding to performance. And complex user interfaces are also easier to implement with classic DOM elements.

But for simple user interfaces Impact++ provides us with very cool UI elements. All UI elements inherit from the UIElement base class, which is located by default under plusplus/ui/ui-element.js inside the project folder. You will also find every other UI element under plusplus/ui/.

The UIElement class itself again is an entity which extends the EntityExtended class. Because of that, UI elements behave very similar to your ordinary Impact++ entities. For example, you can define an animation sheet, or a size, like you would for every other normal entity. However, there are a few things that are specific to UI elements.

UI elements are frozen: true by default. An entity with frozen: true will skip updating, which is good for performance, and UI elements usually don't need to be updated. Also, all UI elements are on an own layer called ui, so they won't interfere with your other entities. And they are fixed to the screen too, so you don't have to worry about reposition them manually, if you move your camera around. But you can disable this behaviour if you set fixed: false on your UI element if you like.

Additionally UI elements won't be destroyed if you change levels and they ignore game pauses. If you want to change this behaviour, take a look at the CLEAR_ON_LOAD_UI_LAYER and IGNORE_PAUSE_UI_LAYER property in the Impact++ config file located under plusplus/core/config.js. But make sure that your overwrite these properties in your own config-user.js and not in the config.js.

Also keep in mind that like all other EntityExtended entities, UI elements are static by default. If you change the performance to dynamic the UI element will be automatically removed from the UI layer and will be added to the entities layer.

Positioning

If you spawn a new UI element, it will appear in the top left corner of your game. This is the default behaviour, but you can reposition it or even set a margin if needed. Let's take at look at some examples.

You can spawn a new UI element like this:

var ui = ig.game.spawnEntity(ig.UIElement, 0, 0);

Let's add a margin of 2% for a little more space:

var ui = ig.game.spawnEntity(ig.UIElement, 0, 0, {
    margin: {
        x: 0.02,
        y: 0.02
    }
});

Note that margins on UI elements are actually pseudo margins. That means that they don't really keep other entities away, they are used to offset the element based on the pivot.

Of course you could also set a new position based on percentages in values from 0 to 1, but make sure that posAsPct is set to true if you use the posPct property:

var ui = ig.game.spawnEntity(ig.UIElement, 0, 0, {
    posPct: {
        x: 0.5,
        y: 0.5
    }
});

Additionally you can set posAsPct to false and set the pos as normal:

var ui = ig.game.spawnEntity(ig.UIElement, 0, 0, {
    posAsPct: false,
    pos: {
        x: 30,
        y: 10
    }
});

There is also the moveTo method which moves an UI element to another entity or position, which might come in handy in some situations of your game.

By the way, you don't have to define all of the properties of your UI element in the spawnEntity method, as seen in the examples above. For a better code organization you can also make a new class, which extends the UIElement class, and just spawn an entity with it.

Interactive UI Elements

Now that we understand the basics about UI elements, and how we can move them around, we should examine interactive UI elements. Impact++ has a base class for interactive UI elements called UIInteractive which offers some cool stuff for your game.

When a UIInteractive entity is touched or clicked it, will automatically call its activateComplete or its deactivateComplete method. Look at the code of this custom UIInteractive entity for example:

ig.UICustomElement = ig.global.UICustomElement = ig.UIInteractive.extend({


   // size, animation sheet and other stuff goes here ...


   // override the activate method to do something special when button interacted with   
   activateComplete: function ( entity ) {

       // call parent activate
       this.parent();

       // do some activation behavior

   },

   // and since interactive elements are toggled by default
   // you can also do something when deactivated
   deactivateComplete: function ( entity ) {

       this.parent();

       // do some deactivation behavior

   }

});

As you can see, you could easily add your own game mechanics to the activateComplete or deactivateComplete method after this.parent() is called. By default an UIInteractive element will toggle between the activateComplete and deactivateComplete methods.

In some cases you don't want this behaviour. You may just want that the activateComplete method gets called every time your element is interacted with, without any toggle at all. In that case you can set the alwaysToggleActivate property of your UI element to true.

Setting alwaysToggleActivate: true will result in always calling the activateComplete method if you click or touch the element, no matter how often you click or touch it.

Another useful feature is, that you can also hook into the activated or deactivated signals of the UIInteractive element, as you can see in the example below:

var ui = ig.game.spawnEntity(ig.UIInteractive, 0, 0);

ui.onActivated.add( player.pickUpItem, player );
ui.onDeactivated.add( player.dropItem, player );

The first parameter of the add method is the callback method you want to call, and the second one is the context of the callback. So in the example above the player will pick up, or drop, an item when the corresponding UI element is clicked or touched.

Like that you can even use abilities:

var ui = ig.game.spawnEntity(ig.UIInteractive, 0, 0);

ui.onActivated.add( myPlayer.specialAbility.activate, myPlayer.specialAbility );

As you may have guessed, the UIInteractive element is highly useful for buttons. Impact++ provides us with a ready to use button class called UIButton, which is based on the UIInteractive element.

The UIButton class disables toggling between the activateComplete and deactivateComplete methods by default, so that only the activate method gets called. On top of that the UIButton class helps with some basic animation handling.

Text for User Interfaces

Impact++ provides us with a class called UIText, which is highly useful for displaying text in your game world. A good example of use for the UIText class, would be displaying the player score in your game, or the amount of collected coins.

Let's take a closer look at this code example :

var _c = ig.CONFIG;

var score = ig.game.spawnEntity(ig.UIText, 0, 0, {

    font: new ig.Font( _c.PATH_TO_MEDIA + 'font_04b03_white_16.png' ),

    text: 'Score: 9000'

});

Please note that you need to define a font for your UIText entity. If you don't it will use the font mentioned in ig.CONFIG.FONT.MAIN_NAME of your config file. The value of the text property gets displayed in the game. You can of course easily change the value of the text property later on to update it:

score.text = 'Score: 9001';

With the maxWidth and maxHeight properties you can define the maximum width or height of the text area. If you have multiple lines, you can set the text alignment via the textAlign property. Possible values for textAlign are ig.Font.ALIGN.CENTER, ig.Font.ALIGN.LEFT and ig.Font.ALIGN.RIGHT.

More UI Elements

We looked at the basics of UI elements, at interactive UI elements and at UI elements for text. But you know what? There are a lot more in Impact++! Taken as a whole, Impact++ offers 13 UI related classes that are really awesome and can help you with your current game!

There are toggle classes like UITogglePause or UIToggleVolume, which are useful for toggling the game pause or the volume of the game music. The UIMeter class displays horizontally or vertically meters that are perfect for health bars. UITracker is an UI element for tracking the closest entity of a type or name in a level. And with the UIOverlay you can add all sorts of overlays to your game.

Have a closer look at the plusplus/ui/ folder of your Impact++ project, or take a look at the docs under http://collinhover.github.io/impactplusplus/ig.html, to get an overview of all the UI classes.

Learn More!

UI Element
UI Interactive
UI Button
UI Text