Добавление физики в веб-компоненты

В предыдущем посте я рассмотрел использование веб-компонентов (настраиваемых элементов) для разработки браузерных игр.

Сегодня мы добавим физику в наши HTML-теги просто потому, что это возможно! И немного узнать о веб-компонентах и ​​физике в javascript Материя.JS

Мы рассмотрим:

  • Пользовательские элементы
  • Цикл игры
  • Добавление физики (с Matter.js)
  • Настройка проекта (с Parcel.js)

анимация

Симуляция с прыгучими бочками, неподатливыми ящиками, платформами и персонажем игрока..

Пример кода находится в Typescript, но вы можете опустить аннотации типа, такие как a:number и public, private конвертировать в Javascript.

Пользовательские элементы

Пользовательский элемент — это HTML-тег, к которому добавлен исполняемый код. Это очень удобно для игровых объектов! Мы будем использовать это, чтобы добавить физику позже. Пользовательские элементы можно вкладывать друг в друга для создания иерархии. Имена тегов должны заканчиваться на -component (по крайней мере, я получаю сообщение об ошибке, если пропущу это)…

HTML

<game-component> <platform-component></platform-component> <crate-component></crate-component> <player-component></player-component>
</game-component>

CSS

Мы будем использовать translate для позиционирования наших элементов с помощью javascript, так что это означает, что все элементы должны position:absolute и display:block. Вы можете использовать фоновое изображение для визуализации, это короче и быстрее, чем использование <img> теги, и вы можете использовать повторяющиеся фоны.

platform-component { position:absolute; display:block; background-image:url(./images/platform.png); width:400px; height:20px;
}

МАШИНОПИСЬ

Сначала мы должны связать наш код с тегом HTML, создав класс и зарегистрировав его с помощью customElments.define().

😬 В Javascript все точно так же, за исключением :number аннотации типов

export class Crate extends HTMLElement { constructor(x:number, y:number) { super() console.log(`I am a crate at ${x}, ${y}`) }
} customElements.define('crate-component', Crate)

Вы можете добавить его в DOM, поместив тег в HTML-документ: <crate-component></crate-component>. Но если мы делаем это с помощью кода, мы можем передавать аргументы конструктора, в данном случае x и y должность. Это удобно, если нам нужно несколько ящиков в разных позициях:

let c = new Crate(200,20)
document.body.appendChild(c)

ИГРОВОЙ ЦИКЛ

Чтобы использовать физику, нам нужен игровой цикл. Это будет обновлять физический движок 60 раз в секунду. Затем игровой цикл обновит все пользовательские элементы. В этом примере мы создаем игровой класс с игровым циклом, который обновляет все ящики.

import { Crate } from "./crate" export class Game extends HTMLElement { private crates : Crate[] = [] constructor() { super() this.elements.push(new Crate(270, 20)) this.gameLoop() } private gameLoop(){ for (let c of this.crates){ c.update() } requestAnimationFrame(() => this.gameLoop()) }
}
customElements.define('game-component', Game)

Компонент ящика получает функцию обновления для translate его положение.

export class Crate extends HTMLElement { constructor(private x:number, private y:number) { super() } public update() { this.style.transform = `translate(${this.x}px, ${this.y}px)` }
}
customElements.define('crate-component', Crate)

🔥 ФИЗИКА

НАКОНЕЦ мы добираемся до точки, где мы добавляем Matter.js физика! Matter.js создает физический движок, который может работать незаметно в фоновом режиме.. Если мы добавим к нему такие объекты, как коробки, цилиндры, полы и потолки, это создаст физическую симуляцию с этими объектами. Наши элементы будут реагировать на гравитацию, трение, скорость, силу, упругость и получать точное обнаружение столкновений.

Matter.js имеет renderer который может рисовать эти объекты прямо на холсте, но это скучно 🥱. Мы будем использовать позиции физических элементов для позиционирования элементов DOM!

Строить планы:

1 — Добавление физического мира в игровой класс 2 — Добавление физики в ящики

3 — Что еще вы можете сделать с физикой?

1 — Добавление Matter.js в класс Game

import Matter from 'matter-js'
import { Crate } from "./crate" export class Game extends HTMLElement { private engine : Matter.Engine private world : Matter.World private crates : Crate[] = [] constructor() { super() this.engine = Matter.Engine.create() this.world = this.engine.world this.crates.push( new Crate(this.world, 270, 20, 60, 60), new Crate(this.world, 320, 70, 60, 60) ) this.gameLoop() } private gameLoop(){ Matter.Engine.update(this.engine, 1000 / 60) for (let c of this.crates){ c.update() } requestAnimationFrame(() => this.gameLoop()) }
} customElements.define('game-component', Game)

2 — Добавление физики в ящики

Класс Crate добавит физический ящик в физический мир. Затем он прочитает позицию поля физики в функции обновления и обновит позицию элемента ящика в мире DOM.

import Matter from 'matter-js' export class Crate extends HTMLElement { private physicsBox: Matter.Body constructor(x: number, y: number, private width: number, private height: number) { super() this.physicsBox = Matter.Bodies.rectangle(x, y, this.width, this.height, options) Matter.Composite.add(game.getWorld(), this.physicsBox) document.body.appendChild(this) } public update() { let pos = this.physicsBox.position let angle = this.physicsBox.angle let degrees = angle * (180 / Math.PI) this.style.transform = `translate(${pos.x - (this.width/2)}px, ${pos.y-(this.height/2)}px) rotate(${degrees}deg)` }
}
customElements.define('crate-component', Crate)

3 — Что еще вы можете сделать с физикой?

Мы действительно только начинаем использовать Matter.JS. Чтобы построить игру, которую вы видите на изображениях из этого поста, вы используете следующие концепции:

Статические элементы

Это такие элементы, как платформы и стены, к которым не применяются силы, но которые все же вызывают столкновения.

this.physicsBox = Matter.Bodies.rectangle(x, y, w, h, {isStatic:true})

Скорость

Установив скорость объекта вручную, вы можете создать персонажа игрока или врага, который движется в соответствии с вводом игрока.

Matter.Body.setVelocity(this.physicsBox, { x: 5, y: this.physicsBox.velocity.y })

Сила

Добавляя сила вы можете временно подтолкнуть объект в определенном направлении, например, ракету или пулю. Вы можете использовать силу, чтобы сделать прыжок персонажа.

Matter.Body.applyForce(this.physicsBox, { x: this.physicsBox.position.x, y: this.physicsBox.position.y }, { x: 0, y: -0.15 })

Настройка проекта

Вы можете настроить приведенный выше проект (с Typescript или без него), используя Parcel для объединения ваших модулей:

npm install -g parcel-bundler
npm install matter-js
npm install @types/matter-js
npm install typescript

Затем вы можете запустить проект в режиме просмотра, используя

Или построить весь проект, используя

parcel build dev/index.html --public-url ./

Заключение

Надеюсь, этот пост не стал слишком длинным! Я думаю, что этот подход очень забавен, но действительно ли он полезен по сравнению с использованием холста для моделирования физики? Хорошо…

  • Элементы холста не могут иметь прослушивателей событий
  • В Canvas нет красивого дерева DOM, по которому можно было бы пройти.

Недостатки:

  • Рендеринг и структура игры слишком переплетены (вы не можете легко переключиться на рендеринг холста на поздней стадии разработки).
  • Если вы хотите, чтобы вокруг прыгали тысячи (или десятки тысяч) объектов, холст гораздо эффективнее.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *