Snake Game – HTML5 Game Programming Tutorial [javascript]




In this video are we creating a simple game using javascript and html. The tutorial are adapted for both beginners and more intermediate coders who wish to learn how to structure game code, use basic data structors useful for game programming (like graphs, queues and so on), and other type of game programming technics.

:: Annotated Source ::
https://github.com/maxwihlborg/youtube-tutorials/blob/master/snake/index.html

:: KeyNote ::
https://docs.google.com/presentation/d/1GG93LkqZwGY-ag9eedReosYqbA00isVVqvTZic98_QY/edit?usp=sharing

:: Other Stuff ::
https://github.com/maxwihlborg
http://maxwihlborg.com/


Original source


38 responses to “Snake Game – HTML5 Game Programming Tutorial [javascript]”

  1. how to fix the problem of the UP is unidentified in inspect mode please help and the main(); is a error and the init(); is an error too please help!!!!!!!

    <!docktype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Simple Snake Game</title>
    </head>
    <body>
    <script>
    //constant
    var COLS=26, ROWS=26;
    //IDs
    var EMPTY=0, SNAKE=1, FRUIT=2;

    var grid = {

    width: null,
    height: null,
    _grid: null,

    init: function(d, c, r) {
    this.width = c;
    this.height = r;

    this._grid = [];
    for (var x=0; x < c; x++) {
    this._grid.push([]);
    for (var y = 0; y < r; y++) {
    this._grid[x].push(d);
    }
    }
    },

    set: function (val, x, y) {
    this._grid[x][y] = val;
    },

    get: function (x, y) {
    return this._grid[x][y];
    }
    }

    var snake = {

    direction: null,
    last: null,
    _queue: null,

    init: function(d, x, y) {
    this.direction = d;

    this._queue = [];
    this.insert(x, y);
    },

    insert: function(x, y) {
    this._queue.unshift({x:x, y:y})
    this.last = this._queue[0];
    },

    remove: function() {
    return this._queue.pop();
    }
    }

    function setFood() {
    var empty = [];
    for (var x=0; x < grid.width; x++) {
    for (var y=0; y < grid.height; y++) {
    if (grid.get(x, y) === EMPTY) {
    empty.push({x:x, y:y});
    }
    }
    }
    var randpos = empty[Math.floor(Math.random()*empty.length)];
    grid.set(FRUIT, randpos.x, randpos.y);
    }

    // Game Objects
    var canvas, ctx, keystate, frames;

    function main() {
    canvas = document.createElement("canvas");
    canvas.width = COLS+20;
    canvas.height = ROWS+20;
    ctx = canvas.getContext("2d");
    document.body.appendChild(canvas);

    frames = 0;
    keystate = {};

    init();
    loop();
    }

    function init() {
    grid.init(EMPTY, COLS, ROWS);

    var sp = {x:Math.floor(COLS/2), y:ROWS-1};
    snake.init(UP, sp.x, sp.y);
    grid.set(SNAKE, sp.x, sp.y);

    setFood();
    }

    function loop() {
    update();
    draw();

    window.requestAnimationFrame(loop, canvas);
    }

    function update() {
    frames++;
    }

    function draw() {
    var tw = canvas.width/grid.width;
    var th = canvas.height/grid.height;

    for (var x=0; x < grid.width; x++) {
    for (var y=0; x < grid.height; y++) {
    switch (grid.get(x, y)) {
    case EMPTY:
    ctx.fillStyle = "#fff" ;
    break;
    case SNAKE:
    ctx.fillStyle = "#0ff" ;
    break;
    case FRUIT:
    ctx.fillStyle = "#f00" ;
    break;
    }
    ctx.fillRect(x*tw, y*th, tw, th);
    }
    }
    }

    main();
    </script>
    </body>
    </html>

  2. <!doctype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Snake</title>
    </head>
    <body>
    <script>
    //Constants
    var COL=26, ROWS=26;
    // IDs
    var EMPTY=0, SNAKE=1, FRUIT=2;
    // Direction
    var LEFT=0, UP=1, RIGHT=2, DONW=3;

    var grid = {

    width: null,
    heigth: null,
    _grid: null,

    init: function(d, c, r) {
    this.width = c;
    this.width = r;

    this._grid = [];
    for (var x=0; x < c; x++) {
    this._grid.push([]);
    for (var y=0; y < r; y++) {
    this._grid[x].push(d);
    }
    }
    },

    set: function(val, x, y) {
    this._grid[x][y] = val;
    },

    get: function(x,y) {
    return this._grid[x][y];
    }
    }

    var snake = {

    direction: null,
    last: null,
    _queue: null,

    init: function(d, x, y) {
    this.direction = d;

    this._queue = [];
    this.insert(x,y);
    },

    insert: function(x,y) {
    this._queue.unshift({x:x, y:y});
    this.last = this._queue[0];
    },

    remove: function() {
    return this._queue.pop();
    }
    }

    function setFood() {
    var empty = [];
    for (var x=0; x < grid.width; x++) {
    for (var y=0; y < grid.height; y++) {
    if (grid.get(x, y) === EMPTY) {
    empty.push({x:x, y:y});
    }
    }
    }
    var randpos = empty[Math.floor(Math.random()*empty.length)];
    grid.set(FRUIT, randpos.x, randpos.y);
    }

    // Game odjects
    var canvas, ctx, keystate, frames;

    function main () {
    canvas = document.createElement("canvas");
    canvas.width = COLS*20;
    canvas.height = ROWS*20;
    ctx = canvas.getContext("2d");
    document.body.appendChild(canvas);

    frames = 0;
    keystate = {};

    init();
    loop();
    }

    function init() {
    grid.init(EMPTY, COLS, ROWS);

    var sp = {x:Math.floor(COLS/2), y:ROWS-1};
    snake.init(UP, sp.x, sp.y);
    grid.set(SNAKE, sp.x, sp.y);

    setFood();
    }

    function loop() {
    update();
    draw();

    window.requestAnimationFrame(loop, canvas);
    }

    function update() {
    frames++;
    }

    function draw() {
    var tw = canvas.width/grid.width;
    var th = canvas.height/grid.height;

    for (var x=0; x < grid.width; x++) {
    for (var y=0; y < grid.height; y++) {
    switch (grid.get(x, y)) {
    case EMPTY:
    ctx.fillStyle = "#fff";
    break;
    case SNAKE:
    ctx.fillStyle = "#0ff"
    break;
    case FRUIT:
    ctx.fillStyle = "#f00";
    break;
    }
    ctx.fillRect(x*tw, y*th, tw, th);
    }
    }
    }
    }

    main();
    </script>
    </body>
    </html>

  3. Agree Max whipped thru this Video fast .. but .. the code documentation is excellent. Also the program is very well organized into blocks of Objects ( Grid, Snake) and Functions (Food, Main, Init, …). It helped me to prepare a simple Block Diagram explaining what each block does. This also helps in understanding the program flow.

    All the action occurs in the last two Functions Update & Draw ( with calls to Grid & Snake Methods) .. pretty cool.

    I have some other game ideas that are grid based & plan on using Max's code as a starting template.

    Max thanks for the effort.

Leave a Reply