Updated Tutorial:Screen, colors and squares (markdown)

Hajime Hoshi 2016-12-28 11:33:11 +09:00
parent e89b6d6890
commit 72eac1c73a

@ -1,8 +1,8 @@
You've already learned things about how to make a basic game with Ebiten in the last tutorial, but that cannot be count as an actual game because it can only shows the text, thus we would need to learn more things about the screen before we make a real game, and that's what we'll talk about in this chapter. You've already learned things about how to make a basic game with Ebiten in the last tutorial, but that cannot be count as an actual game because it can only show the text, thus we would need to learn more things about the screen before we make a real game, and that's what we'll talk about in this chapter.
The game screen is the most important place in the game, it displays everything you can see, and the screen is always been refreshing but the speed is too fast so it might have been refreshed million times before you've noticed. The game screen is the most important place in the game. It displays everything you can see, and the screen is always refreshed but the speed is too fast so it might have been refreshed million times before you notice.
Let's continue the example from the last tutorial, I've brought it to here. By the way, I've added some comments for you :) Let's continue the example from the last tutorial:
```go ```go
package main package main
@ -28,15 +28,15 @@ func main() {
} }
``` ```
Remember the code above will display something like this right? Remember the code above will display something like this:
![](http://i.imgur.com/In5N0Ck.png) ![](http://i.imgur.com/In5N0Ck.png)
Hmmm... It seems a little bit boring, how about filling the screen with some colors? It seems a little bit boring. Let's fill the screen with some colors.
# Color struct # Color struct
Before you color your game screen, you would've to create a color struct, it's quite simple, you might already heard about the Hex color (for example: `#FF0000`) if you have experience with the photo editor or the webpage design software before. Before you color your game screen, you need to create a color struct. It's quite simple. you might already heard about the Hex color (for example: `#FF0000`) if you have experience with the photo editor or the webpage design software before.
You will need to import the `image/color` package to create the color struct by replacing the `import` section of your code to this: You will need to import the `image/color` package to create the color struct by replacing the `import` section of your code to this:
@ -49,19 +49,19 @@ import (
) )
``` ```
Great! And it's time to create a color, how about... a red color? The hex of the red is `#FF0000`, so it will be `0xff, 0x00, 0x00` in our code, and it looks like this (You don't have to edit the last `0xff`): It's time to create a color. Let's adopt red color here. The hex of the red is `#FF0000`, so it will be `0xff, 0x00, 0x00` in our code, and it looks like this (the last 0xff is alpha value).
```go ```go
color.NRGBA{0xff, 0x00, 0x00, 0xff} color.NRGBA{0xff, 0x00, 0x00, 0xff}
``` ```
Alright, now you know how to create a new color, and it's time to paint your game screen. Now you know how to create a new color, and it's time to paint your game screen.
# Fill the screen with the color # Fill the screen with the color
There's a `Fill(clr color.Color)` function for the screen in Ebiten. It is used to fill the screen with a color, and you will need to pass a `color.Color` data type to the function. That's exactly what our color struct returns! So what are we waiting for? There is a `Fill(clr color.Color)` function for the screen in Ebiten. It is used to fill the screen with a color, and you will need to pass a `color.Color` value to the function. That's exactly what our color struct returns.
Remember the `update()` function? Yeah, the function which keeps being called by Ebiten, and we'll paint the screen in the function. Remember the `update()` function. The function which keeps being called by Ebiten, and we'll paint the screen in the function.
```go ```go
func update(screen *ebiten.Image) error { func update(screen *ebiten.Image) error {
@ -80,7 +80,7 @@ func update(screen *ebiten.Image) error {
} }
``` ```
You would've to care about the priority of the codes above, you will need to fill the color before you display the text, otherwise the text will be covered by the color (So you couldn't see the text). You need to care about the priority of the codes above. You will need to fill the color before you display the text, otherwise the text will be covered by the color (so you couldn't see the text).
And save your file, run `go run ./main.go` in your terminal, you'll see the following result: And save your file, run `go run ./main.go` in your terminal, you'll see the following result:
@ -88,52 +88,56 @@ And save your file, run `go run ./main.go` in your terminal, you'll see the foll
# Creating squares # Creating squares
In the next few steps, we'll create some squares, so the game will be more *game-like*. The squares won't be able to move at least now, but trust me, in the next few chapters it will be able to ;). In the next few steps, we'll create some squares, so the game will be more game-like. The squares won't be able to move at least now, however, in the next few chapters it will be able to.
## Squares are just *images* ## Squares are just *images*
There're actually no squares in Ebiten. **Everything is an image** (Includes the screen, it's just bigger), so what we'll do next, is just creating a new image, and make it looks like a square. There're actually no squares in Ebiten. **Everything is an image** (including the screen, it's just bigger), so what we'll do next, is just creating a new image, and make it looks like a square.
## Fill the new image with the color ## Fill the new image with the color
Like we said before, the squares were just images, You can create a new image by using `ebiten.NewImage(width, height int, filter Filter)` in Ebiten, here are the values that you'll need to provide to the function: As we said before, the squares are just images. You can create a new image by using `ebiten.NewImage(width, height int, filter Filter)` in Ebiten, here are the values that you'll need to provide to the function:
* `width` is the width of the new image with the pixels. * `width` is the width of the new image with the pixels.
* `height` is the height of the new image with the pixels. * `height` is the height of the new image with the pixels.
* `filter` is the filter for rendering the image, we won't use it at this chapter, so just do what we do and it'll be okay. * `filter` is the filter for rendering the image, we won't use it at this chapter, so just do what we do and it'll be okay.
In the following example, we'll create an 16x16 image, it will look like a common square, and the image will be saved into the `square` variable, so we can use it later. In the following example, we'll create an 16x16 image, it will look like a common square, and the image will be saved into the `square` variable, so we can use it later. Note that `square` is defined as a global variable since creating an image is an expensive operation so we should avoid to call this many times. In this example, only one square is necessary. In `update` function, fill the square with white color.
```go ```go
// Create an 16x16 image var square *ebiten.Image
square, _ := ebiten.NewImage(16, 16, ebiten.FilterNearest)
// Fill the square with the white color func update(screen *ebiten.Image) error {
square.Fill(color.White) // ...
if square == nil {
// Create an 16x16 image
var err error
square, err = ebiten.NewImage(16, 16, ebiten.FilterNearest)
if err != nil {
return err
}
}
// Fill the square with the white color
if err := square.Fill(color.White); err != nil {
return err
}
// ...
}
``` ```
In the end of the code, we used a new way to color our new image with the `color.White` color. You won't want to create a transparent image, will you?
You might wondering about what is `color.White`, you can actually found it in the `image/color` package, the package provided two default colors, which are BLACK (`color.Black`) and WHITE (`color.White`). You might wondering about what is `color.White`, you can actually found it in the `image/color` package, the package provided two default colors, which are BLACK (`color.Black`) and WHITE (`color.White`).
## Reposition and render the image to the game screen ## Reposition and render the image to the game screen
You will need to render the new image to the main screen once you've created it, otherwise it won't be displayed on the screen, but before you do it, you will also need to create a "render option struct" which's named as `DrawImageOptions{}`, it used to tell Ebiten how should the image be drew on the screen, we'll talk about it later, and right now, we can leave it as blank. You will need to render the new image to the main screen once you've created it, otherwise it won't be displayed on the screen, but before you do it, you will also need to create a "render option struct" which's named as `DrawImageOptions{}`, which tells Ebiten how should the image be drew on the screen. We'll talk about it later, and right now, we can leave it as blank.
Here's the fully example, we'll explain it later. The examples above were be done in the `update()` function, so let's see what should your `update()` function be this time. Here's the fully example.
```go ```go
var square *ebiten.Image var square *ebiten.Image
func init() {
// Create an 16x16 image
var err error
square, err = ebiten.NewImage(16, 16, ebiten.FilterNearest)
if err != nil {
panic(err)
}
}
func update(screen *ebiten.Image) error { func update(screen *ebiten.Image) error {
// Fill the screen with #FF0000 color // Fill the screen with #FF0000 color
@ -146,6 +150,15 @@ func update(screen *ebiten.Image) error {
return err return err
} }
if square == nil {
// Create an 16x16 image
var err error
square, err = ebiten.NewImage(16, 16, ebiten.FilterNearest)
if err != nil {
return err
}
}
// Fill the square with the white color // Fill the square with the white color
if err := square.Fill(color.White); err != nil { if err := square.Fill(color.White); err != nil {
return err return err
@ -163,17 +176,17 @@ func update(screen *ebiten.Image) error {
} }
``` ```
`DrawImage(image *Image, options *DrawImageOptions)` is the function that draws the image to the screen, it's simple to use. You will need to pass the new image which will be rendered on the screen to the first parameter, and the second one is the render option struct which we created above, and that's it, simple, right? `DrawImage(image *Image, options *DrawImageOptions)` is the function that draws the image to the screen. It's simple to use. You will need to pass the new image which will be rendered on the screen to the first parameter, and the second one is the render option struct which we created above, and that's it.
Now run your game with `go run ./main.go` command in your terminal after you saved it. Now run your game with `go run ./main.go` command in your terminal after you saved it.
![](http://i.imgur.com/IdFYBoH.png) ![](http://i.imgur.com/IdFYBoH.png)
Oops! Our text is covered by the new image! We'll need to **set the position of the image** to avoid the such issue. Our text is covered by the new image. We'll need to set the position of the image to avoid the such issue.
# Image transforming # Image transforming
There's no position configuration in Ebiten, but you can get the same result by transforming your images, there are many ways to transform your images in Ebiten, but we'll only talk the basic `x`, `y` position translate in this chapter. There's no position configuration in Ebiten, but you can get the same result by transforming your images. There are many ways to transform your images in Ebiten, but we'll only talk the basic `x`, `y` position translate in this chapter.
What we need is to add the `translate` effect to the `option struct` by using `Translate(tx, ty float64)` function, `float64` is the floating point data type, and here're the two parameters that you'll need to pass to the function: What we need is to add the `translate` effect to the `option struct` by using `Translate(tx, ty float64)` function, `float64` is the floating point data type, and here're the two parameters that you'll need to pass to the function: