{lang: ‘ru’}

уроки html5, html5 canvas, html5 примеры, html5 игрыМы продолжаем серию статей о создании игр в HTML5  с использованием canvas. И в этот раз, в качестве примера, будет более-менее полноценная игра  — мы будем делать аналог старой приставочной игры — Battle City. Я научу вас использовать массивы в виде игровой карты, плюс я покажу — как обнаружить столкновение движущегося объекта (в данном случае это танк) с окружающей средой (объекты на карте).

Demo  Исходники

 

 Шаг 1. HTML

index.html

<!DOCTYPE html>
<html lang="ru" >
    <head>
        <meta charset="utf-8" />
        <title>Разработка игр на HTML5 — Урок 6 | biznistim.net</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 — Урок 6</h2>
            <a href="http://biznistim.net/?p=1769" class="stuts">Вернуться обратно на <span>biznistim.net</span></a>
        </header>

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

Шаг 2. CSS

css/main.css

В этот раз CSS стили не публикую, так как там только разметка страницы. Файл стилей доступен в исходниках.

Шаг 3. JS

js/jquery-1.5.2.min.js

Как и в прошлые разы мы используем jQuery. Следующий файл содержит основной функционал:

js/script.js

// внутренние переменные
var canvas, context;
var imgBrick, imgSteel, imgWater, imgForest, imgTank; // изображения
var aMap; // массив карта
var oTank; // объект танк

var iCellSize = 24; // ширина клетки
var iXCnt = 26; // количество клеток X
var iYCnt = 26; // количество клеток Y

// объекты :
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;
}

// функции
function clear() { // функция очистки canvas
    context.clearRect(0, 0, canvas.width, canvas.height);
}

function drawScene() { // функция отрисовки сцены
    clear(); // очистить canvas

    // заполнить фон
    context.fillStyle = '#111';
    context.fillRect(0, 0, canvas.width, canvas.height);

    // сохранить текущее положение
    context.save();

    // обход нашего массива
    for (var y = 0; y < iYCnt; y++) {
        for (var x = 0; x < iXCnt; x++) {
            switch (aMap[y][x]) {
                case 0: // пропуск
                    break;
                case 1: // рисуем кирпичный блок
                    context.drawImage(imgBrick, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 2: // рисуем стальной блок
                    context.drawImage(imgSteel, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 3: // рисуем блок леса
                    context.drawImage(imgForest, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
                case 4: // рисуем водяной блок
                    context.drawImage(imgWater, 0, 0, iCellSize, iCellSize, x*iCellSize, y*iCellSize, iCellSize, iCellSize);
                    break;
            }
        }
    }

    // восстановление текущего положения
    context.restore();

    // рисуем танк
    context.drawImage(oTank.image, oTank.i*oTank.w, 0, oTank.w, oTank.h, oTank.x, oTank.y, oTank.w, oTank.h);
}
// -------------------------------------------------------------

// инициализация
$(function(){
    canvas = document.getElementById('scene');
    canvas.width  = iXCnt * iCellSize;
    canvas.height = iYCnt * iCellSize;
    context = canvas.getContext('2d');

    // массив - карта
    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]
    ]);

    // загружаем изображения
    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){ // обработчики нажатия клавиш клавиатуры
        switch (event.keyCode) {
            case 38: // клавиша вверх
                oTank.i = 2;

                // проверка столкновений
                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: // клавиша вниз
                oTank.i = 3;

                // проверка столкновений
                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: // клавиша влево
                oTank.i = 1;

                // проверка столкновений
                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: // клавиша вправо
                oTank.i = 0;

                // проверка столкновений
                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); // отрисовка сцены
});

В коде я оставил комментарии, чтобы было понятнее.


Demo Исходники

 
 


 Итог

Сегодня мы сделали основу HTML5 игры — BattleCity. Я буду рад если Вы поделитесь ссылкой на этот урок со своими друзьями и оставите комментарии. Удачи!
 


Получайте новые статьи блога прямо себе на почту