JavaScript from scratch! Part 3
Tags: javascript, tutorial
Published: 2021-01-26 14:18:46

So are we there yet? Nоt уеt, but І bеt it'ѕ а јоurnеу уоu wоn't fоrgеt... ~~Yeah I like this song.~~ But no, we aren't finished yet, do you remember our list?

1. Variables for config (snake data, fruit data)
2. Interval running for canvas rendering
  0. Snake
  1. Moving
  2. Fruit generation
  3. Eating a fruit
  4. Tail expansion
3. Game end, current score

We finished already 1, 2.0, and 2.1. It wasn't that hard, right? Let's move on!

#Math.random() - Pseudorandom numbers.

So yeah, we will use the `Math.random()` function to generate numbers. Awesome, right? Use this [portal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) to teleport to MDN. Let's make another function! But wait, we need to make sure that we can store that fruit!

```js
//Update data variable on top
let data = {
    user: {
        x: 0,
        y: 0,
        direction: 2
    },
    state: 0,
    fruits: {
        max: 1,
        positions: []
    }
}
```

Okay, so we can now store fruit data! We are adding `fruits` property, in fruits we have two more things. Max is a variable that stores a maximal number of fruits in our game, `positions` is an [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). So let's add a function to actually generate those bad bois, I mean fruits...

```js
//At the end
function spawnFruits() {
    while (data.fruits.max > data.fruits.positions.length) {
        let x = Math.floor(Math.random() * 30)
        let y = Math.floor(Math.random() * 15)

        if (x == data.user.x && y == data.user.y) continue;

        data.fruits.positions.push({ x, y })
    }
}

function renderFruits(ctx) {
    data.fruits.positions.forEach(elt => {
        let x = elt.x;
        let y = elt.y;
    
        ctx.fillStyle = 'red';
        ctx.fillRect(x * 10, y * 10, 10, 10);
    })
}
```

We add these two new functions. Let's explain some of the hackish like solutions. In the first function, we use the `while` loop to execute code when the expression in `()` is true. So we check if the max value is larger than the `positions` array length. But wait what is this magical `length` at the end? Let me explain!

```js
let x = [];

console.log(x.length, x) // 0 []

x.push(2) //We add new element to the Array

console.log(x.length, x) // 1 [2]
```

So using `data.fruits.positions.length` we access a length of the positions array. Moving on. We then generate a random number. Since `Math.random()` returns a floating-point number from 0 to 1. So it can return 0.12334567573412 and 0.956463524353 we then multiply it by the max value of our canvas. Since one square is 10x10 pixels. The height of our canvas is 300 in CSS but HTML divided it by 2, so it's actually 150. So 150 divided by 10 is 15, that's our height max value. We cut the floating-point using `Math.floor` to get an integer. Cause if we won't do it, our Snake won't eat the fruits and could miss it by 0.0000000000000001.

See that `continue` thing? It's part of a loop. So what it does? It means to just ignore the code below and continue with loop execution. After that, if a position doesn't match with the user position we add a new element to an array.

The next function renders our fruits. The `forEach` property expects us to provide it with a function. We use the arrow function to create that. An arrow function is a very useful thing, but you can read about it [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), cause I don't want to explain it. You'll be pretty much confused if I do that, so I'll leave it to MDN experts.

```js
//Updating our interval function
    setInterval(function () {
        spawnFruits();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawSnake(ctx);
        renderFruits(ctx);
        moveSnake();
    }, 500)
```

And that's all, as you can see on our page there is a red square inside of our canvas, it also renders on another place when you reload a page! Should we add a snake controlling option? YEZ! Let's get to it right away.

```js
//After window.onload
window.onkeydown = function (event) {
    switch (event.key) {
        case "ArrowLeft":
            data.user.direction = 0;
            break;
        case "ArrowUp":
            data.user.direction = 3;
            break;
        case "ArrowRight":
            data.user.direction = 2;
            break;
        case "ArrowDown":
            data.user.direction = 1;
            break;
    }
}
```

So now, every time a user presses one of the 4 arrow keys, the snake will change its direction.

That's all for this post. Next time we will finish our snake game. Stay tuned for more!