DEV Community

ZiomaleQ
ZiomaleQ

Posted on

JavaScript from scratch! Part 3

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
    1. Snake
    2. Moving
    3. Fruit generation
    4. Eating a fruit
    5. 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 to teleport to MDN. Let's make another function! But wait, we need to make sure that we can store that fruit!

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

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. So let's add a function to actually generate those bad bois, I mean fruits...

//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);
    })
}
Enter fullscreen mode Exit fullscreen mode

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!

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]
Enter fullscreen mode Exit fullscreen mode

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, 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.

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

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.

//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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)