Skip to main content

Placing the Fruit

A freely moving snake is nice. But it get's a bit dull if that's all there is. To make it a bit more of a challenge, you'd need to add something to change the snake. The classic approach is to let the snake "eat" fruits. That's a good place to start.

To place (and eat) a fruit, you first need to make a variable for this. Since it's simply a point on the grid, Point will do:

    frameCount = 0    prevState  uint8    fruit      Point

Random Numbers#

Go provides us with pretty much everything we could need to create random numbers. The package math/rand contains a handy function: Intn(n int) int. It takes an integer and returns a random value between 0 and n-1. If you think, placing something like this in start would be a good idea:

    fruit.X = rand(20)    fruit.Y = rand(20)

You'd be surprised that this pretty much crashes. So we can't use the standard random-functions of Go? No, we can. We just have to make our own instance of the number generator:

    frameCount = 0    prevState  uint8    fruit      Point    rnd        func(int) int

Now you can use it like this:

    rnd = rand.New(rand.NewSource(1)).Intn    fruit.X = rnd(20)    fruit.Y = rnd(20)

The 1 is the seed. But having a fixed seed is not a good idea. You might be tempted to use time.Now().Unix(). But this will crash the came with a nice field 'runtime.ticks' is not a Function.

Since the standard time is not an option, how about you use something that is time related and is already in your project? Like frameCount?

    rnd = rand.New(rand.NewSource(int64(frameCount))).Intn    fruit.X = rnd(20)    fruit.Y = rnd(20)

Works. But since this is the start-function, frameCount is pretty much always 0. That's why here's a small exercise for you: change the seed after the first key was pressed.

Check the for nil

Keep in mind, that the value of rnd is nil if it wasn't initialized yet.

Importing PNG Files#

Importing images in WASM-4 works a bit different compared to other game engines and Fantasy Consoles. Images have to meet certain criteria:

  • PNG only
  • Index only
  • 4 colors max

Indexed PNG files can be created by several image apps like Aseprite or GIMP.

The image we import is a 8x8 PNG file with exactly 4 colors:

Zoomed Fruit This image is zoomed by 800%.

Zoomed Fruit This is the original image. You can download it to proceed.

Now you need to import the image. For this, the WASM-4 CLI tool w4 comes with another tool: png2src. You can use it like this:

w4 png2src --go fruit.png

This will output the following content in the terminal:

const fruitWidth = 8const fruitHeight = 8const fruitFlags = 1 // BLIT_2BPPvar fruit = [16]byte { 0x00,0xa0,0x02,0x00,0x0e,0xf0,0x36,0x5c,0xd6,0x57,0xd5,0x57,0x35,0x5c,0x0f,0xf0 }

To get it into a an existing file, use the >> operator. Like this:

w4 png2src --go fruit.png >> main.go

This will add the previous lines to your main.go and causes an error because "fruit" already exists. Just rename the new fruit to fruitSprite and move it somewhere else. Also: You can remove the other stuff added, you won't need it for this project:

    frameCount  = 0    prevState   uint8    fruit       Point    rnd         func(int) int    fruitSprite = [16]byte{0x00, 0xa0, 0x02, 0x00, 0x0e, 0xf0, 0x36, 0x5c, 0xd6, 0x57, 0xd5, 0x57, 0x35, 0x5c, 0x0f, 0xf0}

With that out of the way, it's time to actually render the newly imported sprite.

Rendering a PNG File#

Rendering the sprite is rather simple. Just call the Blit function of w4:

// Blit draws a sprite at position X, Y and uses DRAW_COLORS accordinglyfunc Blit(sprite *byte, x, y int, width, height, flags uint)

In practice it looks like this:

//go:export updatefunc update() {    frameCount++
    input()
    if frameCount%15 == 0 {        snake.Update()    }
    snake.Draw()
    w4.Blit(&fruitSprite[0], fruit.X*8, fruit.Y*8, 8, 8, w4.BLIT_2BPP)}

But since you set the drawing colors, you need to change the drawing colors too:

    snake.Draw()
    *w4.DRAW_COLORS = 0x4320    w4.Blit(&fruitSprite[0], fruit.X*8, fruit.Y*8, 8, 8, w4.BLIT_2BPP)

This way, w4 uses the color palette in its default configuration. Except for one thing: The background will be transparent.