Принадність розробки програмного забезпечення полягає в тому, що вона дозволяє - в межах розумного - втілити на екрані все, що тільки можна уявити. Чи не обмежені фізичними обмеженнями, які заважають інженерам в інших областях, програмісти здавна використовують графічні API і інструментарій для користувача інтерфейсу для реалізації творчих ідей і створення чудових додатків. Можливо, самий творчий жанр розробки програмного забезпечення - це програмування ігор; не всі починання здатні більше винагородити автора з творчої точки зору, ніж перетворення ідеї гри в реальність.
Однак винагороду це дається не легко - навіть навпаки. Для створення ігор, особливо відеоігор, потрібно нетривіальне знання програмування, добре володіння графікою і анімацією і незвичайні математичні здібності в поєднанні з мистецтвом і творчістю. І це тільки початок. Успішні розробники витрачають багато часу на полірування своїх ігор, відточуючи геймплей і графіку, не кажучи вже про багатьох аспектах гри, які не мають нічого спільного з геймплеєм, - таких як табло, інструкції, анімації в проміжках між життями і рівнями і послідовності ендгейма.
Мета цього циклу статей - показати, як створити відеогру на HTML5, щоб читач зміг продовжувати самостійно.
Відеоролик «Про це циклі статей» - ось розшифровка стенограми .
У цьому циклі статей я покажу, як створити відеогру-платформер, головним чином за допомогою API Canvas HTML5. Це гра Snail Bait (засіб від равликів), яка показана на малюнку 1. У неї можна пограти в онлайні (див. Посилання в розділі ресурси ). Переконайтеся, що ваш браузер підтримує апаратне прискорення Canvas (воно зовсім недавно реалізовано в більшості браузерів, в тому числі в Chrome, починаючи з версії 18); в іншому випадку Snail Bait буде працювати вкрай повільно. (Див. Боковик Продуктивність HTML5 Canvas .)
Малюнок 1. Гра Snail Bait в браузері Chrome
Snail Bait являє собою класичний платформер. Персонаж, якого я буду називати просто бігун, біжить і скаче між плавучих платформ, які рухаються горизонтально. Кінцева мета бігуна - дістатися до пульсуючого платформи із золотою кнопкою в кінці рівня. Бігун, пульсуюча платформа і золота кнопка показані на малюнку 1 .
Гравець управляє бігуном з клавіатури: клавіша d переміщує його вліво, клавіша k - право, клавіші j і f змушують підстрибнути, а клавіша p призупиняє гру.
На початку гри вам даються три життя. Зліва над полотном гри показує значки із зображенням бігуна, що вказують кількість залишилися життів, як видно на малюнку 1 . На своєму шляху бігун повинен вивертатися від монстрів - бджіл, кажанів і равлики - намагаючись при цьому схопити цінні предмети - монети, рубіни і сапфіри. Якщо бігун стикається з монстрами, він лопається, і ви втрачаєте життя, повертаючись в початок рівня. Коли бігун підбирає предмети, ваш рахунок збільшується, і ви отримуєте винагороду у вигляді приємною мелодії.
Монстри в основному просто висять і чекають, поки бігун натрапить на них. Однак равлик періодично впадає ядрами (срібне ядро поблизу центру на малюнку 1 ). Ці ядра, як і монстри, підривають бігуна, коли наздоганяють його.
Гра закінчується одним з двох способів: або ви втрачаєте все три життя, або досягаєте пульсуючою платформи (з бонусними очками за натискання на золоту кнопку). У будь-якому випадку гра закінчується титрами, показаними на малюнку 2.
Малюнок 2. Повідомлення про авторів гри
Чого не видно на малюнку 1 , Так це того, що все - за винятком бігуна, чиїм рухом ви керуєте, - постійно рухається. Це рух робить Snail Bait не просто платформер, а сайд-скроллером. Однак не тільки це рух в грі привело мене до спрайт і їх маніпуляторам.
На початок
За винятком фону, все в Snail Bait є спрайт. Спрайт - це об'єкт, який можна намалювати на полотні гри. Спрайт прості в реалізації, хоча і не є частиною API Canvas. Ось спрайт гри:
- платформи (неживі об'єкти);
- бігун (персонаж);
- бджоли і кажани (монстри);
- кнопки (корисні предмети);
- рубіни і сапфіри (корисні предмети);
- монети (корисні предмети);
- равлик (монстр);
- ядра равлики (шкідливі предмети).
Крім горизонтальних рухів, майже всі спрайт гри мають власні незалежні руху. Наприклад, рубіни і сапфіри підстрибують з різною частотою, а кнопки і равлик снують туди-сюди за своїми платформ.
Це незалежний рух - один з багатьох маніпуляторів спрайтів. У спрайтів можуть бути і інші маніпулятори, не пов'язані з рухом; наприклад, крім підстрибування, рубіни і сапфіри іскряться.
Кожен спрайт має свій набір маніпуляторів. Маніпулятор - це просто об'єкт з методом execute (). У кожному кадрі анімації гра викликає метод execute () кожного маніпулятора. У цьому методі маніпулятори певним чином керують відповідними спрайтами в залежності від умов гри. Наприклад, при натисканні клавіші k для переміщення бігуна вправо маніпулятор бігуна горизонтальне переміщення послідовно переміщує бігуна вправо в кожному кадрі анімації до тих пір, поки ви не зміните напрям. Інший маніпулятор - біг на місці - періодично змінює зображення бігуна, імітуючи біг на місці. У сукупності ці два маніпулятора справляють враження бігу вліво або вправо.
У таблиці 1 перераховані спрайт гри і відповідні маніпулятори (поведінку).
Таблиця 1. Спрайт і маніпулятори Snail Bait
Спрайт Поведінка Платформи
- Переміщаються горизонтально (всі спрайт, за винятком бігуна і ядер равлики, рухаються синхронно з платформами)
- Біг на місці
- горизонтальне переміщення
- стрибок
- падіння
- Зіткнення з монстрами / шкідливими предметами і вибух
- Зіткнення з корисними предметами та отримання очок
- парять
- махають крилами
- снують
- лопаються
- Підривають монстрів або завершують рівень.
- виблискують
- підстрибують
- снують
- снують
- кидають ядра
- Рухаються вправо і вліво (швидше, ніж платформи)
- Стикаються з бігуном і зникають
Ми детально розглянемо спрайт і маніпулятори в наступних статтях цього циклу. Поки ж, щоб дати вам загальне уявлення, в лістингу 1 показано, як гра створює спрайт бігуна.
Лістинг 1. Створення спрайтів
var runInPlace = {// Просто об'єкт з методом execute execute: function (sprite, time, fps) {// Оновлення атрибутів спрайту на основі часу і частоти кадрів}}; var runner = new Sprite ( 'runner', // ім'я runnerPainter, // будівник [runInPlace, ...]); // маніпулятори
Об'єкт runInPlace визначається і передається конструктору спрайту бігуна разом з іншими маніпуляторами. Поки той біжить, гра в кожному кадрі анімації викликає метод execute () об'єкта runInPlace.
На початок
Практика розробки ігор на HTML5
Протягом цього циклу статей я буду давати практичні рекомендації по розробці ігор і почну з п'ятірки, специфічної для HTML5:
Я розгляну цю п'ятірку рекомендацій докладно в наступних статтях циклу; поки ж коротко пробіжимося по кожному з них.
1. Призупинення гри, коли вікно втрачає фокус
Якщо гра HTML5 виконується в браузері, і ви перенесли фокус на іншу вкладку або в інше вікно браузера, більшість браузерів різко знижує частоту кадрів анімації гри для економії ресурсів, таких як ресурси ЦП та заряд батареї. Це зниження частоти кадрів, в свою чергу, майже завжди наводить хаос в алгоритмах виявлення зіткнень, які очікують, що гра буде працювати з мінімально допустимої частотою кадрів. Щоб уникнути обмежень, пов'язаних з частотою кадрів, і подальшого хаосу в виявленні зіткнень краще автоматично призупинити гру, коли вікно втрачає фокус.
2. Зворотний відлік часу, коли вікно відновлює фокус
Коли вікно гри знову відновлює фокус, корисно надати користувачеві кілька секунд на підготовку до гри. У грі Snail Bait, коли вікно відновлює фокус, починається зворотний відлік трьох секунд, як показано на малюнку 3 .
Малюнок 3. Автопауза Snail Bait
3. Використання переходів CSS3
На малюнку 4 наведено скріншот, зроблений після завантаження гри.
Малюнок 4. Ефекти CSS3
на малюнку 4 треба відзначити три речі. По-перше, це напис Good luck! (Удачі!), Яка на короткий час демонструється гравцеві. Вона тьмяніє в процесі завантаження гри і через п'ять секунд зникає. По-друге, зверніть увагу на прапорці (для відключення звуку і музики) і інструкції (що вказують, які клавіші які функції виконують) під полотном гри. Коли гра починається, прапорці та інструкції добре видно, як на малюнку 4 ; коли ж гра починається, ці елементи повільно тьмяніють, поки на стають ледь помітні (як показано на малюнку 3 ), Щоб не відволікати гравця.
Snail Bait затемнює елементи і гасить написи за допомогою переходів CSS3.
4. Виявлення повільного виконання гри і реагування на нього
На відміну від консольних ігор, які виконуються в жорстко контрольованому середовищі, середа ігор HTML5 мінлива, непередбачувана і хаотична. Нерідко гра працює неприпустимо повільно, так як користувач відтворює відео YouTube в іншій вкладці або ще як-небудь перевантажує ЦП або графічний процесор. І завжди є ймовірність того, що гравець буде використовувати браузер, який "не тягне".
Розробник ігор повинен передбачити ці несприятливі умови і відповідно реагувати на них. Snail Bait постійно контролює частоту кадрів, і коли вона опускається нижче певного порогу багато разів і на багато секунд, відображає повідомлення про повільну роботу гри, показане на малюнку 5.
Малюнок 5. Виявлення низької частоти кадрів
5. Включення соціальних функцій
Майже всі популярні ігри включають соціальні аспекти, такі як розміщення рахунки в Twitter або Facebook. Коли гравець Snail Bait клацає на посиланні Tweet my score, яка з'являється в кінці гри (див. малюнок 2 ), Snail Bait відкриває Twitter в окремій вкладці і автоматично створює твіт з оголошенням рахунку, як показано на малюнку 7.
Малюнок 7. Текст твіти
Тепер, коли у вас склалося загальне уявлення про гру, настав час поглянути на код.
На початок
Гра Snail Bait реалізована на базі HTML, CSS і JavaScript; як видно з врізки Статистика коду Snail Bait , Велика частина коду - це JavaScript. Інші статті цього циклу присвячені головним чином JavaScript - з окремими вилазками в сторону HTML і CSS3.
На малюнку 8 показані елементи HTML і відповідні CSS для самої гри, без HTML і CSS інших елементів, таких як повідомлення і заключні титри.
Малюнок 8. Код HTML і CSS гри (без оголошень і написів)
Код CSS в основному нічим не примітний, за винятком кількох цікавих атрибутів, які я підкреслив на малюнку 8 . По-перше, я встановив значення 0 auto атрибута margin елемента wrapper, що означає, що оболонка і все, що всередині неї, центрується в вікні по горизонталі. По-друге, положення елементів lives і sound-and-music має значення absolute. Якщо залишити значення за замовчуванням relative, то ці елементи DIV розгорнуться до ширини полотна і заслонять своїх сусідів (рахунок і інструкції відповідно). Нарешті, класи CSS keys і explanation мають атрибут inline, щоб відповідні елементи розміщувалися в тому ж рядку.
У лістингу 2 показаний код CSS, відповідний малюнку 8 .
Лістинг 2. game.CSS (фрагмент)
#arena {text-align: center; padding: 5px; width: 805px; height: 445px; } #Copyright {margin-top: -35px; float: right; margin-right: 12px; padding: 2px; color: blue; text-shadow: 1px 1px 1px rgba (255,255,255,0.7); font-size: 0.8em; } .Explanation {color: # ff0; text-shadow: 1px 1px 1px rgba (0,0,0,1.0); display: inline; margin-top: 5px; padding-right: 5px; padding-left: 5px; padding-bottom: 2px; } # Game-canvas {border: 2px inset rgba (0,0,80,0.62); -webkit-box-shadow: rgba (0,0,0,0.5) 8px 8px 16px; -moz-box-shadow: rgba (0,0,0,0.5) 8px 8px 16px; -o-box-shadow: rgba (0,0,0,0.5) 8px 8px 16px; box-shadow: rgba (0,0,0,0.5) 8px 8px 16px; } #Instructions {height: 30px; margin-right: 8px; padding-top: 6px; padding-left: 25px; -webkit-transition: opacity 2s; -moz-transition: opacity 2s; -o-transition: opacity 2s; transition: opacity 2s; color: # ff0; font-size: 1.05em; opacity: 1.0; } .Keys {color: blue; text-shadow: 1px 1px 1px rgba (255,255,0,1.0); background: rgba (0,0,0,0.1); border: thin solid rgba (0,0,0,0.20); border-radius: 5px; margin-left: 10px; padding-right: 10px; padding-left: 10px; padding-bottom: 5px; display: inline; } # Sound-and-music {position: absolute; top: 495px; margin-left: 10px; color: # ff0; text-shadow: 1px 1px 1px rgba (0,0,0,0.5); background: rgba (0,0,0,0.1); border-radius: 5px; border: thin solid rgba (0,0,0,0.20); padding-top: 2px; padding-bottom: 2px; z-index: 1; } #Wrapper {margin: 0 auto; margin-top: 20px; padding: 5px; width: 817px; height: 520px; }
Як видно з лістингу 3, який містить код HTML, відповідний малюнку 8 , HTML-код гри - це набір елементів DIV і полотен з декількома зображеннями і парою прапорців.
Лістинг 3. game.html (фрагмент)
<! DOCTYPE html> <html> <! - Head ..................................... ...................--> <head> <title> Snail Bait </ title> </ head> <! - Body ....... .................................................- -> <body> <! - Wrapper ........................................ ..........--> <div id = 'wrapper'> <! - Header ........................ .........................--> <div id = 'header'> <div id = 'lives'> <img id = 'life -icon-left 'src =' images / runner-small.png '/> <img id =' life-icon-middle 'src =' images / runner-small.png '/> <img id =' life-icon -right 'src =' images / runner-small.png '/> </ div> <div id =' score '> 0 </ div> <div id =' fps '> </ div> </ div> < ! - Arena .............................................. ....--> <div id = 'arena'> <! - The game canvas ............................ .........--> <canvas id = 'game-canvas' width = '800' height = '400'> Your browser does not support HTML5 Canvas. </ canvas> <! - Sound and music .....................................-- > <div id = 'sound-and-music'> <div class = 'checkbox-div'> Sound <input id = 'sound-checkbox' type = 'checkbox' checked /> </ div> <div class = ' checkbox-div '> Music <input id =' music-checkbox 'type =' checkbox 'checked /> </ div> </ div> <! - Instructions .............. ..........................--> <div id = 'instructions'> <div class = 'keys'> d / k <div class = 'explanation'> move left / right </ div> </ div> <div class = 'keys'> f / j <div class = 'explanation'> jump </ div> </ div> <div class = 'keys'> p <div class = 'explanation'> pause </ div> </ div> </ div> <! - Copyright ................... ........................--> <div id = 'copyright'> В © 2012 David Geary </ div> </ div> </ div> <! - JavaScript ........................................... .....--> <script src = 'js / stopwatch.js'> </ script> <script src = 'js / animationTimer.js'> </ script> <script src = 'js / sprites.js '> </ script> <script src =' js / requestNextAnimationFrame.js '> </ script> <script src = 'js / behaviors / bounce.js'> </ script> <script src = 'js / behaviors / cycle.js'> </ script> <script src = 'js / behaviors / pulse.js'> </ script> <script src = 'game.js'> </ script> </ body> </ html>
Елемент canvas - це місце, де відбувається вся дія. Полотно містить 2D-контекст з потужним API для реалізації 2D-ігор і інших речей. Текст всередині елемента canvas є страхувальний текст, який браузер відображає тільки в тому випадку, якщо він не підтримує Canvas HTML5.
Одне заключне зауваження про коді HTML і CSS гри: зверніть увагу, що ширина і висота полотна вказується атрибутами елемента canvas width і height. Ці атрибути відносяться як до розміру елемента canvas, так і до розміру поверхні малюнка, що міститься в цьому елементі.
З іншого боку, розмір елемента canvas можна встановити, лише використовуючи CSS для завдання його ширини і висоти. Поле малюнка зберігає свою ширину і висоту за замовчуванням в 300 і 150 пікселів відповідно. Це означає, що відповідності між розміром елемента canvas і розміром поля його малюнка, швидше за все, не буде, і браузер змінить масштаб поля малюнка під розмір елемента. Найчастіше це небажано, тому краще поставити розмір елемента canvas за допомогою CSS.
Отже, як в кращих кінофільмах, таких як Кримінальне чтиво, кінець історії ви вже знаєте. Тепер звернемося до її початку.
На початок
Невибагливе початок Snail Bait
На малюнку 9 показано відправна точка гри, де просто вимальовується фон, платформи і бігун. Спочатку платформи і бігун не є спрайтами; гра вимальовує їх безпосередньо. Див. Розділ Завантаження з кодом, який створює фон і бігуна.
Малюнок 9. Зображення фону і бігуна
У лістингу 3 приведена відправна точка HTML-коду гри, який представляє собою просто усічену версію HTML-коду з лістингу 2 .
Лістинг 3. game.html (початкова версія)
<! DOCTYPE html> <html> <! - Head ..................................... ....................--> <head> <title> Snail Bait </ title> <link rel = 'stylesheet' href = 'game.css' / > </ head> <! - Body ........................................ .................--> <body> <! - Wrapper ...................... .............................--> <div id = 'wrapper'> <! - Header ..... ............................................--> <div id = 'header'> <div id = 'score'> 0 </ div> </ div> <! - Arena ....................... ...........................--> <div id = 'arena'> <! - The game canvas ..... ................................--> <canvas id = 'game-canvas' width = '800' height = '400'> Your browser does not support HTML5 Canvas. </ canvas> </ div> </ div> <! - JavaScript ................................. ...............--> <script src = 'game.js'> </ script> </ body> </ html>
У лістингу 4 показаний код JavaScript.
Лістінг 4. game.html (початкова версія)
// --------------------------- ОГОЛОШЕННЯ -------------------- -------- var canvas = document.getElementById ( 'game-canvas'), context = canvas.getContext ( '2d'), // Константи .............. .............................................. PLATFORM_HEIGHT = 8, PLATFORM_STROKE_WIDTH = 2, PLATFORM_STROKE_STYLE = 'rgb (0,0,0)', STARTING_RUNNER_LEFT = 50, STARTING_RUNNER_TRACK = 1, // Проведення вихідних ліній // // Платформи рухаються уздовж доріжок. Наступні Константи визначаються координату // Y кожної доріжкі (від верхньої Межі полотна). TRACK_1_BASELINE = 323, TRACK_2_BASELINE = 223, TRACK_3_BASELINE = 123, // Зображення background = new Image (), runnerImage = new Image (), // Платформи // // У кожної Платформи свой власний стиль заливки, но стиль контура однаково. platformData = [// Екран поки один // Екран 1 ...................................... ................. {left: 10, width: 230, height: PLATFORM_HEIGHT, fillStyle: 'rgb (255,255,0)', opacity: 0.5, track: 1, pulsate : false,}, {left: 250, width: 100, height: PLATFORM_HEIGHT, fillStyle: 'rgb (150,190,255)', opacity: 1.0, track: 2, pulsate: false,}, {left: 400, width: 125, height: PLATFORM_HEIGHT, fillStyle: 'rgb (250,0,0)', opacity: 1.0, track: 3, pulsate: false}, {left: 633, width: 100, height: PLATFORM_HEIGHT, fillStyle: 'rgb (255,255, 0) ', opacity: 1.0, track: 1, pulsate: false,},]; // ------------------------- ініціалізації ---------------------- ------ function initializeImages () {background.src = 'images / background_level_one_dark_red.png'; runnerImage.src = 'images / runner.png'; background. onload = function (e) {startGame (); }; } Function drawBackground () {context.drawImage (background, 0, 0); } Function calculatePlatformTop (track) {var top; if (track === 1) {top = TRACK_1_BASELINE; } Else if (track === 2) {top = TRACK_2_BASELINE; } Else if (track === 3) {top = TRACK_3_BASELINE; } Return top; } Function drawPlatforms () {var pd, top; context.save (); // Збереження атрібутів контексту в стеці for (var i = 0; i <platformData.length; ++ i) {pd = platformData [i]; top = calculatePlatformTop (pd.track); context.lineWidth = PLATFORM_STROKE_WIDTH; context.strokeStyle = PLATFORM_STROKE_STYLE; context.fillStyle = pd.fillStyle; context.globalAlpha = pd.opacity; // Если Изменить порядок Наступний двох викликів, то контур буде здаватіся товстішім. context.strokeRect (pd.left, top, pd.width, pd.height); context.fillRect (pd.left, top, pd.width, pd.height); } Context.restore (); // Відновлення атрибутів контексту} function drawRunner () {context.drawImage (runnerImage, STARTING_RUNNER_LEFT, calculatePlatformTop (STARTING_RUNNER_TRACK) - runnerImage.height); } Function draw (now) {drawBackground (); drawPlatforms (); drawRunner (); } Function startGame () {draw (); } // Запуск гри initializeImages ();
Сценарій JavaScript звертається до елементу canvas і отримує посилання на 2D-контекст полотна. Потім код використовує метод контексту drawImage () для малювання фону і бігуна. В даному випадку я використовую варіант з трьома аргументами методу drawImage (), щоб намалювати зображення в певному місці полотна (x, y).
Функція drawPlatforms () зображує платформи, вимальовуючи і заповнюючи прямокутні контури після установки ширини лінії, стилю обведення, стилю заливки і глобального альфа-атрибута контексту. Зверніть увагу на виклики методів context.save () і context.restore (): налаштування атрибутів між цими викликами - тимчасові. Ми поговоримо про ці методи в наступній статті.
Гра починається, коли завантажується фонове зображення. Поки запуск тягне за собою тільки вимальовування фону, спрайтів і бігуна. Наступне завдання - викликати ці статичні зображення до життя.
на початок
Наступну статтю цього циклу я почну з огляду 2D-API контексту полотна, а потім розповім про анімацію і приведення предметів в рух за допомогою прокрутки фону. Ви побачите, як реалізувати паралакс, щоб платформа здавалася ближче, ніж фон, і як зробити так, щоб спрайт рухалися з постійною швидкістю незалежно від частоти кадрів анімації. До скорої зустрічі.
на початок
Опис Ім'я Розмір Метод завантаження Код фону і персонажа Snail Bait j-html5-game1.zip 718 КБ HTTPІнформація про методи завантаження
Девід Гирі (David Geary), автор книги Core HTML5 Canvas , Є також співзасновником групи користувачів HTML5 Денвера і автором восьми книг по Java-програмування, в тому числі бестселерів по Swing і JavaServer Faces. Девід часто виступає на конференціях, в тому числі JavaOne, Devoxx, Strange Loop, NDC і OSCON, і тричі заслужив титул "рок-зірки JavaOne". Для developerWorks він написав цикли статей JSF 2 fu и GWT fu . За новинами Девіда можна стежити в Twitter: @davidgeary.
При першому вході в developerWorks для Вас буде створений профіль і Вам потрібно буде вибрати Коротке ім'я. Воно буде виводитися поруч з контентом, опублікованими Вами в developerWorks.
Псевдонім повинно мати довжину від 3 символів до 31 символу. Ваше ім'я в системі має бути унікальним. Як ім'я з міркувань приватності можна використовувати контактний e-mail.
Вся введена інформація захищена.
на початок