Skip to content

Added tutorial 04-HUD #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added img/tutorials/04/gray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tutorials/_posts/2016-04-11-camera-movement.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,6 @@ the lower-right corner (`WorldBounds.Max`).

> We won't be setting it to anything now, because we have no "map" at the moment.

<div class="button-group stacked">
<a class="button" href="/tutorials/04-hud">Continue to Tutorial 4: <i>HUD</i> &raquo;</a>
</div>
125 changes: 125 additions & 0 deletions tutorials/_posts/2016-04-12-hud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
layout: tutorial
title: HUD
permalink: /tutorials/04-hud
number: 4
---

In this tutorial, we will try to create a HUD, which will show information about selected *Cities*. We will also show
*how* you can select those Cities.

> #### Recap
> Remember what we did in [the last tutorial](/tutorials/03-camera-movement)? <br>
> We added the `KeyboardScroller`, `EdgeScroller` and `MouseZoomer` to allow camera movements.

> #### Final Code
> The final code **for tutorial 4** is available
> [here at GitHub](https://github.com/EngoEngine/TrafficManager/tree/04-hud).

### What makes a HUD so special?
You might ask, what makes a HUD so much different than the *Cities* we created the last tutorials? Good question!

Now that we're being able to move around with the camera, we might move our HUD as well. We don't want this to happen,
so we need to do something different than we usually do.

### Creating the HUD
Let's forget about selecting *Cities*. We shall focus us now on creating the HUD; we can worry about *when* to create
it, later. We shall create a 200x200 pixels HUD on the bottom-left of our screen, and it'll have a lightgray background.

#### SpaceComponent
Defining the dimensions in the `SpaceComponent` is relatively easy. But it would be nice to know *where* to position it.
The X-point is relatively easy: because it's going to be all the way to the left, the X-coordinate is `0`. However,
the height is a bit more tricky. This might also change when the window gets resized (but that's something for a future
tutorial).

Engo has four helper-functions that may be of use:

* `WindowWidth()` returns the width of the window we can use;
* `WindowHeight()` returns the height of the window we can use;
* `Width()` returns the width of the game as `engo` knows it. This is measured in game-units, not in pixels.
* `Height()` returns the height of the game as `engo` knows it.

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`).

{% highlight go %}
type HUD struct {
ecs.BasicEntity
engo.RenderComponent
engo.SpaceComponent
}
{% endhighlight %}

{% highlight go %}
hud := HUD{BasicEntity: ecs.NewBasic()}
hud.SpaceComponent = engo.SpaceComponent{
Position: engo.Point{0, engo.WindowHeight() - 200},
Width: 200,
Height: 200,
}
{% endhighlight %}

#### 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. Engo has a
function called `engo.NewTexture(img engo.Image)`. This allows you to create a texture by providing an `Image`.

> ##### Not image.Image
> Note that this is not the same `Image` as in `image.Image`. `engo.Image` requires three methods: `Data() interface{}`,
`Width() int` and `Height() int`. In order to use `image.Image`, we need to convert it using `engo.NewImageRGBA(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:

{% highlight go %}
hudImage := image.NewUniform(color.RGBA{205, 205, 205, 255})
hudNRGBA := engo.ImageToNRGBA(hudImage, 200, 200)
hudImageObj := engo.NewImageObject(hudNRGBA)
hudTexture := engo.NewTexture(hudImageObj)

hud.RenderComponent = engo.NewRenderComponent(
hudTexture,
engo.Point{1, 1},
"hud",
)
{% endhighlight %}

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.

> ##### 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: `engo.DefaultShader` (which,
> surprisingly, is the default), and the `engo.HUDShader`.

We shall be using the `HUDShader` now:

{% highlight go %}
hud.RenderComponent.SetShader(engo.HUDShader)

// And finally add it to the world:
for _, system := range world.Systems() {
switch sys := system.(type) {
case *engo.RenderSystem:
sys.Add(&hud.BasicEntity, &hud.RenderComponent, &hud.SpaceComponent)
}
}
{% endhighlight %}

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](https://github.com/EngoEngine/engo/issues/new)!

<figure class="callout text-center">
<a href="/img/tutorials/04/gray.png" target="_blank">
<img alt="City texture" src="/img/tutorials/04/gray.png" style="height:400px">
<figcaption>Our HUD so far</strong></figcaption>
</a>
</figure>