Skip to content Skip to sidebar Skip to footer

Javascript Canvas Game - How To Know When Object Crosses Its Own Path?

I am new to Javascript. I am trying to make a canvas game similar to Snake, but without the fruits. The game is over if the player crosses his own path. The following is my code.

Solution 1:

Array as a Queue.

The way this game is traditionally done is using a special array type called a queue. Like a real queue you have items added at one end and removed at the other, or first in first out.

Javascript does not have a special array type for a queue but it has all the functions needed to implement a queue.

Push and shift

Array.push(item); // pushes an item onto the top of the arrayArray.shift(); // removes an item from the start of the queue

So for the snake game imagine the head as the end of the queue. Every time it moves one forward you place another item on the queue. At the other end you remove an item if the length of the array is longer than the snake length;

var snake = [];
var snakeLength = 10;
functionsnakeMove(x,y){  // position to move headcheckForHit(x,y); // see below
   snake.push({x:x,y:y}); // put another headpiece on the queueif(snake.length > snakeLength){ // is the length longer than it should be
       snake.shift();    // remove a tail item
   }
}

To draw the snake you just iterate each part drawing it at the X,y position

To test if the snake has run its self over use the following function

function checkForHit(x,y){
    for(var i = 0; i < snake.length; i++){
       if(snake[i].x === x && snake[i].y === y){
           // Snake has hit its self
       }
    }
}

When the snake eats something it traditionally grows in length. this is easily done by simply increasing the length variable. snakeLength += 1 makes the queue longer.

And a demo as i have not played the game in so long why not.

 "use strict";

var score = 0;
var canvas =  document.createElement("canvas");
var scoreE =  document.createElement("div");
scoreE.style.color = "white";
scoreE.style.font = "16px arial";
scoreE.style.position = "absolute";
scoreE.style.top = "10px";
scoreE.style.left = "10px";
scoreE.style.width = "600px";
scoreE.style.textAlign = "center";
scoreE.textContent = "Click canvas area to get focus";
 

canvas.width = 600;
canvas.height = 200;
var ctx  = this.canvas.getContext("2d");
document.body.appendChild(canvas);
document.body.appendChild(scoreE);
var lastKeyDown = 0;
window.addEventListener('keydown', function(e) {
     lastKeyDown = e.keyCode;
     e.preventDefault()
})

var snakePartSize = 8;
var playWidth = canvas.width /snakePartSize;
var playHeight = canvas.height /snakePartSize;
var snake = [];
var snakeLength = 10;
var snakePosX = 0;
var snakePosY = 0;
var snakeDirX = 0;
var snakeDirY = 0;
var snakeSpeed = 16; // number of frame between movesvar gameOver = true;
var instDrawn = false;
var food = [];
var foodFreq = 60; 
var yum = 0;
var yumCol = ["red","orange","yellow"];
 

functionstartSnake(){
    ctx.fillStyle = "black";
    ctx.fillRect(0,0,canvas.width,canvas.height);
    snakePosX = Math.floor(playWidth  / 2);
    snakePosY = Math.floor(playHeight / 2);
    snakeDirX = 0;
    snakeDirY = 0;
    snakeLength = 10;
    snake = [];
    snakeSpeed = 16;
    move(snakePosX,snakePosY); // set first pos
    food = [];
    score = 0;
}
functiontestHit(x,y){
    if(x < 0 || y < 0 || y >= playHeight   || x >= playWidth ){
        returntrue;
    }
    for(var i = 0; i < snake.length; i ++){
        if(snake[i].x === x && snake[i].y === y){
            returntrue;
        }
    }
}
functiontestFood(x,y){
    for(var i = 0; i < food.length; i ++){
        if(food[i].x === x && food[i].y === y){
            food.splice(i,1);
            i --;
            yum = 4;
            score += 100;
            snakeLength += 1;
            if(snakeLength % 4 === 0){
               snakeSpeed -= snakeSpeed > 1 ? 1:0;
            }
        }
    }
}
functionaddFood(){
    var x = Math.floor(Math.random() * playWidth );
    var y = Math.floor(Math.random() * playHeight );
    if(!testHit(x,y)){
       food.push({x:x,y:y});
       drawFood();
    }
} 

functionmove(x,y){
    if(testHit(x,y)){
        gameOver = true;
        return;
    }
    testFood(x,y);
    snake.push({x : x, y : y});
    drawSnakeHead();
    if(snake.length > snakeLength){
        drawSnakeTail();
        snake.shift();
    }
}
functiondrawYum(){
    for(var i = 0; i < snake.length; i ++){
        ctx.fillStyle = yumCol[yum];
        ctx.fillRect(snake[i].x*snakePartSize, snake[i].y*snakePartSize, snakePartSize, snakePartSize);
    }

}

functiondrawFood(){
    var f = food[food.length-1];
    ctx.fillStyle = "green";
    ctx.fillRect(f.x*snakePartSize, f.y*snakePartSize, snakePartSize, snakePartSize);
    
}
functiondrawSnakeHead(){
    var head = snake[snake.length-1];
    ctx.fillStyle = "red";
    ctx.fillRect(head.x*snakePartSize, head.y*snakePartSize, snakePartSize, snakePartSize);
    
}
functiondrawSnakeTail(){
    var head = snake[0];
    ctx.fillStyle = "black";
    ctx.fillRect(head.x*snakePartSize, head.y*snakePartSize, snakePartSize, snakePartSize);
    
}



var counter = 0;
functionupdate(){
    counter += 1;
    if(!gameOver){
        
        if(snakeDirX === 0){ 
            if(lastKeyDown === 37){   // left
                snakeDirX = -1;
                snakeDirY = 0;
            }
            if(lastKeyDown === 39){ // right
                snakeDirX = 1;
                snakeDirY = 0;
            }
        }
        if(snakeDirY === 0){ 
            if(lastKeyDown === 38){   // up
                snakeDirY = -1;
                snakeDirX = 0;
           }
           if(lastKeyDown === 40){ // down
                snakeDirY = 1;
                snakeDirX = 0;
           }
        }
        lastKeyDown = 0;
      
        if(counter % foodFreq ===0){
            addFood();
        }
        if(counter % snakeSpeed === 0){
            snakePosX += snakeDirX;
            snakePosY += snakeDirY;      
            score += 1;  
            move(snakePosX ,snakePosY);        
        }
        if((counter % 2 === 0) && yum > 0){
            yum -= 1;
            drawYum();

        }
        scoreE.textContent = "Score : "+ score;


    }
    if(gameOver){
        if(!instDrawn){
            instDrawn = true;
            ctx.fillStyle = "white";
            ctx.font = "32px arial";
            ctx.textAlign = "center";
            ctx.fillText("GAME OVER",canvas.width /2, canvas.height /2);
            ctx.font = "16px arial";
            ctx.fillText("Press a direction key to start.",canvas.width /2, canvas.height /2+32);
        }
        if(lastKeyDown >= 37 && lastKeyDown <= 40){
            gameOver = false;
            instDrawn = false;
            counter = -1;
            startSnake();

        }
    }
    
    
    
    requestAnimationFrame(update);
}
requestAnimationFrame(update);
startSnake();

Post a Comment for "Javascript Canvas Game - How To Know When Object Crosses Its Own Path?"