diff --git a/img/tutorials/04/gray.png b/img/tutorials/04/gray.png new file mode 100644 index 0000000..e232d90 Binary files /dev/null and b/img/tutorials/04/gray.png differ diff --git a/tutorials/_posts/2016-04-11-camera-movement.md b/tutorials/_posts/2016-04-11-camera-movement.md index c1578aa..5fb4fb6 100644 --- a/tutorials/_posts/2016-04-11-camera-movement.md +++ b/tutorials/_posts/2016-04-11-camera-movement.md @@ -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. +
+Continue to Tutorial 4: HUD » +
\ No newline at end of file diff --git a/tutorials/_posts/2016-04-12-hud.md b/tutorials/_posts/2016-04-12-hud.md new file mode 100644 index 0000000..fd73fac --- /dev/null +++ b/tutorials/_posts/2016-04-12-hud.md @@ -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)?
+> 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)! + +
+ +City texture +
Our HUD so far
+
+