Анімація, розваги. Організація віртуального світу аркадної гри.

Фронтенд розробка JavaScript. -> Організація віртуального світу аркадної гри.

Аркадна гра.

start page

[посилання на репозиторій] (https://github.com/zdimon/simple-arcade)

Пересування об’єкта по горизонталі.

Завдання: переміщати внутрішній блок відносного зовнішнього горизонталі нескінченно взад-вперед.

Рішення.

Визначимо 2 блоки на сторінці.

<div class="out">
  <div class="in" id="ball">

  </div>
</div>

Стилі.

.out {
    width: 200px;
    height: 200px;
    position: relative;
    border: 1px solid silver;
}

.in {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: red;
    position: absolute;
}

Визначимо нескінченний таймер.

var timerFunc = function() {
    console.log($.now());
    id = setTimeout(timerFunc, 1000);
}

var id = setTimeout(timerFunc, 1000);

Визначимо об’єкт кульки з елементом та напрямок руху.

$( document ).ready(() => {


    var ball = {
        el: $('#ball'),
        move: 'right'
    };

    var timerFunc = function() {
        id = setTimeout(timerFunc, 1000);
        ball.el.css({'left' : parseInt(ball.el.position().left+5) + 'px'});
    }

    var id = setTimeout(timerFunc, 1000);

    }
);

Відпрацюємо два напрямки руху.

var timerFunc = function() {
    id = setTimeout(timerFunc, 100);
    if(ball.move === 'right') {
        var newCoord =  parseInt(ball.el.position().left+5);
    } else {
        var newCoord =  parseInt(ball.el.position().left-5);
    }
    ball.el.css({'left' : newCoord + 'px'});

    if (newCoord>200) {
        ball.move = 'left';
    }

    if (newCoord<0) {
        ball.move = 'right'
    }
}

Проблема виникне, коли у нас буде багато об’єктів, при такому підході ми будемо змушені для кожного встановлювати свій таймер і коли їх стане багато, це буде дуже незручно.

Тому логічніше визначити спеціальну функцію – життєвий цикл, яку запустити з інтервалом та в ній пересувати всі об’єкти на сторінці.

$( document ).ready(() => {

    var ball2 = {
        el: $('#ball2'),
        move: 'right'
    };


    function gameLoop()
    {
        console.log(parseInt($.now()));
        setTimeout(gameLoop,100);
    }

    gameLoop();
}

);

Зробимо для гри один єдиний блок.

<div class="out" id="gameApp"> </div>

Далі створимо 3 функції:

clear – для очищення ігрового поля

draw - для промальовування всіх елементів

calc - для перерахунку координат елементів

І викличемо їх у життєвому циклі подій.

function clear() {

}

function calc() {

}

function draw() {

}

function gameLoop()
{
    // change position based on speed
    //moveSelection();
    console.log(parseInt($.now()));
    calc();
    clear();
    draw();
    setTimeout(gameLoop,100);
}

Далі закинемо усі об’єкти гри в один об’єкт.

var gameApp = {
    balls: [
        {x: 0, y: 30},
        {x: 30, y: 100},
    ]
}

Опишемо функцію очищення.

function clear() {
    $("#game").clear();
}

Функція промальовування.

function draw() {
    for (let ball of gameApp.balls) {
        $('#gameApp').append(`<div class="ball" style="top:${ball.y}px; left:${ball.x}px">`);
    }
}

Функція перерахунку координат об’єктів.

function calc() {
    for (let ball of gameApp.balls) {
        if(ball.x>170) ball.move = 'left';
        if (ball.x<30) ball.move = 'right';

        if(ball.move === 'left') ball.x = ball.x - 4;
        if(ball.move === 'right') ball.x = ball.x + 4;
    }        
}

Рухаємо об’єкт гармати натисканням стрілок.

Додамо стилі для гармати.

.canon {
    height: 25px;
    width: 5px;
    background-color: black;
    position: absolute;
}

Додамо координату гармати та статус натискання клавіш стрілок в об’єкт гри.

var gameApp = {
    balls: [
        {x: 0, y: 30, move: 'right'},
        {x: 70, y: 100, move: 'left'},
    ],
    cannon_x: 100,
    key_left: 'up',
    key_right: 'up'
}

Додамо до промальовування.

function draw() {
    for (let ball of gameApp.balls) {
        $('#gameApp').append(`<div class="ball" style="top:${ball.y}px; left:${ball.x}px">`);
    }
    $('#gameApp').append(`<div class="canon" style="top:170px; left:${gameApp.cannon_x}px">`);
}

Відстежуємо натискання кнопок стрілок.

$(document).on('keyup', function( e ) {

    if(e.keyCode === 39) gameApp.key_right = 'up'
    if(e.keyCode === 37) gameApp.key_left = 'up'

})

$(document).on('keydown', function( e ) {

    if(e.keyCode === 39) gameApp.key_right = 'down'
    if(e.keyCode === 37) gameApp.key_left = 'down'

})

Додаємо перерахунок координат гармати.

function calc() {
    for (let ball of gameApp.balls) {
        if(ball.x>170) ball.move = 'left';
        if (ball.x<0) ball.move = 'right';

        if(ball.move === 'left') ball.x = ball.x - 4;
        if(ball.move === 'right') ball.x = ball.x + 4;

    }      
    if(gameApp.key_left === 'down') gameApp.cannon_x = gameApp.cannon_x - 4;
    if(gameApp.key_right === 'down') gameApp.cannon_x = gameApp.cannon_x + 4;

}

Робимо обмеження руху гармати за розмірами екрану.

    if(gameApp.key_left === 'down') (gameApp.cannon_x>0)? gameApp.cannon_x = gameApp.cannon_x - 4: gameApp.cannon_x = 0;
    if(gameApp.key_right === 'down') (gameApp.cannon_x<190)? gameApp.cannon_x = gameApp.cannon_x + 4: gameApp.cannon_x=190;

Додамо кульки в об’єкт гри.

var gameApp = {
    ....
    bullets: []
}

Відпрацюємо натискання на пробіл.

$(document).on('keydown', (e) => {
    ...
    if(e.keyCode === 32) {
        gameApp.bullets.push({x: gameApp.canon_x, y: 185})
    }
   ...
})

Змінюємо координати куль і прибираємо їх із масиву при виході межі ігрового поля.

    for (let bullet of gameApp.bullets){

        bullet.y -= 2;
        if(bullet.y<0) gameApp.bullets.splice(gameApp.bullets.indexOf(bullet),1);

       }

Приклад визначення колізії.

var rect1 = {x: 5, y: 5, width: 50, height: 50}
var rect2 = {x: 20, y: 10, width: 10, height: 10}

if (rect1.x < rect2.x + rect2.width &&
   rect1.x + rect1.width > rect2.x &&
   rect1.y < rect2.y + rect2.height &&
   rect1.y + rect1.height > rect2.y) {
    // collision detected!
}
Фронтенд розробка JavaScript. -> Домашнє завдання.

Домашнє завдання.

Відпрацювати колізію куль із кульками. Забирати всі кульки при зіткненні.

Кулі при зіткненні залишати та продовжувати їх рух.

Зробити автоматичну появу нових кульок із випадковою координатою x і рухати їх зверху донизу.

Відпрацювати колізію кульок з гарматою та завершити гру.

Вважати кількість збитих куль.