Skip to main content

Drawing the Snake

Drawing the Body#

To draw the snake, you can take advantage of AssemblyScripts forEach function. To make it a little easier, it's a good idea to use the rect function of WASM-4:

// rect draws a rectangle. It uses color 1 to fill and color 2 for the outlinefunction rect(x: i32, y: i32, width: u32, height: u32): void;

With that out the way, let's see what a first draft could look like.

draw(): void {    this.body.forEach(part => w4.rect(part.x * 8, part.y * 8, 8, 8))}

Simply loop through the body and draw it at x * 8 and y * 8. 8 is the width and the height of a single part. On a 160x160 screen, it's big enough to fit snake that is 20*20=400 parts long.

Importing w4

Keep in mind you need to import w4 in case your editor doesn't do this for you.

That's all fine, but since there is no instance of the snake, nothing can be drawn. To fix this, simply create a new variable in main and call it's draw function:

import { Point, Snake } from "./snake"import * as w4 from "./wasm4"
const snake = new Snake()
export function start(): void {    store<u32>(w4.PALETTE, 0xfbf7f3, 0 * sizeof<u32>())    store<u32>(w4.PALETTE, 0xe5b083, 1 * sizeof<u32>())    store<u32>(w4.PALETTE, 0x426e5d, 2 * sizeof<u32>())    store<u32>(w4.PALETTE, 0x20283d, 3 * sizeof<u32>())}
export function update(): void {    snake.draw()}

Creating a global instance of a snake with some default values.

After that, simply call the draw function of the snake.

You should see some green blocks at the top.

Snake Body

Drawing the Head#

But where is the head? You can pick a side. Either position [0] or position [this.body.length - 1].

I think it's easier to pick [0].

Since the body is drawn, head is not much of a problem. Simply use the rect function again. But use a specific part instead:

    w4.rect(this.body[0].x * 8, this.body[0].y * 8, 8, 8)

The draw function should now look like this:

draw(): void {    this.body.forEach(part => w4.rect(part.x * 8, part.y * 8, 8, 8))    w4.rect(this.body[0].x * 8, this.body[0].y * 8, 8, 8)}

Notice the difference? Me neither.

The head should stand out a little. For this, you can use a different color:

store<u16>(w4.DRAW_COLORS, 0x0004)

You can set the colors with this variable. You can look at this variable like a table that is read from right to left.

The value for each digit can be 0 up to 4:

  • 0 = Use transparency
  • 1 = Use the 1st color from the color palette
  • 2 = Use the 2nd color from the color palette
  • 3 = Use the 3rd color from the color palette
  • 4 = Use the 4th color from the color palette

The snippet above reads like this: "Color 1 uses Color 4 of the color palette, Color 2 to Color 4 don't use any color." The basic drawing functions use "Color 1" to fill the shape and "Color 2" for the border.

If you change the source to

draw(): void {    this.body.forEach(part => w4.rect(part.x * 8, part.y * 8, 8, 8))
    store<u16>(w4.DRAW_COLORS, 0x0004)    w4.rect(this.body[0].x * 8, this.body[0].y * 8, 8, 8)}

Result:

Changing Color

You'll see a change. The snake changed color. Not only the head, but the complete snake! Once you've set a color, it stays that way. So if you want to change only the head, you have to change Color 1 again. Right before you draw the body.

draw(): void {    store<u16>(w4.DRAW_COLORS, 0x0043)    this.body.forEach(part => w4.rect(part.x * 8, part.y * 8, 8, 8))
    store<u16>(w4.DRAW_COLORS, 0x0004)    w4.rect(this.body[0].x * 8, this.body[0].y * 8, 8, 8)}

This changes the color back and adds the darker green as its outline.

Snake with outline