Develop a Greedy snake Game In Browser Using Javascript CSS3 and HTML5 Complete Project

Welcome Learner today in this blog post we will be Develop a greedy snake game in Browser With Javascript HTML5 and CSS3. All the Complete source code of the application is shown Down.

 

Greedy Snake Game

 

index.html `

 

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="stylesheets/style.css">
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <!-- latest-->
  <link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet">
  <link href="https://unpkg.com/nes.css@2.3.0/css/nes.min.css" rel="stylesheet">
  <!-- import boostrap-->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
  <style>
    html, body, pre, code, kbd, samp {
    font-family: "Press Start 2P";
    }
  </style>
</head>
<div class="Container d-flex justify-content-center">
  <div class="PlayGround row col-10 col-md-5">
    <div class="nes-container with-title is-centered">
      <div class="d-flex justify-content-between" style="margin:1em"></div>
      <div class="GameBoard">
        <div id="gameResult"></div>
        <div class="alert alert-warning d-none" role="alert"></div>
        <div class="Game" id="game"></div>
      </div>
    </div>
  </div>
</div>

 

 

 

style.css 

 

 

.Container {
    margin-top: 5em;
    height : 80vh; 
    width : 100%;
    justify-content: center;
}
.PlayGround {
    background-color: ghostwhite;
}
.GameBoard {
    position: relative;
    min-height: 80%;
    background-color: gray;
    margin: 1em;
}
.Game {
    position: absolute;
    height: 100%;
    width: 100%;
}
table {
    height: 100%;
    width: 100%;
    background-color: ghostwhite;
}
.table-bordered td {
    border-width : 1px 1px !important;
}

READ Build a 2048 Sliding Block Puzzle Number Game In Browser Using Javascript CSS3 and HTML5 Complete Project For learner

 

script.js 

 

const statics = {
    game : {
        Snake : {
            field_width: 30,
            field_height: 30,
            init_speed: 150,
            init_length: 3,
            accelerate: 2.5,
            point_weight : 5,
            callback : ()=> { $("#gameResult").text('Win!')}
        }       
    }
}
class Game {
    initFields(x, y) {
        // >> Clean game field and init a new one.
        // ---
        // >> ARGUMENTS :
        // x (Integer): width of playground 
        // y (Integer): height of playground
        // ---
        // >> RETURN : null
        let game = document.getElementById('game');
        let gameboard = document.createElement('table');
        for(let i = 0; i < y; i ++) {
            let line = document.createElement('tr');
            for(let j = 0; j < x; j ++) {
                let block = document.createElement('td');
                block.setAttribute('id', i + '_' + j);
                line.appendChild(block);
            } 
            gameboard.append(line);
        } 
        game.appendChild(gameboard);
    }
    initBorder() {
        // >> Optional parent method for adding border.
        // ---
        // >> ARGUMENTS :
        // ---
        // >> RETURN : null
        let game = document.getElementById('game');
        if (game.childElementCount) {
            game.children[0].className += 'table table-bordered';
        }
    }
}
class Snake extends Game {
    constructor(x_length, y_length) {
        // >> Child object of Game, make yourself as long as possible by eating food.
        // ---
        // Arguments : 
        // x_length (Integer): width of this game.
        // y_length (Integer): height of this game.
        // ---
        // RETURN : null
        super(); 
        this.x_length = x_length;
        this.y_length = y_length;
        this.initFields(x_length, y_length);
        this.initBorder()  
        this.speed = statics.game.Snake.init_speed;               // Snake move speed.
        this.snake_length = statics.game.Snake.init_length;          // initial length.
        this.snake_body = Array();      // Queue for each piece position.
        this.food = this.createFood(); 
        this.initSnake();
        this.direction = [0, 1];
        this.speedUp();
        this.callbackEvent()
    }
    getRandomIntInclusive(min, max) {
        // >> Random number method.
        // ---
        // Arguments : 
        // min (Integer): bottom of random.
        // max (Integer): cap of random.
        // ---
        // RETURN : Integer
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1) + min);
    }
    initSnake() {
        // >> Initialize the snake with length on random position.
        // ---
        // Arguments :
        // ---
        // RETURN : null
        let x = this.getRandomIntInclusive(this.snake_body, this.x_length-1);
        let y = this.getRandomIntInclusive(this.snake_body, this.y_length-1);
        for (let i = 0; i < this.snake_length ; i ++ ) {
            let p = [y, x-i];
            this.snake_body.push(p);
        }
        this.fillColor(this.snake_body);
    }
    callbackEvent() {
        // >> Add keyboard event to change head direction.
        // ---
        // Arguments : 
        // ---
        // RETURN : null
        $(document).keydown((e) => {
            let switch_to = null
            switch (e.keyCode) {
                case 37:
                    switch_to = [0, -1];
                    break
                case 39 : 
                    switch_to = [0, 1];
                    break
                case 38 :
                    switch_to = [-1, 0];
                    break
                case 40 :
                    switch_to = [1, 0];
                    break
                default:
                    break;
            }
            if (switch_to) {
                let current = [this.snake_body[0][0] - this.snake_body[1][0], this.snake_body[0][1] - this.snake_body[1][1]]
                let c = switch_to.map((x)=> Math.abs(x));
                if (c[0] != Math.abs(current[0]) || c[1]!= Math.abs(current[1])){
                    this.direction = switch_to;
                }
            }
        }
        )
    }
    fillColor() {
        // >> Update view with latest .snake_body and food.
        // ---
        // Arguments : 
        // ---
        // RETURN : null
        $('td').css({backgroundColor: 'white'});
        this.snake_body.forEach(element => {
            $('#'+element.join('_')).css({backgroundColor: 'black'});
        });
        $('#'+this.food.join('_')).css({backgroundColor: 'red'});
    }
    crossBorder(next) {
        // >> Convert the position when head reaching border.
        // ---
        // Arguments : 
        // next (Integer): head position.
        // ---
        // RETURN : null
        if (next[0] < 0 || next[0] == this.x_length) {
            next[0] = (next[0] + this.x_length)%this.x_length;
        }
        else if (next[1] < 0 || next[1] == this.y_length) {
            next[1] = (next[1] + this.y_length)%this.y_length;
        }
        return next;
    }
    moveForward() {
        // >> unshift next td in direction and pop the last in body, also determine below condition.
        // >> * hit body : will call getResult() to stop the game and calculate points with length.
        // >> * eat food : recover the drop to extend length and reset interval to speed up.
        // ---
        // Arguments : 
        // ---
        // RETURN : null
        let next = [this.snake_body[0][0]+this.direction[0], this.snake_body[0][1]+this.direction[1]];
        next = this.crossBorder(next);
        this.snake_body.unshift(next);
        let drop = this.snake_body.pop();
        let checker = this.snake_body.map((x)=>x.join('_'))
        
        if (new Set(checker).size != checker.length) {

            clearInterval(this.interval);
            // toResult('Win', this.snake_length * statics.game.Snake.point_weight);
            statics.game.Snake.callback();
            
        }
        else if (next.join('_') == this.food.join('_')) {
            this.snake_length += 1;
            this.speed -= statics.game.Snake.accelerate;
            this.speedUp()
            this.snake_body.push(drop);
            this.food = this.createFood();
        }
        this.fillColor();
    }
    speedUp() {
        // >> Reset interval with updated speed.
        // ---
        // Arguments : 
        // ---
        // RETURN : null
        clearInterval(this.interval);
        this.interval = setInterval(() => {
            this.moveForward()
        }, this.speed);
    }
    createFood() {
        // >> Create food in fields randomly.
        // ---
        // Arguments : 
        // ---
        // RETURN : null
        let food = [this.getRandomIntInclusive(0, this.x_length-1), this.getRandomIntInclusive(0, this.y_length-1)];
        while (this.snake_body.map((x)=> x.join('_')).includes(food.join('_'))) {
            food = [this.getRandomIntInclusive(0, this.x_length-1), this.getRandomIntInclusive(0, this.y_length-1)];
        }
        return food;
    }
}

var game = new Snake(15, 15)

Leave a Comment

Your email address will not be published. Required fields are marked *