You are viewing our Forum Archives. To view or take place in current topics click here.
[JAVASCRIPT] Snake Game - Prototype
Posted:

[JAVASCRIPT] Snake Game - PrototypePosted:

Bighair
  • Powerhouse
Status: Offline
Joined: Sep 26, 201013Year Member
Posts: 401
Reputation Power: 17
Status: Offline
Joined: Sep 26, 201013Year Member
Posts: 401
Reputation Power: 17
Hey guys!

Over the last few days I've thrown together a basic prototype of the game snake. I plan on cleaning up the code and adding to this over the next week or two...

Feed back would be great.

TODO LIST

    Rewrite code in jquery & tidy up the code.
    Implement special foods(Diet Pill(loose x amount of blocks),special food(Extra Score), Clock Slows game down by 1/4 for x amount of time)
    Implement Mazes
    Implement a challenge based game mode(get a score of 100 in each maze without dieing)
    Redesign the graphics so the game is bigger and better looking.
    Implement Local High-scores & potentially global high-scores
    Make the game compatible with mobile devices using jquery mobile


This is just the first version. It will be improved.

Each time you eat food the game will speed up by 0.9 fps & score is worked out by the fps

Feedback would be great

Remove spaces in the link TTG wont allow me to put direct link

www . fullonhorsefollio. 16mb. com/ Snake%20Game%20-%20Prototype/snake.html

P.S this is my first ever loop based game & was not made using a tutorial!

The following 1 user thanked Bighair for this useful post:

Skittle (06-12-2015)
#2. Posted:
tyfgyl
  • Resident Elite
Status: Offline
Joined: Jun 07, 201212Year Member
Posts: 263
Reputation Power: 10
Status: Offline
Joined: Jun 07, 201212Year Member
Posts: 263
Reputation Power: 10
Source for anyone who wants it ;)

/**
* Created by Adam on 29/05/2015.
*/


//Extends the canvas class to add a method that draws a rotated image.
CanvasRenderingContext2D.prototype.drawRotatedImage = function(image,angle,x,y){
    function angleToRadians (){
        return angle * (Math.PI/180);
    }

    this.save();
    this.translate(x + (image.width/2), y + (image.height/2) );
    this.rotate(angleToRadians());
    this.drawImage(image, -(image.width/2), -(image.height/2));
    this.restore();
};

var Color = {
    Sand:"#FFD685",
    Black:"#000000",
    white:"#ffffff"
};

var VALID_KEYS = {
    LEFT_KEY: 37,
    UP_KEY: 38,
    RIGHT_KEY: 39,
    DOWN_KEY: 40
};


/*
    Variables for the the game
 */

var canvas;
var ctx;
var canvasDimensions;
var gameBoardDimensions;
var statBoardDimension;
var gameImages;
var buttonImages;
var buttons;
var gameState = "loading";
var timer;
var isGameOver;
var fps = 8;
var newDirection;
var snakeDirection;
var snake;
var snakeToGrow;
var food;
var score;

/*
    BUTTON OBJECT
 */
var Button = function (imgNormal,imgHover,x,y) {
    this.imageNormal = imgNormal;
    this.imageHover = imgHover;
    this.x = x;
    this.y=y;
    this.bottom = y + imgHover.height;
    this.right = x + imgHover.width;
};

Button.prototype.isClicked = function(x,y){
    if((this.right>x && this.x<x) && (this.bottom>y && this.y<y)){
        return true;
    }else{
        return false;
    }
};

Button.prototype.isHover = function(x,y){
    return this.isClicked(x,y);
};

Button.prototype.drawHover = function(){
    ctx.drawImage(this.imageHover,this.x,this.y);
};

Button.prototype.drawNormal = function () {
    ctx.drawImage(this.imageNormal,this.x,this.y);
};

/*
FOOD OBJ
 */
var Food = function (img,x,y) {
    this.img = img;
    this.x = x;
    this.y = y;

};

Food.prototype.draw = function(){
    ctx.drawImage(this.img,this.x,this.y);
};

/*
    SNAKE BLOCK OBJ
 */
var SnakeBlock = function (img,x,y) {
    this.img = img;
    this.x = x;
    this.y = y;
    this.bottom = y+img.height;
    this.right = x+img.width;
};

SnakeBlock.prototype.switchImageToBody = function(){
    this.img = gameImages.snakeBody;
};

SnakeBlock.prototype.draw = function(direction){
    if(this.img == gameImages.snakeHead){
        var degrees;
        switch(direction){
            case "right":degrees = 90;break;
            case "down": degrees = 180;break;
            case "left":degrees = 270;break;
            case "up":degrees=0;break;
        }
        ctx.drawRotatedImage(this.img,degrees,this.x,this.y);
    }else{
        ctx.drawImage(this.img,this.x,this.y);
    }
};

/*
SNAKE OBJ
 */
var Snake = function(){
    this.headX  = gameBoardDimensions.height/2;
    this.headY = gameBoardDimensions.width/2;
    this.length = 5;
    this.blocks = [];

    var x = this.headX - 10;

    this.blocks[0] = new SnakeBlock(gameImages.snakeHead,this.headX,this.headY);
    for(var i = 1; i<this.length;i++){
        this.blocks[i] = new SnakeBlock(gameImages.snakeBody,x,this.headY);
        this.blocks[i].switchImageToBody();
        x-=10;
    }


    function getInput (e) {
        switch(e.keyCode){
            case  VALID_KEYS.LEFT_KEY: newDirection = "left";break;
            case  VALID_KEYS.DOWN_KEY: newDirection = "down";break;
            case VALID_KEYS.RIGHT_KEY: newDirection = "right";break;
            case  VALID_KEYS.UP_KEY: newDirection = "up";break;
        }

        if((newDirection == "right" && snakeDirection == "left") ||
            (newDirection == "left" && snakeDirection == "right")||
            (newDirection == "up" && snakeDirection=="down")||
            (newDirection=="down" && snakeDirection=="up")){
            newDirection = snakeDirection;
            console.log("invalid init?")
        }
    }
    document.onkeydown = getInput;
};

Snake.prototype.draw = function(){
    for(var i = 0;i<this.blocks.length;i++){
        this.blocks[i].draw(snakeDirection);
    }
};

Snake.prototype.update = function () {
    snakeDirection = newDirection;
    switch(snakeDirection){
        case "right":this.headX+=10;break;
        case "left":this.headX-=10;break;
        case "up":this.headY-=10;break;
        case "down":this.headY+=10;break;
    }

    var newHead = new SnakeBlock(gameImages.snakeHead,this.headX,this.headY);
    var lastBlock = this.blocks[this.blocks.length-1];
    this.blocks[0].switchImageToBody();
    for (var i = this.blocks.length - 1; i > 0; i--) {
        this.blocks[i] = this.blocks[i - 1];
    }
    this.blocks[i] = newHead;
    if(snakeToGrow){
        this.blocks.push(lastBlock);
        console.log(this.blocks.length);
    }
};


Snake.prototype.isBlocksColliding = function () {
    var collision = false;
    for(var i=2;i<this.blocks.length;i++){
        if((this.blocks[0].x == this.blocks[i].x )&&
            (this.blocks[0].y == this.blocks[i].y)){
            collision=true;
        }
    }
    return collision;
};

Snake.prototype.isCollidingWithBorder = function () {
    if(this.headX < gameBoardDimensions.left || this.headX == gameBoardDimensions.width ||
        this.headY<gameBoardDimensions.top || this.headY==gameBoardDimensions.height){
        return true;
    }
};

Snake.prototype.isHeadCollidingWithFood = function () {
    if(this.headX == food.x && this.headY == food.y){
        return true;
    }
    return false;
};

Snake.prototype.isCollidingWithNewFood = function(x,y){
    var isColliding = false;
    for(var i = 0;i<this.blocks.length;i++){
        if(this.blocks[i].x == x || this.blocks[i].y == y){
            isColliding = true;
        }
    }
    return isColliding;
};


//Functions for menus and organising of the game

function initButtons(){
    window.clearTimeout(timer);
    var startX = (canvasDimensions.width/2) - (buttonImages.aboutHover.width/2);
    var startY = (canvasDimensions.height/2)  -20 - buttonImages.startHover.height;
    var aboutY = (canvasDimensions.height/2) + 20;

    buttons = {
        start: new Button(buttonImages.startNormal,buttonImages.startHover,startX,startY),
        restart: new Button(buttonImages.restartNormal,buttonImages.restartHover,startX,startY),
        about: new Button(buttonImages.aboutNormal,buttonImages.aboutHover,startX,aboutY)
    };

    drawMenu("startMenu");
}

/*
    DRAW FUNCTIONS
 */

function clearCanvas(){
    ctx.clearRect(canvasDimensions.left,canvasDimensions.top,canvasDimensions.width,canvasDimensions.height);
}   //Clears the canvas ready for redraw.

function drawLoadingScreen(){
    clearCanvas();
    ctx.fillStyle = Color.Sand;
    ctx.fillRect(canvasDimensions.left,canvasDimensions.top,canvasDimensions.width,canvasDimensions.height);
    ctx.fillStyle = Color.Black;
    ctx.font = "18px serif";
    ctx.fillText("Game Loading....",90,150);
    ctx.rect(canvasDimensions.left,canvasDimensions.top,canvasDimensions.width,canvasDimensions.height);
    ctx.stroke();
}

function drawMenu(GameState){
    gameState = GameState;
    clearCanvas();
    ctx.fillStyle = Color.Sand;
    ctx.fillRect(canvasDimensions.left,canvasDimensions.top,canvasDimensions.width,canvasDimensions.height);
    ctx.fillStyle = Color.Black;
    ctx.rect(canvasDimensions.left,canvasDimensions.top,canvasDimensions.width,canvasDimensions.height);
    ctx.stroke();

    if(gameState =="startMenu"){
        buttons.start.drawNormal()
    }else{
        buttons.restart.drawNormal()
    }
    buttons.about.drawNormal();
}


//Game handling code

function generateFood(){
    var x,y;
    do {
        x = Math.floor(Math.random() * (gameBoardDimensions.left - (gameBoardDimensions.width - 10) + 1)) + gameBoardDimensions.width - 10;
        y = Math.floor(Math.random() * (gameBoardDimensions.top - (gameBoardDimensions.height - 10) + 1)) + gameBoardDimensions.height - 10;;
        x = Math.round(x / 10) * 10;
        y = Math.round(y / 10) * 10;
    }while(snake.isCollidingWithNewFood(x,y));

    return new Food(gameImages.apple,x,y)
}

function gameOver(){
    alert("Game Over! Your score was " + score);
    gameState = "restartMenu";
    drawMenu(gameState);
    location.reload();
}

function detectCollision(){
    if(snake.isBlocksColliding() || snake.isCollidingWithBorder() ){
        isGameOver=true;

    }
    if(snake.isHeadCollidingWithFood()){
        snakeToGrow=true;
        food = generateFood();
        score+=Math.round(fps);
        fps+=0.09;
    }
}

function update(){
    snake.update();
    snakeToGrow = false;
}

function draw(){
    clearCanvas();
    ctx.fillStyle=Color.Sand;
    ctx.fillRect(gameBoardDimensions.left,gameBoardDimensions.top,gameBoardDimensions.width,gameBoardDimensions.height);
    ctx.fillStyle=Color.Black;
    ctx.rect(gameBoardDimensions.left,gameBoardDimensions.top,gameBoardDimensions.width,gameBoardDimensions.height);
    ctx.fillRect(statBoardDimension.left,statBoardDimension.top,statBoardDimension.width,statBoardDimension.height);
    ctx.stroke();
    ctx.fillStyle = Color.white;
    ctx.font = "16px sans-serif";
    ctx.fillText("Score = " + score,statBoardDimension.left+2,statBoardDimension.height + 16);
    snake.draw();
    food.draw();
}

function gameLoop(){
    update();
    detectCollision();
    if(isGameOver == true){
        clearTimeout(timer);
        gameOver();
    }else{
        draw();
        timer = window.setTimeout(gameLoop,1000/fps)
    }
}


function initGame(){
    gameState = "running";
    snakeDirection = "right";
    newDirection = "right";
    snakeToGrow = false;
    snake = new Snake();
    food = generateFood();
    score = 0;
    gameLoop();
}


//Event Handlers

function mouseClick(event){
    //This code is taken from a stack overflow article.
    var x,
        y;
    if (event.x != undefined && event.y != undefined) {
        x = event.x;
        y = event.y;
    } else {
        x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;
    x = x - window.pageXOffset;
    y = y - window.pageYOffset;
    //End of code taken.

    if (gameState == "startMenu" || gameState == "restartMenu") {
        if(gameState == "startMenu"){
            if(buttons.start.isClicked(x, y)){
                initGame()
            }else if(buttons.about.isClicked(x, y)){
                buttons.about.drawHover();
            }
        }else if(gameState=="restartGame"){
            if(buttons.restart.isClicked(x, y)){
                initGame();
            }else if(buttons.about.isClicked(x, y)){
                buttons.about.drawHover();
            }
        }
    }
}

function mouseOver(event) {
    //This code is taken from a stack overflow article.
    var x,
        y;
    if (event.x != undefined && event.y != undefined) {
        x = event.x;
        y = event.y;
    } else {
        x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;
    x = x - window.pageXOffset;
    y = y - window.pageYOffset;
    //End of code taken.

    if (gameState == "startMenu" || gameState == "restartMenu") {
        if(gameState == "startMenu"){
            if(buttons.start.isHover(x, y)){
                buttons.start.drawHover()
            }else if(buttons.about.isHover(x, y)){
                buttons.about.drawHover();
            }else{drawMenu("startMenu")}
        }else if(gameState=="restartGame"){
            if(buttons.restart.isHover(x, y)){
                buttons.restart.drawHover();
            }else if(buttons.about.isHover(x, y)){
                buttons.about.drawHover();
            }else{drawMenu("startMenu")}
        }
    }
}

    window.onload = function () {
        canvas = document.getElementById("game");
        ctx = canvas.getContext("2d");

        canvasDimensions = {
            top: 0,
            left: 0,
            height: canvas.height,
            width: canvas.width
        };
        gameBoardDimensions = {
            top: 0,
            left: 0,
            height: canvas.height - 20,
            width: canvas.width
        };
        statBoardDimension = {
            top: gameBoardDimensions.height,
            left: 0,
            height: canvas.height - 20,
            width: canvas.width
        };
        gameImages = {
            snakeHead: new Image(),
            snakeBody: new Image(),
            apple: new Image()
        };
        buttonImages = {
            startNormal: new Image(),
            startHover: new Image(),
            restartNormal: new Image(),
            restartHover: new Image(),
            aboutNormal: new Image(),
            aboutHover: new Image()
        };

        //Load in the game images
        gameImages.snakeHead.src = "img/snakeHead.png";
        gameImages.snakeBody.src = "img/snakeBody.png";
        gameImages.apple.src = "img/apple.png";

        //Load in the button images
        buttonImages.startNormal.src = "img/startGameNormal.png";
        buttonImages.startHover.src = "img/startGameHover.png";
        buttonImages.restartNormal.src = "img/restartGameNormal.png";
        buttonImages.restartHover.src = "img/restartGameHover.png";
        buttonImages.aboutNormal.src = "img/aboutNormal.png";
        buttonImages.aboutHover.src = "img/aboutHover.png";

        //Add events to the canvas.
        canvas.addEventListener("mousemove", mouseOver, false);
        canvas.addEventListener("mousedown",mouseClick,false);

        drawLoadingScreen();
        timer = window.setTimeout(initButtons, 2000);
};
Jump to:
You are viewing our Forum Archives. To view or take place in current topics click here.