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 thoughts on “Snake Game – HTML5 Game Programming Tutorial [javascript]

  • November 12, 2017 at 00:11
    Permalink

    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>

  • November 12, 2017 at 00:11
    Permalink

    <!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>

  • November 12, 2017 at 00:11
    Permalink

    if ranked from beginner, intermediate, advanced, expert … what category of developer would you expect to be able to write this kind of program?

  • November 12, 2017 at 00:11
    Permalink

    .push({x:x, y:y});
    why not use .push(x,y);
    .js Arrays confuse me when both Object & Array methods can be used

  • November 12, 2017 at 00:11
    Permalink

    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.

  • November 12, 2017 at 00:11
    Permalink

    Have got stuck at the first point u display the .html file. Error reads: cannot read property "appendChild" of null. Have done everything exactly up to 15:28 as far as I know

  • November 12, 2017 at 00:11
    Permalink

    Yea he's fast, but he provides the code and you can play around with it. I think this is good compared to what ive found lol

  • November 12, 2017 at 00:11
    Permalink

    what color scheme are you using? and when I save and open it in Google Chrome the screen is just a blank white screen! please help me

Leave a Reply