Over a million developers have joined DZone.

HTML5 Game Development – Lesson 6

· Web Dev Zone

Easily build powerful user management, authentication, and authorization into your web and mobile applications. Download this Forrester report on the new landscape of Customer Identity and Access Management, brought to you in partnership with Stormpath.

This is our next game development article. We continue a series of articles on game development in HTML5 using canvas. Today this is a quite complete game example – it will reincarnate an old computer game – Battle City. I will teach you to use alternative array-map, plus I will show you how to detect collisions of an active object (Tank) with the environment (array-based map).

Here you can read our previous lesson: Developing Your First HTML5 Game – Lesson 5.

Here are our demo and downloadable packages:

Live Demo

download in package


Ok, download the example files and let's start coding !


Step 1. HTML

As always – very small HTML markup.

index.html

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <title>HTML5 Game Development - Lesson 6 | Script Tutorials</title>
        <link href="css/main.css" rel="stylesheet" type="text/css" />
        <script src="js/jquery-1.5.2.min.js"></script>
        <script src="js/script.js"></script>
    </head>
    <body>
        <header>
            <h2>HTML5 Game Development - Lesson 6</h2>
            <a href="http://www.script-tutorials.com/html5-game-development-lesson-6/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
        </header>

        <div class="container">
            <canvas id="scene" width="800" height="600"></canvas>
        </div>
    </body>
</html>

Step 2. CSS

css/main.css

I won’t publish CSS styles today; there are only a few page layout styles. You can find this file in our package.

Step 3. JS

js/jquery-1.5.2.min.js

We use jQuery for our lesson. Available in package. This file is the most important (it contains all html5 our functionality):

js/script.js

// inner variables
var canvas, context; // canvas and context objects
var imgBrick, imgSteel, imgWater, imgForest, imgTank; // images
var aMap; // map array
var oTank; // tank object

var iCellSize = 24; // cell wide
var iXCnt = 26; // amount of X cells
var iYCnt = 26; // amount of Y cells

// objects :
function Tank(x, y, w, h, image) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.i = 0;
    this.image = image;
}

// functions
function clear() { // clear canvas function
    context.clearRect(0, 0, canvas.width, canvas.height);
}

function drawScene() { // main drawScene function
    clear(); // clear canvas

    // fill background
    context.fillStyle = '#111';
    context.fillRect(0, 0, canvas.width, canvas.height);

    // save current context
    context.save();

    // walk through our array
    for (var y = 0; y < iYCnt; y++) {
        for (var x = 0; x < iXCnt; x++) {
            switch (aMap[y][x]) {
                case 0: // skip
                    break;
                case 1: // draw brick block
                    context.drawImage(imgBrick, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 2: // draw steel block
                    context.drawImage(imgSteel, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 3: // draw forest block
                    context.drawImage(imgForest, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 4: // draw water block
                    context.drawImage(imgWater, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
            }
        }
    }

    // restore current context
    context.restore();

    // draw tank
    context.drawImage(oTank.image, oTank.i*oTank.w, 0, oTank.w, oTank.h, oTank.x, oTank.y, oTank.w, oTank.h);
}
// -------------------------------------------------------------

// initialization
$(function(){
    canvas = document.getElementById('scene');
    canvas.width  = iXCnt * iCellSize;
    canvas.height = iYCnt * iCellSize;
    context = canvas.getContext('2d');

    // main scene Map array
    aMap = ([
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
      [0, 0, 1, 1, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 1, 1, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 4, 4, 4, 4, 1, 1, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0],
      [0, 0, 0, 0, 4, 4, 4, 4, 1, 1, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 1, 1, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 1, 1, 0, 0, 0, 0],
      [0, 0, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [3, 3, 3, 3, 1, 1, 0, 0, 4, 4, 4, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
      [3, 3, 3, 3, 1, 1, 0, 0, 4, 4, 4, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
      [3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 2, 2],
      [3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 2, 2],
      [0, 0, 1, 1, 4, 4, 4, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 1, 1, 4, 4, 4, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [2, 2, 0, 0, 4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 0, 0, 1, 1, 0, 0],
      [2, 2, 0, 0, 4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 0, 0, 1, 1, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0],
      [0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0],
      [0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0],
      [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 2, 0, 0, 0, 0],
      [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 2, 0, 0, 0, 0]
    ]);

    // load images
    imgBrick = new Image();
    imgBrick.src="images/brick.png";
    imgSteel = new Image();
    imgSteel.src="images/steel.png";
    imgWater = new Image();
    imgWater.src="images/water.png";
    imgForest = new Image();
    imgForest.src="images/forest.png";

    imgTank = new Image();
    imgTank.src="images/tank.png";
    oTank = new Tank(iCellSize*9, iCellSize*24, 48, 48, imgTank);

    $(window).keydown(function(event){ // keyboard alerts
        switch (event.keyCode) {
            case 38: // Up key
                oTank.i = 2;

                // checking collisions
                var iCurCelX = (2 * oTank.x) / 48;
                var iCurCelY = (2 * oTank.y) / 48;
                if (iCurCelY) {
                    var iTest1 = aMap[iCurCelY-1][iCurCelX];
                    var iTest2 = aMap[iCurCelY-1][iCurCelX+1];

                    if ((iTest1 == 0 || iTest1 == 3) && (iTest2 == 0 || iTest2 == 3)) {
                        oTank.y-=24;
                        if (oTank.y < 0) {
                            oTank.y = 0;
                        }
                    }
                }
                break;
            case 40: // Down key
                oTank.i = 3;

                // checking collisions
                var iCurCelX = (2 * oTank.x) / 48;
                var iCurCelY = (2 * oTank.y) / 48;
                if (iCurCelY+2 < iYCnt) {
                    var iTest1 = aMap[iCurCelY+2][iCurCelX];
                    var iTest2 = aMap[iCurCelY+2][iCurCelX+1];

                    if ((iTest1 == 0 || iTest1 == 3) && (iTest2 == 0 || iTest2 == 3)) {
                        oTank.y+=24;
                        if (oTank.y > 576) { //iCellSize * (iYCnt-2)
                            oTank.y = 576;
                        }
                    }
                }
                break;
            case 37: // Left key
                oTank.i = 1;

                // checking collisions
                var iCurCelX = (2 * oTank.x) / 48;
                var iCurCelY = (2 * oTank.y) / 48;
                var iTest1 = aMap[iCurCelY][iCurCelX-1];
                var iTest2 = aMap[iCurCelY+1][iCurCelX-1];

                if ((iTest1 == 0 || iTest1 == 3) && (iTest2 == 0 || iTest2 == 3)) {
                    oTank.x-=24;
                    if (oTank.x < 0) {
                        oTank.x = 0;
                    }
                }
                break;
            case 39: // Right key
                oTank.i = 0;

                // checking collisions
                var iCurCelX = (2 * oTank.x) / 48;
                var iCurCelY = (2 * oTank.y) / 48;
                var iTest1 = aMap[iCurCelY][iCurCelX+2];
                var iTest2 = aMap[iCurCelY+1][iCurCelX+2];

                if ((iTest1 == 0 || iTest1 == 3) && (iTest2 == 0 || iTest2 == 3)) {
                    oTank.x+=24;
                    if (oTank.x > 576) { //iCellSize * (iXCnt-2)
                        oTank.x = 576;
                    }
                }
                break;
        }
    });

    setInterval(drawScene, 40); // loop drawScene
});

I have added my comments everywhere, and hope that all this code is pretty understandable.


Live Demo

download in package


Conclusion

Today, we have made a quite complete HTML5 game – BattleCity. I will be glad to see your thanks and comments. Good luck!

 

Source: http://www.script-tutorials.com/html5-game-development-lesson-6/

The Web Dev Zone is brought to you by Stormpath—offering a complete, pre-built User Management API for building web and mobile applications, and APIs. Download our new whitepaper: "Build Versus Buy: Customer Identity Management for Web and Mobile Applications".

Topics:

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}