HTML 5 Разработка игр - Урок 4


Оригинал статьи

Сегодня мы продолжаем серию статьей о создании игры в HTML 5 с использованием canvas. Сегодня мы будем изучать следующие элементы: анимацию спрайтов и работа со звуком. В нашей демо вы уведите летящего дракона. Мы постоянно будем слышать звук крыльев (мы зациклим этот звук), а другой звук - рев дракона (мы услышим по событию MouseUp). И наконец мы научим дракона подлетать к мыши (при нажатой кнопки мыши).

Предыдущую статью вы можете прочитать здесь Урок -3.

Новый скрипт является развитием предыдущей версии.

Вот демо и архив.

Демо

download in package

Ок - загрузите файлы примеров и начинайте программировать.

Шаг 1. HTML

Ниже представлен HTML код примера.

index.html

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <title>HTML5 Game Development - Lesson 4 | Script Tutorials</title>

 

 

        <link href="css/main.css" rel="stylesheet" type="text/css" />

 

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script type="text/javascript" src="js/script.js"></script>
    </head>
    <body>
        <div class="container">
            <canvas id="scene" width="1000" height="600"></canvas>
        </div>

 

        <footer>
            <h2>HTML5 Game Development - Lesson 4</h2>
            <a href="http://www.script-tutorials.com/html5-game-development-lesson-4/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
        </footer>
    </body>
</html>

Шаг 2.CSS

Ниже CSS стили использованные в примере.

CSS / main.css

Сегодня я не буду публиковать стили - это всего лишь страница со стилями, ничего особенного.
Присутствует в архиве.

Шаг 3. JS

JS / script.js

// inner variables
var canvas, ctx;
var backgroundImage;
var iBgShiftX = 100;
var dragon;
var dragonW = 75; // dragon width
var dragonH = 70; // dragon height
var iSprPos = 0; // initial sprite frame
var iSprDir = 4; // initial dragon direction
var dragonSound; // dragon sound
var wingsSound; // wings sound
var bMouseDown = false; // mouse down state
var iLastMouseX = 0;
var iLastMouseY = 0;
// -------------------------------------------------------------

 

 

// objects :
function Dragon(x, y, w, h, image) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.image = image;
    this.bDrag = false;
}
// -------------------------------------------------------------

 

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

 

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

 

    // draw background
    iBgShiftX -= 4;
    if (iBgShiftX <= 0) {
        iBgShiftX = 1045;
    }
    ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600);

 

    // update sprite positions
    iSprPos++;
    if (iSprPos >= 9) {
        iSprPos = 0;
    }

 

    // in case of mouse down - move dragon more close to our mouse
    if (bMouseDown) {
        if (iLastMouseX > dragon.x) {
            dragon.x += 5;
        }
        if (iLastMouseY > dragon.y) {
            dragon.y += 5;
        }
        if (iLastMouseX < dragon.x) {
            dragon.x -= 5;
        }
        if (iLastMouseY < dragon.y) {
            dragon.y -= 5;
        }
    }

 

    // draw dragon
    ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);
}

 

// -------------------------------------------------------------

 

// initialization
$(function(){
    canvas = document.getElementById('scene');
    ctx = canvas.getContext('2d');

 

    var width = canvas.width;
    var height = canvas.height;

 

    // load background image
    backgroundImage = new Image();
    backgroundImage.src = 'images/hell.jpg';
    backgroundImage.onload = function() {
    }
    backgroundImage.onerror = function() {
        console.log('Error loading the background image.');
    }

 

    // 'Dragon' music init
    dragonSound = new Audio('media/dragon.wav');
    dragonSound.volume = 0.9;

 

    // 'Wings' music init
    wingsSound = new Audio('media/wings.wav');
    wingsSound.volume = 0.9;
    wingsSound.addEventListener('ended', function() { // looping wings sound
        this.currentTime = 0;
        this.play();
    }, false);
    wingsSound.play();

 

    // initialization of dragon
    var oDragonImage = new Image();
    oDragonImage.src = 'images/dragon.gif';
    oDragonImage.onload = function() {
    }
    dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage);

 

    $('#scene').mousedown(function(e) { // binding mousedown event (for dragging)
        var mouseX = e.layerX || 0;
        var mouseY = e.layerY || 0;
        if(e.originalEvent.layerX) { // changes for jquery 1.7
            mouseX = e.originalEvent.layerX;
            mouseY = e.originalEvent.layerY;
        }

 

        bMouseDown = true;

 

        if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w &&
            mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) {

 

            dragon.bDrag = true;
            dragon.x = mouseX;
            dragon.y = mouseY;
        }
    });

 

    $('#scene').mousemove(function(e) { // binding mousemove event
        var mouseX = e.layerX || 0;
        var mouseY = e.layerY || 0;
        if(e.originalEvent.layerX) { // changes for jquery 1.7
            mouseX = e.originalEvent.layerX;
            mouseY = e.originalEvent.layerY;
        }

 

        // saving last coordinates
        iLastMouseX = mouseX;
        iLastMouseY = mouseY;

 

        // perform dragon dragging
        if (dragon.bDrag) {
            dragon.x = mouseX;
            dragon.y = mouseY;
        }

 

        // change direction of dragon (depends on mouse position)
        if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
            iSprDir = 0;
        } else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
            iSprDir = 4;
        } else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
            iSprDir = 2;
        } else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
            iSprDir = 6;
        } else if (mouseY < dragon.y && mouseX < dragon.x) {
            iSprDir = 5;
        } else if (mouseY < dragon.y && mouseX > dragon.x) {
            iSprDir = 7;
        } else if (mouseY > dragon.y && mouseX < dragon.x) {
            iSprDir = 3;
        } else if (mouseY > dragon.y && mouseX > dragon.x) {
            iSprDir = 1;
        }
    });

 

    $('#scene').mouseup(function(e) { // binding mouseup event
        dragon.bDrag = false;
        bMouseDown = false;

 

        // play dragon sound
        dragonSound.currentTime = 0;
        dragonSound.play();
    });

 

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

Как это работает(вкратце). Во первых мы определяем canvas, контекст, загружаем фоновое изображение, два звука, дальше мы инициализируем дракона и создаем обработчики событий мыши. В основной функции я смещаю фоновое изображение (цикл), а затем обновляю позицию спрайта, и в конце рисую дракона. В нашем коде вы можете найти несколько новых интересных методов.

1. Звуковой фон цикл

// 'Wings' music init
wingsSound = new Audio('media/wings.wav');
wingsSound.volume = 0.9;
wingsSound.addEventListener('ended', function() { // looping wings sound
    this.currentTime = 0;
    this.play();
}, false);
wingsSound.play();

2. Рисование спрайтов

  
var oDragonImage = new Image();
    oDragonImage.src = 'images/dragon.gif';
    oDragonImage.onload = function() {
    }
....
    // update sprite positions
    iSprPos++;
    if (iSprPos >= 9) {
        iSprPos = 0;
    }

 

 

    // draw dragon
    ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);

Таким образом загружаем исходное изображение (с множеством всех суб-изображений), а затем отображаем часть этого изображения, со смещением своей позиции, и делаем это еще раз(цикл).

Шаг 4. Пользовательские файлы

изображения / dragon.gif, изображения / hell.jpg
Все эти файлы, доступные в архиве.

Демо

download in package