Tutorial 4
HUD
In this tutorial, we will create a Heads-Up display, or HUD, that can provide information to the player about things like how much money they have at the moment, details about the currently selected city, etc.
Recap
Remember what we did in the last tutorial?
We added theKeyboardScroller
,EdgeScroller
andMouseZoomer
to allow camera movements.
Final Code
The final code for tutorial 4 is available here at GitHub.
What makes HUD so special?
You might ask, what makes an HUD different from, say, the Cities we added in the previous tutorial? Good question! Once we get a map size bigger than the game window, we’ll be able to scroll around our map. Some components we don’t want to move when we move the camera. The HUD shader option makes it so these components do not move as you pan around the game world.
Creating the HUD
Let’s get started creating the HUD entities. We’ll create a 200x200 light gray, partially transparent HUD at the bottom left corner of the screen.
Space component
Getting the dimensions for the SpaceComponent is easy, but we need a way to
properly position our HUD in the bottom left corner. Luckily engo
has six useful
functions to deal with the size of the screen:
engo.WindowWidth()
gives the current width of the game windowengo.GameWidth()
is the size of the game (meaning what was passed as parameters in engo.RunOptions)engo.CanvasWidth()
gives the current width of the openGL Frame Buffer.
Each of these functions also have the corresponding Height variation.
Because we are building a HUD, we are not interested in how large our in-game
map is. We are only interested in how big the window itself is. We shall be
using the WindowHeight()
, and subtracting the height of our HUD (in this case
200
).
RenderComponent
Now we know where to draw it, let’s talk about what we’re going to draw. We
could be creating a 200x200 image filled with a white background. This is
usually the best way to go, since you can easily add additional effects in your
image editing environment. Luckily, engo
does not rely on files alone to
provide the textures. The common package has a function called
common.NewTextureSingle(img common.Image)
. This allows you to create a texture
by providing a common.Image
.
Not image.Image
Note that this is not the same
Image
as inimage.Image
.common.Image
requires three methods:Data() interface{}
,Width() int
andHeight() int
. In order to useimage.Image
, we need to convert it usingcommon.NewImageObject(img)
.
As noted, we are indeed going to use our own image.Image
, and then cast it in
order to transform it to a Texture
.
It is a bit verbose at the moment, so we’re not going in too much depth into this:
But if we were to add this RenderComponent
to our entity, and add the entity to our world, we would notice that this
is no HUD yet. As we predicted, it moves around as the camera moves. This is because we haven’t set the correct
Shader
yet. We also set the Z-index of our UI to a higher number, so it’s
always on top of anything else on the screen.
Shader
A shader roughly is a program which is being executed on the (hundreds / thousands of) GPU cores, in order to graphically render your texture. Engo has two you can use without much effort:
common.DefaultShader
(which, surprisingly, is the default), and thecommon.HUDShader
.
We shall be using the HUDShader
now:
That’s it! If we put these lines of code in our Setup()
function, our game
will have a 200x200px HUD with gray-ish background, which does not move around
as we move around with our camera. You may have noticed that a 200x200px HUD is
a bit large for a 400x400ox window. You may want to change the window dimensions
to something a bit bigger, 800x800px for instance. If you have any cool thoughts
on how to handle resizing / different resolutions in an orderly fashion, please
tell us by creating an issue at GitHub!
Next time we’re going to render the background map using a tmx file and adjust our CameraBounds based on it!