HTML5 растет быстрее, чем кто-либо мог себе представить. Мощные и профессиональные решения уже разрабатываются … даже в игровом мире! Проверьте сотни игр HTML5 на Envato Market.
Сегодня вы создадите свою первую игру, используя Box2D и тег HTML5 canvas
.
Что такое Box2D ?
Box2D — это популярный движок с открытым исходным кодом, который имитирует физику 2D для создания игр и приложений. Первоначально написанный на C ++, он был преобразован в многочисленные языки участниками сообщества.
Используя одни и те же методы и объекты, вы можете создавать физику игр на многих языках, таких как Objective C (iPhone / iPad), Actionscript 3.0 (Интернет), HTML 5 (Интернет) и т. Д.
Шаг 1 — Настройка вашего проекта
Чтобы начать разработку демоверсии, загрузите движок Box2D для HTML5 здесь . Затем создайте новый HTML-файл со следующей структурой (скопируйте каталоги js и lib из проекта box2d-js в папку с игрой).
Теперь вы должны вставить необходимые файлы для запуска box2D в ваш HTML-файл:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<!—[if IE]><script src=»lib/excanvas.js»></script><![endif]—>
<script src=»lib/prototype-1.6.0.2.js»></script>
<!— box2djs —>
<script src=’js/box2d/common/b2Settings.js’></script>
<script src=’js/box2d/common/math/b2Vec2.js’></script>
<script src=’js/box2d/common/math/b2Mat22.js’></script>
<script src=’js/box2d/common/math/b2Math.js’></script>
<script src=’js/box2d/collision/b2AABB.js’></script>
<script src=’js/box2d/collision/b2Bound.js’></script>
<script src=’js/box2d/collision/b2BoundValues.js’></script>
<script src=’js/box2d/collision/b2Pair.js’></script>
<script src=’js/box2d/collision/b2PairCallback.js’></script>
<script src=’js/box2d/collision/b2BufferedPair.js’></script>
<script src=’js/box2d/collision/b2PairManager.js’></script>
<script src=’js/box2d/collision/b2BroadPhase.js’></script>
<script src=’js/box2d/collision/b2Collision.js’></script>
<script src=’js/box2d/collision/Features.js’></script>
<script src=’js/box2d/collision/b2ContactID.js’></script>
<script src=’js/box2d/collision/b2ContactPoint.js’></script>
<script src=’js/box2d/collision/b2Distance.js’></script>
<script src=’js/box2d/collision/b2Manifold.js’></script>
<script src=’js/box2d/collision/b2OBB.js’></script>
<script src=’js/box2d/collision/b2Proxy.js’></script>
<script src=’js/box2d/collision/ClipVertex.js’></script>
<script src=’js/box2d/collision/shapes/b2Shape.js’></script>
<script src=’js/box2d/collision/shapes/b2ShapeDef.js’></script>
<script src=’js/box2d/collision/shapes/b2BoxDef.js’></script>
<script src=’js/box2d/collision/shapes/b2CircleDef.js’></script>
<script src=’js/box2d/collision/shapes/b2CircleShape.js’></script>
<script src=’js/box2d/collision/shapes/b2MassData.js’></script>
<script src=’js/box2d/collision/shapes/b2PolyDef.js’></script>
<script src=’js/box2d/collision/shapes/b2PolyShape.js’></script>
<script src=’js/box2d/dynamics/b2Body.js’></script>
<script src=’js/box2d/dynamics/b2BodyDef.js’></script>
<script src=’js/box2d/dynamics/b2CollisionFilter.js’></script>
<script src=’js/box2d/dynamics/b2Island.js’></script>
<script src=’js/box2d/dynamics/b2TimeStep.js’></script>
<script src=’js/box2d/dynamics/contacts/b2ContactNode.js’></script>
<script src=’js/box2d/dynamics/contacts/b2Contact.js’></script>
<script src=’js/box2d/dynamics/contacts/b2ContactConstraint.js’></script>
<script src=’js/box2d/dynamics/contacts/b2ContactConstraintPoint.js’></script>
<script src=’js/box2d/dynamics/contacts/b2ContactRegister.js’></script>
<script src=’js/box2d/dynamics/contacts/b2ContactSolver.js’></script>
<script src=’js/box2d/dynamics/contacts/b2CircleContact.js’></script>
<script src=’js/box2d/dynamics/contacts/b2Conservative.js’></script>
<script src=’js/box2d/dynamics/contacts/b2NullContact.js’></script>
<script src=’js/box2d/dynamics/contacts/b2PolyAndCircleContact.js’></script>
<script src=’js/box2d/dynamics/contacts/b2PolyContact.js’></script>
<script src=’js/box2d/dynamics/b2ContactManager.js’></script>
<script src=’js/box2d/dynamics/b2World.js’></script>
<script src=’js/box2d/dynamics/b2WorldListener.js’></script>
<script src=’js/box2d/dynamics/joints/b2JointNode.js’></script>
<script src=’js/box2d/dynamics/joints/b2Joint.js’></script>
<script src=’js/box2d/dynamics/joints/b2JointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2DistanceJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2DistanceJointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2Jacobian.js’></script>
<script src=’js/box2d/dynamics/joints/b2GearJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2GearJointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2MouseJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2MouseJointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2PrismaticJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2PrismaticJointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2PulleyJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2PulleyJointDef.js’></script>
<script src=’js/box2d/dynamics/joints/b2RevoluteJoint.js’></script>
<script src=’js/box2d/dynamics/joints/b2RevoluteJointDef.js’></script>
|
Да, это огромное количество HTTP-запросов!
Обратите внимание, что для развертывания настоятельно рекомендуется объединить все эти ресурсы в один файл
script
.
Затем создайте еще два скрипта в папке /js/
"box2dutils.js"
и "game.js"
.
- box2dutils.js — это копирование и вставка из некоторых демонстраций, поставляемых с
box2dlib
, и это важно для функций рисования (я также объясню некоторые важные части здесь). - game.js — сама игра; Здесь мы создаем платформы, проигрыватель, применяем взаимодействия с клавиатурой и т. д.
Скопируйте и вставьте следующий код в box2dutils.js
. Не волнуйся! Я объясню это по крупицам!
функция drawWorld (мир, контекст) { for (var j = world.m_jointList; j; j = j.m_next) { drawJoint (j, контекст); } for (var b = world.m_bodyList; b; b = b.m_next) { for (var s = b.GetShapeList (); s! = null; s = s.GetNext ()) { drawShape (s, context); } } } функция drawJoint (соединение, контекст) { var b1 = joint.m_body1; var b2 = joint.m_body2; var x1 = b1.m_position; var x2 = b2.m_position; var p1 = joint.GetAnchor1 (); var p2 = joint.GetAnchor2 (); context.strokeStyle = '# 00eeee'; context.beginPath (); switch (joint.m_type) { case b2Joint.e_distanceJoint: context.moveTo (p1.x, p1.y); context.lineTo (p2.x, p2.y); перемена; case b2Joint.e_pulleyJoint: // СДЕЛАТЬ перемена; дефолт: if (b1 == world.m_groundBody) { context.moveTo (p1.x, p1.y); context.lineTo (x2.x, x2.y); } иначе если (b2 == world.m_groundBody) { context.moveTo (p1.x, p1.y); context.lineTo (x1.x, x1.y); } еще { context.moveTo (x1.x, x1.y); context.lineTo (p1.x, p1.y); context.lineTo (x2.x, x2.y); context.lineTo (p2.x, p2.y); } перемена; } context.stroke (); } function drawShape (shape, context) { context.strokeStyle = '# 000000'; context.beginPath (); switch (shape.m_type) { case b2Shape.e_circleShape: { круг var = форма; var pos = circle.m_position; var r = circle.m_radius; var сегменты = 16,0; вар тета = 0,0; var dtheta = 2,0 * Math.PI / сегменты; // нарисовать круг context.moveTo (pos.x + r, pos.y); for (var i = 0; i <сегменты; i ++) { var d = new b2Vec2 (r * Math.cos (theta), r * Math.sin (theta)); var v = b2Math.AddVV (pos, d); context.lineTo (vx, vy); тета + = дхета; } context.lineTo (pos.x + r, pos.y); // нарисовать радиус context.moveTo (pos.x, pos.y); var ax = circle.m_R.col1; var pos2 = new b2Vec2 (pos.x + r * ax.x, pos.y + r * ax.y); context.lineTo (pos2.x, pos2.y); } перемена; case b2Shape.e_polyShape: { var poly = shape; var tV = b2Math.AddVV (poly.m_position, b2Math.b2MulMV (poly.m_R, poly.m_vertices [0])); context.moveTo (tV.x, tV.y); for (var i = 0; i <poly.m_vertexCount; i ++) { var v = b2Math.AddVV (poly.m_position, b2Math.b2MulMV (poly.m_R, poly.m_vertices [i])); context.lineTo (vx, vy); } context.lineTo (tV.x, tV.y); } перемена; } context.stroke (); } function createWorld () { var worldAABB = new b2AABB (); worldAABB.minVertex.Set (-1000, -1000); worldAABB.maxVertex.Set (1000, 1000); var gravity = new b2Vec2 (0, 300); var doSleep = true; var world = new b2World (worldAABB, gravity, doSleep); вернуть мир; } function createGround (world) { var groundSd = new b2BoxDef (); groundSd.extents.Set (1000, 50); groundSd.restitution = 0,2; var groundBd = new b2BodyDef (); groundBd.AddShape (groundSd); groundBd.position.Set (-500, 340); возвращение world.CreateBody (groundBd) } функция createBall (world, x, y) { var ballSd = new b2CircleDef (); ballSd.density = 1,0; ballSd.radius = 20; ballSd.restitution = 1,0; ballSd.friction = 0; var ballBd = new b2BodyDef (); ballBd.AddShape (ballSd); ballBd.position.Set (х, у); return world.CreateBody (ballBd); } функция createBox (world, x, y, width, height, fixed, userData) { if (typeof (fixed) == 'undefined') fixed = true; var boxSd = new b2BoxDef (); if (! fixed) boxSd.density = 1.0; boxSd.userData = userData; boxSd.extents.Set (ширина, высота); var boxBd = new b2BodyDef (); boxBd.AddShape (boxSd); boxBd.position.Set (х, у); вернуть world.CreateBody (boxBd) }
Шаг 2 — Разработка игры
Откройте файл index.html
который вы ранее создали, и добавьте элемент canvas
(600×400) в элемент body
. Здесь мы будем работать с API рисования HTML5:
1
|
<canvas id=»game» width=’600′ height=’400′></canvas>
|
Также, пока вы здесь, game.js
и box2dutils.js
.
1
2
|
<script src=’js/box2dutils.js’></script>
<script src=’js/game.js’></script>
|
Это сделает это для HTML! Давайте работать над забавным JavaScript сейчас!
Откройте game.js
и вставьте код ниже:
// некоторые переменные, которые мы будем использовать в этой демонстрации var initId = 0; var player = function () { this.object = null; this.canJump = false; }; мир вар; var ctx; var canvasWidth; var canvasHeight; var keys = []; // HTML5 onLoad событие Event.observe (window, 'load', function () { world = createWorld (); // box2DWorld ctx = $ ('game'). getContext ('2d'); // 2 var canvasElm = $ ('game'); canvasWidth = parseInt (canvasElm.width); canvasHeight = parseInt (canvasElm.height); initGame (); // 3 шаг (); // 4 // 5 window.addEventListener ( 'KeyDown', handleKeyDown, правда); window.addEventListener ( 'KeyUp', handleKeyUp, правда); });
Box2DWorld — вот почему мы здесь
Хорошо, давайте выясним, что делает этот кусок кода!
Box2DWorld — один из классов, доступных через ядро box2d. Его функция проста: объединить все в один класс. В box2DWorld у вас есть диспетчер определения тел и столкновений вашей игры или приложения.
game.js
box2dutils.js
файлы game.js
и box2dutils.js
и найдите createWorld()
в box2dutils.js
.
function createWorld () { // здесь мы создаем настройки мира для столкновений var worldAABB = new b2AABB (); worldAABB.minVertex.Set (-1000, -1000); worldAABB.maxVertex.Set (1000, 1000); // установить вектор гравитации var gravity = new b2Vec2 (0, 300); var doSleep = true; // инициализируем наш мир и возвращаем его значение var world = new b2World (worldAABB, gravity, doSleep); вернуть мир; }
Создать box2DWorld
довольно просто.
Вернуться к game.js
Обратитесь к закомментированным номерам в двух блоках кода выше. На втором месте мы извлекаем контекст элемента canvas
с помощью API селектора (похоже на селекторы jQuery или MooTools, не так ли?). На третьем месте у нас есть новая интересная функция: initGame()
. Здесь мы создаем декорации.
Скопируйте и вставьте приведенный ниже код в game.js
, а затем мы рассмотрим его вместе.
function initGame () { // создаем 2 большие платформы createBox (world, 3, 230, 60, 180, true, 'ground'); createBox (world, 560, 360, 50, 50, true, 'ground'); // создаем небольшие платформы для (var i = 0; i <5; i ++) { createBox (world, 150+ (80 * i), 360, 5, 40+ (i * 15), true, 'ground'); } // создаем мяч для игрока var ballSd = new b2CircleDef (); ballSd.density = 0,1; ballSd.radius = 12; ballSd.restitution = 0,5; ballSd.friction = 1; ballSd.userData = 'player'; var ballBd = new b2BodyDef (); ballBd.linearDamping = .03; ballBd.allowSleep = false; ballBd.AddShape (ballSd); ballBd.position.Set (20,0); player.object = world.CreateBody (ballBd); } <p> Внутри <code> box2dutils.js </ code> мы создали функцию под названием <code> createBox </ code>. Это создает статическое прямоугольное тело. </ Р> функция createBox (world, x, y, width, height, fixed, userData) { if (typeof (fixed) == 'undefined') fixed = true; // 1 var boxSd = new b2BoxDef (); if (! fixed) boxSd.density = 1.0; // 2 boxSd.userData = userData; // 3 boxSd.extents.Set (ширина, высота); // 4 var boxBd = new b2BodyDef (); boxBd.AddShape (boxSd); // 5 boxBd.position.Set (х, у); // 6 вернуть world.CreateBody (boxBd) }
Box2DBody
У Box2DBody
есть несколько уникальных характеристик:
- Он может быть статическим (не подверженным воздействию столкновений), кинематическим (не подверженным столкновениям, но может перемещаться, например, вашей мышью) или динамическим (взаимодействующим со всем)
- Должен иметь определение формы и должен указывать, как выглядит объект
- Может иметь более одного прибора, который указывает, как объект будет взаимодействовать с столкновениями.
- Его положение задается центром вашего объекта, а не левым верхним краем, как это делают многие другие движки.
Просмотр кода:
- Здесь мы создаем одно определение формы, которое будет представлять собой квадрат или прямоугольник, и устанавливаем его плотность (как часто он будет перемещаться или вращаться силами).
- Мы настраиваем
userData
, обычно вы настраиваете графические объекты здесь, но в этом примере я просто устанавливаю строки, которые будут идентификатором типа объекта для столкновений. Этот параметр не влияет на физические алгоритмы. - Установите половину размера моего блока (это линия от точки положения или центральной точки объекта до угла)
- Мы создаем определение тела и добавляем к нему определение формы блока.
- Настройте позицию.
- Создайте тело в мире и верните его ценность.
Создание тела игрока
Я закодировал игрока (мяч) прямо в файле game.js
Он следует той же последовательности создания ящиков, но на этот раз это мяч.
var ballSd = new b2CircleDef (); ballSd.density = 0,1; ballSd.radius = 12; ballSd.restitution = 0,5; ballSd.friction = 1; ballSd.userData = 'player'; var ballBd = new b2BodyDef (); ballBd.linearDamping = .03; ballBd.allowSleep = false; ballBd.AddShape (ballSd); ballBd.position.Set (20,0); player.object = world.CreateBody (ballBd);
Итак, как мы создадим тело, шаг за шагом?
- Создать форму, крепление и определение датчика
- Создать определение тела
- Добавьте в тело свою форму, приспособления или датчики (не объясненные в этой статье)
- Создай тело в мире
Box2DCircle
Как я уже отмечал ранее, это следует тому же процессу создания блока, но теперь вы должны установить некоторые новые параметры.
- радиус — это длина линии от центра круга до любой точки на его краю.
- реституция — как мяч потеряет или наберет силу при столкновении с другим телом.
- трение — как шарик катится.
Box2DBody
— Дополнительные свойства
- демпфирование используется для уменьшения скорости тела — есть угловое демпфирование и линейное демпфирование.
- спать в box2D, тела могут спать, чтобы решить проблемы с производительностью. Например, предположим, что вы разрабатываете платформенную игру, а уровень определяется экраном 6000×400. Зачем вам нужно выполнять физику для объектов, которые находятся за пределами экрана? Вы не; в этом-то и дело! Поэтому правильный выбор — усыпить их и улучшить производительность вашей игры.
Мы уже создали наш мир; Вы можете проверить код, который у вас есть. Вы увидите, что игрок падает над западной платформой.
Теперь, если вы попытались запустить демонстрацию, вы должны задаться вопросом, почему страница такая бесплодная, как белая книга?
Всегда помните: Box2D не рендерится; это только вычисляет физику.
Шаг 3 — Время рендеринга
Далее давайте отрендерим box2DWorld.
Откройте скрипт game.js
и добавьте следующий код:
function step () { var steping = false; var timeStep = 1,0 / 60; var итерация = 1; // 1 world.Step (timeStep, итерация); // 2 ctx.clearRect (0, 0, canvasWidth, canvasHeight); drawWorld (world, ctx); // 3 setTimeout ('step ()', 10); }
Что мы делаем здесь:
- Инструкции box2dWorld для выполнения физических симуляций
- Очистить экран холста и нарисовать снова
- Выполните функцию
step()
раз за десять миллисекунд
С этим фрагментом кода мы сейчас работаем с физикой и рисованием. Вы можете проверить себя и наблюдать за падающим шаром, как показано ниже:
drawWorld
in box2dutils.js
функция drawWorld (мир, контекст) { for (var j = world.m_jointList; j; j = j.m_next) { drawJoint (j, контекст); } for (var b = world.m_bodyList; b; b = b.m_next) { for (var s = b.GetShapeList (); s! = null; s = s.GetNext ()) { drawShape (s, context); } } }
То, что мы написали выше, это функция отладки, которая рисует наш мир на холсте, используя графический API, предоставляемый HTML5 Canvas API.
Первая петля рисует все суставы. Мы не использовали суставы в этой статье. Они немного сложны для первого демо, но, тем не менее, они важны для ваших игр. Они позволяют создавать очень интересные тела.
Второй цикл рисует все тела, поэтому мы здесь!
function drawShape (shape, context) { context.strokeStyle = '# 000000'; context.beginPath (); switch (shape.m_type) { case b2Shape.e_circleShape: { круг var = форма; var pos = circle.m_position; var r = circle.m_radius; var сегменты = 16,0; вар тета = 0,0; var dtheta = 2,0 * Math.PI / сегменты; // нарисовать круг context.moveTo (pos.x + r, pos.y); for (var i = 0; i <сегменты; i ++) { var d = new b2Vec2 (r * Math.cos (theta), r * Math.sin (theta)); var v = b2Math.AddVV (pos, d); context.lineTo (vx, vy); тета + = дхета; } context.lineTo (pos.x + r, pos.y); // нарисовать радиус context.moveTo (pos.x, pos.y); var ax = circle.m_R.col1; var pos2 = new b2Vec2 (pos.x + r * ax.x, pos.y + r * ax.y); context.lineTo (pos2.x, pos2.y); } перемена; case b2Shape.e_polyShape: { var poly = shape; var tV = b2Math.AddVV (poly.m_position, b2Math.b2MulMV (poly.m_R, poly.m_vertices [0])); context.moveTo (tV.x, tV.y); for (var i = 0; i <poly.m_vertexCount; i ++) { var v = b2Math.AddVV (poly.m_position, b2Math.b2MulMV (poly.m_R, poly.m_vertices [i])); context.lineTo (vx, vy); } context.lineTo (tV.x, tV.y); } перемена; } context.stroke (); }
Мы перебираем все вершины объекта и рисуем его с помощью линий ( context.moveTo
и context.lineTo
). Теперь полезно иметь пример … но не так полезно на практике. Когда вы используете графику, вам нужно только обратить внимание на расположение тел. Вам не нужно зацикливать вершины, как это делает демо.
Шаг 4 — Интерактивность
Игра без интерактивности — это фильм, а фильм с интерактивностью — это игра.
Давайте разработаем функциональность стрелки клавиатуры, чтобы прыгать и перемещать мяч.
Добавьте следующий код в ваш файл game.js
:
function handleKeyDown (evt) { keys [evt.keyCode] = true; } function handleKeyUp (evt) { keys [evt.keyCode] = false; } // отключаем вертикальную прокрутку от стрелок 🙂 document.onkeydown = function () {return event.keyCode! = 38 && event.keyCode! = 40}
С помощью handleKeyDown
и handleKeyUp
мы handleKeyUp
array
который отслеживает каждый ключ, который вводит пользователь. При использовании document.onkeydown
мы отключаем встроенную в браузере функцию вертикальной прокрутки для стрелок вверх и вниз. Вы когда-нибудь играли в игру HTML5, и когда вы прыгаете, игрок, враги и объекты уходят с экрана? Это не будет проблемой сейчас.
Добавьте следующий бит кода в начало вашей функции step()
:
handleInteractions ();
А снаружи объявим функцию:
function handleInteractions () { // стрелка вверх // 1 var collision = world.m_contactList; player.canJump = false; if (столкновение! = ноль) { if (collision.GetShape1 (). GetUserData () == 'player' || collision.GetShape2 (). GetUserData () == 'player') { if ((collision.GetShape1 (). GetUserData () == 'ground' || collision.GetShape2 (). GetUserData () == 'ground')) { var playerObj = (collision.GetShape1 (). GetUserData () == 'player'? collision.GetShape1 (). GetPosition (): collision.GetShape2 (). GetPosition ()); var groundObj = (collision.GetShape1 (). GetUserData () == 'ground'? collision.GetShape1 (). GetPosition (): collision.GetShape2 (). GetPosition ()); if (playerObj.y <groundObj.y) { player.canJump = true; } } } } // 2 var vel = player.object.GetLinearVelocity (); // 3 if (keys [38] && player.canJump) { vel.y = -150; } // 4 // стрелки влево / вправо if (ключи [37]) { vel.x = -60; } еще если (ключи [39]) { vel.x = 60; } // 5 player.object.SetLinearVelocity (VEL); }
Самый сложный фрагмент кода выше — это первый, где мы проверяем наличие столкновения и пишем некоторые условия, чтобы определить, является ли shape1
или shape2
игроком. Если это так, мы проверяем, является ли shape1
или shape2
наземным object
. Опять же, если так, игрок сталкивается с землей. Далее мы проверяем, находится ли игрок над землей. Если это так, то игрок может прыгать.
Во второй строке комментария (2) мы получаем LinearVelocity
игрока.
Третья и четвертая прокомментированные области проверяют, нажимаются ли стрелки, и соответственно корректируют вектор скорости.
В пятом регионе мы настраиваем игрока с новым вектором скорости.
Взаимодействие теперь сделано! Но нет цели, Мы просто прыгаем, прыгаем, прыгаем … и прыгаем!
Шаг 5 — Сообщение «Ты выиграл»
Добавьте приведенный ниже код в начало вашей функции LinearVelocity
:
if (player.object.GetCenterPosition (). y> canvasHeight) { player.object.SetCenterPosition (new b2Vec2 (20,0), 0) } else if (player.object.GetCenterPosition (). x> canvasWidth-50) { showWin (); возвращение; }
- Первое условие определяет, падает ли игрок, и должно быть перенесено обратно в начальную точку (над западной платформой).
- Второе условие проверяет, находится ли игрок над второй платформой и выиграл ли игру. Вот
showWin()
.
function showWin () { ctx.fillStyle = '# 000'; ctx.font = '30px verdana'; ctx.textBaseline = 'top'; ctx.fillText («Да! Ты сделал это!», 30, 0); ctx.fillText («спасибо, andersonferminiano.com», 30, 30); ctx.fillText ('@ andferminiano', 30, 60); }
Вот и все! Вы только что завершили свою первую простую игру с HTML5 и Box2D. Поздравляем!
Если вам нужно более простое решение, вы можете ознакомиться с выбором игр HTML5 на Envato Market, многие из которых поставляются с исходным кодом, который вы можете исследовать и настроить в соответствии со своими потребностями.