Работа с частицами в Canvas
В продолжении темы разработки Арканоида, захотелось сделать какой-нибудь эффект разрыва блока при его уничтожении, для этого необходимо освоиться с работой частиц в canvas. Как работать с Canvas частицами сегодня и пойдет речь.
Чистый холст
Поскольку canvas изначально поддерживается большим количеством браузеров, у нас нет необходимости в каких-то дополнительных приготовлениях, мы просто создадим новый холст. [cce lang=»html»] [/cce] Кроме того, canavas можно добавить на страницу с помощью javascript
[cce lang=»javascript»]
var canvas = document.createElement(«canvas»);
var context = canvas.getContext(«2d»);
canvas.width = 200;
canvas.height = 200;
document.body.appendChild(canvas);
[/cce] Пока мы ничего не видим, но это не беда. Давайте продолжим писать наш код и начнем рисовать на canvas’е, мы уже создали context и будем использовать его далее. [cce lang=»javascript»] context.fillRect(0, 0, canvas.width, canvas.height); [/cce] Мы просто рисуем прямоугольник с координатами начала canvas’а и во всю ширину холста.
Представление частицы
Теперь давайте добавим частицу на наш холст и начнем проводить манипуляции уже с ней.
[cce lang=»javascript»]
// Рисуем частицу
context.fillStyle = «white»;
context.fillRect(300, 200, 10, 10);
[/cce]
Теперь мы будем рисовать частицу с помощью метода fillRect, вы можете указать частицу в форме круга или вовсе нужного вам рисунка. В предыдущем коде мы рисовали на канвасе во весь холст прямоугольник, но не указывали fillStyle, когда данный параметр не указан, стиль заливки по умолчанию будет черным. Пример отрисовки круглой частицы
[cce lang=»javascript»]
//Рисуем круглую частицу на холсте
context.beginPath();
context.fillStyle = «white»;
context.arc(500, 200, 10, 0, Math.PI*2, true);
context.closePath();
context.fill();
[/cce]
Движение частицы
Перемещение объектов на canvas’е происходит не совсем так, как обычных html элементов таких как div. Иллюзия перемещения создается с помощью покадровой перерисовки холста и предварительным очищением холста перед рисованием нового кадра. Для этого чаще всего используется функция requestAnimationFrame() или функции setTimeout или setInterval. Давайте продолжим расширять наш код и я приведу у дальнейший пример, для начала мы должны установить позицию частицы как переменные, чтобы в дальнейшем мы могли ее передвигать. [cce lang=»javascript»] var posX = 20, posY = 100; [/cce] Далее дополним наш код и добавим setInterval перерисовки холста
[cce lang=»javascript»]
// Рисуем частицу на холсте с интервалом в 30ms
setInterval(function() {
//Очищаем canvas context.fillStyle = «black»;
context.fillRect(0,0,canvas.width, canvas.height);
posX += 1;
//На каждой итерации меняем позиции X и Y
posY += 0.25;
// Рисуем частицу
context.beginPath();
context.fillStyle = «white»;
context.arc(posX, posY, 10, 0, Math.PI*2, true);
context.closePath(); context.fill(); }, 30);
[/cce]
Физика и случайности
Наша основная идея до этого заключалась в том, что мы брали просто частицу и передвигали ее на определенный интервал, меняя переменные позиций. Давайте введем понятие гравитации и векторной скорости, вынесем в новые переменные данные параметры.
[cce lang=»javascript»]
var vx = 10,
vy = -10,
gravity = 1;
[/cce]
Теперь векторная скорость говорит нам о том, что каждую итерацию (30мс) частица будет перемещаться на 10 пикселей вправо и 10 пикселей в низ. Теперь давайте заменим часть кода в нашем примере и добавим движение с прибавлением векторной скорости и прибавлением гравитации в векторной скорости по вертикали
[cce lang=»javascript»]
posX + vx;
poxY + vY;
posY + gravity;
[/cce]
Отскок
Для того, чтобы частицы не падали и имели некий отскок, мы можем дополнить логику и «переворачивать» (флиповать) векторную скорость по оси Y и домножать на произвольный коофицент отскока.
[cce lang=»javascript»]
if (posY > canvas.height * 0.75) {
vy *= -0.6; vx *= 0.75;
posY = canvas.height * 0.75;
}
[/cce]
Если положение частицы ниже чем две трети (*0.75) холста, то мы домножаем отскок на 60% (т.е. каждый следующий отскок будет ниже на 40%) в тоже время мы замедляем на 25% скорость по горизонтали при каждом отскоке.
Хаотичность
До этого момента мы рассматривали одну частицу и ее поведение, теперь давайте перейдем к созданию нескольких частиц и добавим случайности в их движение.
Создание частиц
Теперь нам необходимо расширить наш код и оптимизировать его для создания множества частиц. Для этого мы создадим функцию с именем Particle, которая будет создавать частицу и служить в роли генератора частиц, а также манипулировать ими. Также нам необходимо реализовать логику хаотичного перемещения для каждой частицы в отдельности. Первым делом вынесем все настройки будущих частиц в один объект. [cce lang=»javascript»] var particles = {}, particleIndex = 0, settings = { density: 20, particleSize: 10, startingX: canvas.width / 2, startingY: canvas.height / 4, gravity: 0.5, maxLife: 100 }; [/cce] Мы определили пустой объект Particles в котором мы будем хранить частицы, создали переменную для индекса и объект с настройками размера, стартовой позиции, гравитации и жизни. В место того, чтобы хранить частицы в массиве, мы будем использовать объект т.к. далее будет проще работать с ключами, а не с индексами. Вот функция, которая будет генерировать частицу.
[cce lang=»javascript»]
function Particle() {
// Устанавливаем позицию согласно настройкам
this.x = settings.startingX;
this.y = settings.startingY;
// Случайные X и Y скорости
this.vx = Math.random() * 20 — 10;
this.vy = Math.random() * 20 — 5;
//Увеличиваем индекс и добавляем частицу с новым индексом.
particleIndex ++; particles[particleIndex] = this;
this.id = particleIndex; this.life = 0;
}
[/cce]
Рисование множества частиц
Теперь для рисования мы должны расширить наш объект Particle и добавим в prototype метод draw
[cce lang=»javascript»]
Particle.prototype.draw = function() {
this.x += this.vx;
this.y += this.vy;
// Добавляем гравитацию
this.vy += settings.gravity;
// Отсчитываем жизнь
this.life++;
// Если жизнь частицы больше максимальной — удаляем
if (this.life >= settings.maxLife) { delete particles[this.id]; }
// Рисуем частицу
context.clearRect(settings.leftWall, settings.groundLevel, canvas.width, canvas.height);
context.beginPath();
context.fillStyle=»#ffffff»;
context.arc(this.x, this.y, settings.particleSize, 0, Math.PI*2, true); context.closePath(); context.fill();
}
[/cce]
Наш метод draw делает сразу несколько вещей. Во первых он регулирует скорость частицы и перемещает ее, т.к. значения скорости были случайны частица будем двигаться хаотично по обеим осям. Также наш метод подсчитывает жизни частицы и при необходимости удаляет устаревшие частицы, также мы корректируем направление по оси Y с учетом силы тяжести.
На этом можно подвести черту, далее вы можете добавлять и манипулировать своими условиями, создавать дополнительные ограничения и т.п., сам пост является вольным переводом вот от сюда. Там же можно увидеть дополнительные примеры. Если возникнут вопросы, обращайтесь, дополню статью.
Последняя редакция 11 октября, 2014 в 12:10