ASCII анимация с помощью спрайта, элемента canvas и JavaScript


Содержание

ASCII анимация с помощью спрайта, элемента canvas и JavaScript

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1

Всем привет. Пару дней назад совершенно случайно наткнулся в залежах дисков на «Космические рейнджеры 2: Доминаторы». Устанавливать не стал, так как сейчас не хватает времени, чтобы как следует в неё погрузиться. А решил посмотреть, что на диске находится. Посмотрел «Фан-Арт» и там увидел программку для ковыряния ресурсов рейнджеров. Вот и решил посмотреть, из чего же сделаны наши доминаторы. Покликав немного, нашел файлики с анимацией в формате GAI. Начал любоваться той анимацией. Захотел их сохранить в «гифки», но не как не давала та программка сохранить анимацию? Можно либо сохранить текущий кадр, либо все файлы в PNG. Я решил сохранить все кадры, а их было — 150. Картинки все есть, а почему бы не сделать с ними ту же анимацию.

Для того чтобы порадовать себя такой анимацией взял в помощь CSS + JS. А что мне делать со 150-ю файлами изображений? Их вес не критичен, хоть и весят они в сумме больше мегабайта. Главные проблемы с их одновременной загрузкой и манипуляцией. Поэтому я решил «склеить» их в одну. Грузить только одну, да и при помощи CSS + JS придется только правильно позиционировать её.

Осталось выбрать метод «склейки». Я же программист, а мы все ленивые:), поэтому я сразу отбросил ручную склейку в графическом редакторе. Первым делом я бросился, как обычно, к PHP и библиотеке GD. Но она оставляет желать лучшего по работе с полупрозрачными PNG. Дальше я подумал, а чем же ещё можно «склеить» картинки? И остановился на том, что сейчас у всех на слуху, что считается сейчас модным — HTML5. За работу с графикой у него отвечает — Canvas, причем мне очень нравится эта «вкусняшка». Вот поэтому все же решил «клеить» на «холсте».

И так добавлю я ка этот тег в HTML:

В JS укажу маску для имени картинки, первую картинку и номер последней (мне не пришлось переименовывать картинки, так как они все идут по порядку). Это должно выглядеть примерно так:

var first = ‘000’; //номерная часть имени первой картинки
var last = 49; //номер последней картинки
var num = 0; //итератор

var maskFileName = [‘2HULL_PEOPLE_P_A_’, ‘.png’];//маска имени картинки
var dir = ‘ship’; //директория, в которой лежат картинки

Теперь можно указать размеры спрайта который должен получиться, и получить его контекст:

var canvas = document.getElementById(«sprite»); //выберем наш канвас
canvas.w >canvas.height = 75;
var w >var context = canvas.getContext(«2d»); //получаем контекст

Для облегчения перевода из числа в строку (аналог str_pad из PHP) написал функцию-преобразователь с диким названием — zerofikator():

function zerofikator(int, length) < //на вход получаем число и длину строки
var prefix = »;
for (var i = num.toString().length; i //при этом каждый раз сдвигаем на ширину изображения, чтобы рисовать справа от предыдущего рисунка, а не на нем
if (zerofikator(num, first.length) != zerofikator(last, first.length)) <
//проверяем достигли ли мы последнего рисунка
num++; //увиличуем итератор
draw(); //и запускаем функцию вновь
>
>
img.src = dir + ‘/’ + maskFileName[0] + zerofikator(num, first.length) + maskFileName[1]; //собираем имя файла картинки для загрузки
>

draw(); //вызываем функцию впервые

После запуска такой страницы мы увидим широкое покадровое изображение, которое если мы сохраним, то сможем называть спрайтом. Кстати, сохраненный спрайт весит 615 KB, а 150 картинок 1 189 KB, хм, вот и ещё один плюс:).

Ну а теперь, можно приступить и к анимации.

В HTML добавляем пару «дивчиков», с которыми мы дальше будем работать:

Дальше я написал функцию, которая анимирует спрайты, но настройки решил вынести отдельно, для того чтобы можно было его использовать сразу для нескольких «анимашек»:

var styles = <>;
styles.cursor = ‘pointer’; //чтобы видно было что это наш элемент, меняем курсор
styles.w ; //размеры элемента
styles.height = ’75px’;
var element ; // id элемента, в котором будет анимация
var imgName = ‘canvas.png’; // имя файла спрайта

А далее сама функция:

function spriteAnimation(elementId, imgName, styles) <

var img = document.createElement(‘img’);
var offset = 0;
img.onload = function () < //как только спрайт загружается
var element = document.getElementById(elementId);
element.style.cursor = styles.cursor;
element.style.w > element.style.height = styles.height;
element.style.background = «url(‘» + imgName + «‘) » + offset + «px 50%»; //меняем стили для нашего элемента
var i = 0;
element.onmouseover = function() < //вешаем обработчик на наведение мыши
interval = setInterval(function() < //запускаем интервал
if (offset < img.width) < //для смены позиции изображения
i++; // если дошли до конца спрайта
> else <
i = 0; // то возвращаемся к началу
>
offset = 75 * i; //сдвиг по слайду
element.style.background = «url(‘» + imgName + «‘) » + offset + «px 50%»;
//меняем позиционирование спрайта
> , 1000/24) //24 кадра в секунду
>
element.onmouseout = function() < //вешаем обработчик на убирание курсора мыши
clearInterval(interval) //удаляем интервал (прекращаем анимацию)
>
>
img.src = imgName; //даем имя нашего спрайта
>

Ах да, нужно ведь ещё вызвать эту функцию:

spriteAnimation(elementId, imgName, styles);
spriteAnimation(‘ship’, ‘ship.png’, styles);

И чтобы смотрелось к месту можно добавить картинку с фоном и правильно спозиционировать:

Canvas: основы работы с изображениями, спрайты

Здравствуйте, уважаемые читатели!

В сегодняшней статья я хотел немного рассказать про работу с изображениями с помощью Canvas Api.

Данная статья является продолжением линейки статей про Canvas. Первая статья здесь: Canvas, основы работы с помощью JavaScript.

Естественно, что в Canvas есть возможность работать с изображениями. Функционал достаточно богат, но мы рассмотрим лишь самые основные возможности. Для более детального изучения всегда можно заглянуть в полную документацию и ознакомиться. По Canvas написано много учебников с хорошими примерами.

Как правило, работая с Canvas мы используем какие-либо библиотеки (я, например, привык использовать konvajs), так как нативный Canvas достаточно громоздкий. Народные умельцы помогли нам и сделали множество удобных библиотек, которые облегчают работу с изображениями и с другими возможностями Canvas.

Основы работы с изображениями

В принципе всю работу с изображениями можно свести к 2-м действиям:

  1. Загрузка изображения
  2. Добавление изображения на холст после наступления callback-а загрузки

Приведем простой пример:


Если мы попытаемся вывести изображение где-то до вызова onload у img, то изображение попросту не отобразиться.

Для вывода нашего изображения нам понадобится функция drawImage()

С помощью этой функции мы можем вывести наше изображение на экран (1), изменить размер изображения (2) либо вырезать какую-либо часть изображения (3).

Сложность может вызвать возможность вырезания изображения. Сложно соотнести, где какие параметры. Изображение ниже хорошо иллюстрирует, какие параметры на что влияют:

Если мы дополним пример выше, то получим следующий несложный пример:

Пожалуй, в 90% случаев этих 3-х возможностей будет достаточно ��

Немного о спрайтах в Canvas

Sprite — графический объект в компьютерной графике. Чаще всего — растровое изображение, свободно перемещающееся по экрану.

Один из примеров спрайтов, которые я использовал при создании игр:

Если простыми словами, то спрайт — это некоторое изображение, которое, как правило, состоит из кадров анимации. И если мы будем перемещать кадры, то создастся эффект движущейся картинки.

Примером ниже на Canvas можно воспроизвести анимацию героя выше, если в игровом цикле передавать правильные параметры X и Y:

Здесь мы вырезаем квадратное изображения в 50 пикселей и рисуем его на экране. При этом квадрат вырезается из указанной точки изображения (X;Y).

Код анимирования спрайтов я тут приводить уже не буду. Примеры были в других статьях по разработки игр на Canvas ��

В следующий раз хочу сделать небольшую обзорную статью про Canvas и WebGL.

Жду вас в следующих статьях!

Подписывайтесь на рассылку ��

Спасибо за внимание!

Автор статьи: Alex. Категория: JavaScript
Дата публикации: 11.07.2020

JS анимация. Остается след

Здравствуйте. Надо нарисовать с помощью Canvas и JavaScript анимацию падающего примитива. Так вот. Как сделать так, чтобы он не оставлял предыдущее состояние?

Javascript
29.03.2020, 16:58

На фоне остается след от анимации
Здравствуйте. Помогите пожалуйста с этой проблемой, повторюсь — остается след на фоновой картинке.

Остается след блока при перемещении
В общем раньше не встречался с такими проблемами. Да и не верстаю я уже ооочень долго но наконец-то.

После движения шарика остается след
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick Dim Mercuriy.

Движение шарика — остается след от движения
Всем привет! Помогите пожалуйста дописать программу! Есть шарик, который перемещается в.

Canvas. При перемещении объекта остается след
Есть объект PaintBox, на канву которого выводится тайловая карта. Поверх этой карты выводится.

HTML5 Canvas — анимация

Нарисовать одну картинку может казаться достаточно обескураживающей задачей. Поэтому не удивительно, что даже закаленные веб-разработчики рассматривают с определенным трепетом идею рисования нескольких десятков изображений каждую секунду. Основная трудность с анимацией состоит в необходимости обновлять отображение содержимого холста достаточно быстро, чтобы оно выглядело натурально движущимся или изменяющимся.

Анимация — это очевидная и необходимая составная часть для определенных типов приложений, таких как игры в режиме реального времени и эмуляторы физических процессов. Но для намного более широкого диапазона страниц на основе холста лучше применять более простые типы анимации. Так, анимацию можно использовать для выделения действий пользователя, например, подсвечивать фигуру при наведении на нее курсора мыши или заставлять ее пульсировать или мерцать.

Анимацию также можно использовать для привлечения внимания к изменениям содержимого, например, постепенно вводить новый вид или создавать графики и диаграммы, «вырастающие» в требуемую позицию. Такие способы использования анимации являются мощным средством для придания глянца веб-приложениям.

Простая анимация

Сделать анимацию из элемента на холсте HTML5 достаточно просто. Для этого устанавливается таймер, который постоянно вызывает элемент, обычно 30 или 40 раз в секунду. При каждом вызове код полностью обновляет содержимое всего холста. Если код написан правильно, постоянно сменяющиеся кадры сольются в плавную, реалистичную анимацию.

JavaScript предоставляет два способа для управления этим повторяющимся обновлением содержимого холста:

Функция setTimeout()


Эта функция дает указание браузеру подождать несколько миллисекунд, а потом исполнить фрагмент кода, в данном случае код для обновления содержимого холста. По окончании исполнения кода функция setTimeout() выполняется опять, вновь вызывая код обновления холста, и так до тех пор, пока анимацию не нужно завершить.

Функция setInterval()

Эта функция дает указание браузеру исполнять фрагмент кода через регулярный интервал времени, например каждые 20 мс. Эффект от этой функции, по большому счету, такой же, как и от функции setTimeout(), но функцию setInterval() нужно вызывать только один раз. Чтобы остановить повторяющийся вызов кода браузером, исполняется функция clearInterval().

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

При вызове функции setTimeout() передаются два параметра: название функции, которою нужно выполнить, и период времени ожидания перед исполнением этой функции. Время ожидания указывается в миллисекундах (т.е. тысячных секунды), таким образом, 20 мс (обычная задержка при анимации) равняется 0,02 с. Далее показан пример такого кода анимации с использованием функции setTimeout():

Этот вызов функции setTimeout() является ключевой частью любой задачи анимации. Допустим, что мы хотим создать анимацию квадрата, падающего сверху вниз страницы. Для этого нам нужно отслеживать позицию квадрата, используя две глобальные переменные. После нам надо просто изменять позицию при каждом исполнении функции drawFrame(), а потом перерисовывать квадрат в новой позиции:

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

Для более утонченной анимации потребуются более сложные вычисления. Например, предыдущий пример можно немного усложнить, ускоряя падение квадрата, чтобы эмулировать силу притяжения, или отскакивать от «пола», для чего потребуются более сложные математические расчеты, чем для единообразного движения вниз. Но основной подход — установка таймера, вызов функции рисования и обновление содержимого всего холста — остается точно таким же.

Анимация нескольких объектов

Теперь, когда мы освоили основы анимации и рисования интерактивной графики на холсте, настало время сделать следующий шаг и совместить эти навыки. Сделаем мы это на примере программы анимации падающих «мячиков», как показано на рисунке ниже:

Эта программа анимации позволяет добавлять в холст неограниченное количество мячиков. Программа предоставляет опцию выбора размера мячика (радиус по умолчанию — 15 пикселов) и соединения мячиков линиями, как показано справа на рисунке. Каждый добавленный в холст мячик двигается независимо от других, падая с ускорением, пока не столкнется с нижним краем холста, потом отскакивает от него и начинает двигаться в другом направлении.

В этой программе используется уже знакомый нам по предыдущему разделу метод setTimeout(), но сейчас код рисования должен управлять практически неограниченным количеством падающих мячиков.

Добавьте базовую разметку для примера:

Для управления всеми этими шариками мы воспользуемся пользовательским объектом. В данном случае нам нужно отслеживать массив объектов Ball и кроме позиции (представляемой свойствами x и y) для каждого мячика нужно еще отслеживать и скорость (представляемую свойствами dx и dy):

В математике выражение dx обозначает скорость изменения абсциссы, а dy — скорость изменения ординаты. Поэтому по мере падения мячика значение x для каждого кадра увеличивается на величину dx, а значение y — на величину dy.

При нажатии кнопки «Добавить мячик» простой код создает новый объект Ball и сохраняет его в массиве balls:

Кроме очистки холста, кнопка «Очистить холст» также очищает массив balls:

Но ни функция addBall(), ни функция clearBalls() в действительности не только ничего не рисуют, но даже не вызывают функцию для рисования. Вместо этого код страницы устроен таким образом, чтобы вызывать функцию drawFrame(), которая прорисовывает холст каждые 20 мс:

Функция drawFrame() является ключевой частью этого примера. Она не только рисует мячики на холсте, но также и вычисляет их текущую позицию и скорость. В функции drawFrame() выполняется несколько разных вычислений, чтобы более реалистично эмулировать движение мячиков, например, ускорение мячиков при падении и замедление, когда они отскакивают от препятствий. Полный код функции выглядит так:

Хотя весь этот объем кода может вызывать легкий страх, общий подход остался прежним. Код исполняет следующие операции:

Перебирает в цикле мячики в массиве.

Корректирует позицию и скорость каждого мячика.

Рисует каждый мячик на холсте.

Устанавливает время ожидания (функция setTimeout) для вызова метода drawFrame() опять 20 мс.

Сложным здесь является шаг 3, в котором корректируются позиция и скорость мячиков. Уровень сложности этого кода может быть таким, каким этот код пожелает разработчик, в зависимости от эффектов, которые он пытается реализовать. Особенно трудно поддается моделированию плавное, природное движение, требующее более сложных математических вычислений.

Наконец, теперь, когда мы можем отслеживать каждый мячик, добавить интерактивность не составляет труда. По сути, можно использовать практически тот же код, который применялся для определения щелчков по кругу в программе рисования кругов из предыдущей статьи. Но только в данном случае мы хотим делать что-то другое с мячиком, по которому щелкнули, например ускорить или изменить направление его движения:

Довольно впечатляющую версию этого примера, можно исследовать на странице HTML5 Canvas Google Bouncing Balls. Здесь наведение курсора мыши на мячики разбрасывает их в разные стороны (как именно, зависит от того, каким образом наводится на них курсор), а если отвести курсор, мячики собираются в слово «Google».

Производительность анимации

Так как для анимации требуется постоянно обновлять нарисованную графику, очевидно, что эта задача будет намного требовательней к возможностям холста, чем обычное рисование. Но холст справляется с этой трудной задачей на удивление хорошо.

В современных браузерах применяются такие средства повышения производительности, как аппаратное ускорение, при котором определенный объем обработки графики передается видеокарте компьютера, вместо применения центрального процессора для выполнения всех задач. И хотя JavaScript — не самый быстрый из языков программирования, на нем вполне можно создавать сложные высокоскоростные анимации, включая аркадные игры в режиме реального времени, не используя ничего, кроме кода сценариев и холста.

Но производительность холста может быть проблемой в случае маломощных мобильных устройств, таких как iPhone или устройства с операционной системой Android. Результаты тестов показывают, что анимация, которая может выполняться на настольном компьютере со скоростью 60 кадр/с (кадров в секунду), будет исполняться на среднем смартфоне рывками, с максимальной скоростью 10 кадр/с.

Поэтому, если вы хотите создавать приложения для мобильных устройств, прежде чем углубляться в разработку, обязательно протестируйте их производительность для таких устройств и будьте готовы пожертвовать некоторыми второстепенными украшениями анимационной программы, чтобы ее основная функция работала без проблем.

Анимация на холсте для ленивых

Мне действительно нужно выполнять все вычисления самому?

Самый значительный недостаток анимации на холсте состоит в необходимости выполнять все вычисления самому разработчику. Например, если нужно, чтобы изображение двигалось от одной стороны холста к другой, разработчику надо рассчитать координаты каждого кадра, а потом нарисовать его в соответствующей позиции.

А если требуется анимировать одновременно несколько предметов разными способами, объем и сложность необходимых для этого вычислений могут очень быстро выйти из под контроля. Поэтому намного легче жизнь разработчиков, использующих подключаемый модуль, такой как Flash или Silverlight. Обе технологии имеют встроенную систему анимации, которая позволяет разработчикам давать команды наподобие «переместить эту фигуру из этой точки в ту за 45 секунд» или, еще лучше, «переместить эту фигуру от верхнего края окна к нижнему, применяя эффект ускорения, вследствие которого фигура слегка отскакивает, достигнув нижнего края».


Нет сомнений, что однажды кто-то изобретет высокоуровневую систему анимации, которую можно будет наложить поверх холста. В идеальном случае такая система анимации позволит разработчику реализовывать желаемые эффекты, не требуя написания многочисленных страниц кода для математических вычислений. Вероятнее всего, что такой высокоуровневой системой анимации будет не усовершенствование основной спецификации HTML, а библиотека JavaScript. Но на данном этапе слишком рано говорить, какие средства разработки будут наиболее эффективными, с наименьшим количеством ошибок и с наивысшим уровнем поддержки.

Желеобразная анимация с Canvas. Рисование и анимация на JavaScript Canvas. Часть 1

В этом уроке мы научим вас создавать и анимировать фигуры с эффектом желе. Вы сможете создать желеобразную форму и оживить ее в соответствии с вашими потребностями без особых усилий. В частности, в первой части мы увидим, как добиться следующего результата:

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

В то же время мы были вдохновлены работой Тома Чиоволони и игрой «The Floor is Jelly», поэтому мы специально начали с реализации желеобразной физики.

Результат вылился в библиотеку, которую мы назвали jelly.js, в которую мы добавили все, что нужно, чтобы получить желеобразую форму. Давайте посмотрим, как ее использовать!

Создание фигур с помощью SVG

Мы решили создавать фигуры с помощью SVG, потому что это самый простой способ: мы можем создавать нужные нам формы в векторном редакторе (например, Inkscape или Illustrator) и вставлять их непосредственно в наш HTML-документ или даже импортировать их из JavaScript. Создадим вот такую простую форму в векторном редакторе:

Затем включим соответствующий SVG-код непосредственно в HTML:

Настройка HTML разметки

Нам также потребуется canvas, чтобы нарисовать фигуру и другие элементы с целью перемещения буквы «S» относительно средней точки формы.

Немного CSS

Для этого примера нам нужно совсем CSS стилей:

Давайте сделаем желе

Наконец, мы подошли к самой интересной части! Давайте нарисуем наш пятиугольник на canvas и анимируем его. Не беспокойтесь, — это будет очень просто с помощью нашей библиотеки.

Нам просто нужно несколько строк кода, чтобы нарисовать наш пятиугольник и заставить его пенять форму, если мы переместим мышь к краям фигуры:

Обратите внимание, что конструктор нашей библиотеки (jelly.js) получает элемент canvas и набор опций. Мы также можем предоставить массив опций или набор параметров для каждой фигуры, которую мы хотим рисовать. Подробное описание доступных опций вы можете проверить на Github репозитории .

Можно было бы оставить так и ничего не менять, но у нашей библиотеки еще есть огромный потенциал. Итак, давайте посмотрим, что мы еще можем сделать.

Внедрение желеобразного перетаскивания

Чтобы проиллюстрировать немного больше возможностей, которые у нас есть (и для удовольствия), давайте посмотрим, как мы можем поколебать наш пятиугольник, когда мы перетаскиваем его по экрану. Для этого нам нужно знать, когда указатель мыши находится внутри формы, чтобы перетащить ее только в этом случае. Взгляните на следующий код:

Давайте посмотрим, как мы можем реализовать базовую логику перетаскивания. Пожалуйста, ознакомьтесь с комментариями, чтобы разобраться в происходящем и обратите особое внимание на функцию shake:

Производительность и поддержка браузерами

Все современные браузеры поддерживают canvas, но jelly.js использует промисы, поэтому вам потребуется полиполк для браузеров, которые не поддерживает промисы.

Производительность эффекта варьируется в зависимости от браузеров и операционных систем. Это связано с интенсивной работой процессора в каждом анимационном кадре, поэтому не злоупотребляйте использованием этих эффектов на сайте.

Заключение

Мы создали поистине желеобразный пятиугольник без особых усилий. Наша форма также изменяет курсор при наведении и реагирует на перетаскивание! Результат вы можете увидеть здесь или скачать и протестировать локально.

Это не единственное, что мы можем сделать. Во второй части нашего урока мы построим удивительный слайдер, где все будет одно сплошное желе. В общих чертах мы узнаем, как:

  • Нарисовать больше желе-форм и текст!
  • Использовать изображения внутри фигур, а не только сплошные цвета.
  • Анимировать фигуры, чтобы показать их или плавно скрыть.
  • Менять форму желе.
  • Сделать весь слайдер адаптивным.

Cool Ascii Animation using an Image Sprite, Canvas, and Javascript

Description

Images can be converted into ascii art by turning the pixels grayscale and representing them using text characters. Dense characters are used for dark pixels and sparse characters are used for light pixels.

In this lesson, HTML5 canvas is used to read the sprite’s pixel data which is then converted to grayscale. A character map is then derived from the pixels’ grayscale values and injected into the DOM making up the ascii art.

Finally Javascript is used to move the ascii version of the sprite in steps to create the animation.


14 Comments

Egypt Urnash

Oh man that long string of ifs in the number-to-character function makes me weep.

Here is something that will give SLIGHTLY different results but is a TON more succinct:

in the variables section:
var greys = “@@WWWW#*:` “;

replace all those “if (gray > n) character = ‘x’” lines with:
character = greys.charAt(Math.floor(gray/25));

This will give you a SLIGHTLY different balance of : versus ‘. If you were really persnickety you could make the ‘greys’ string 51 characters long, and repeat the characters so that you get the exact same results. Or have a much wider set of characters!

LazerFX

Nice article… this HTML5 stuff is really, really cool.

I didn’t like the way things repeated constantly, so I added a couple of new variables (
var waiting = 0;
var rndWait = Math.floor(Math.random()*11);) at the start, and modified the player function to:

if(current_ml == frame_width*(frames-1)*-1 || waiting

Sonja

Thanks for sharing, this is really inspiring.

Unfortunately my asci animation always disappeared (in Firefox) after the first loop and d >

I fixed it by changing the operator here:
if(current_ml == frame_width*(frames-1)*-1)
into:
if(current_ml

Sonja

Clement

Sweet! I never imagined it was possible to decompose an image (sprite here) into pixels and into characters (never actually looked on how ascii art was done thought).
Thanks for sharing :)

javad

wow it is best tutorial that i see .
thanks. have a good time

pradeep

it is not working

Why this doesn’t work on IE9+ ?
Even with a polyfill I can’t get it to work…
Anyone?

pradeep

to make this work you need to upload to the html,css,js and sprite png to webhosting site..
this is becoz of some security issues with the browsers

Mfarooqi

excellent work dear.. I really love it. :) .. i didn’t know how easy is this..

JavaScript Canvas скорость спрайт анимации

У меня есть проблема с холстом анимацией. Я работаю с этой обучающей программе . Это довольно просто, но теперь я хочу сделать анимацию с 60 кадров в секунду. Я попробовал setInterval(Update, 1000/60) , и, конечно, работает , но теперь есть проблема с спрайта. Его анимация слишком быстро. Есть ли способ сделать 60fps и замедлить характер спрайтов анимации (чтобы выглядеть более естественно)?

Мне жаль, что я не живой пример, но это немного трудно создать без передачи файлов для спрайтов.

код:

Всякий раз , когда вы двигаете спрайт, вы должны разделить количество пикселей , перемещаемого количеством кадров в секунду. Например, если вы хотите , чтобы переместить его dx пикселей в секунду при 60fps, определяют var fps = 60; как глобальные переменные и делать , x += dx/fps; когда вы перемещаете его. Какова была частота кадров до этого ? 30 кадров в секунду или что — то? Как бы то ни было, если вы хотите, чтобы идти с той же скоростью , как и раньше в 60fps, сделать свой dx равным однако количество пикселей пройденных в секунду, умножив ваш предыдущий dx на кадр. Так что, если он движется в 10px на кадр 30 кадров в секунду, делают var dx = 300; .

Вы можете «душить» Обновление () для выполнения реже.

Если пользователь нажимает клавишу можно заставить анимацию, установив счетчик в 0.

Create a Sprite Animation with HTML5 Canvas and JavaScript


Sprite animations can be drawn on HTML5 canvas and animated through JavaScript. Animations are useful in game and interactive application development. Several frames of an animation can be included in a single image and using HTML5 canvas and JavaScript we can draw a single frame at a time.

This tutorial will describe how HTML5 sprite animations work. We will go step by step through the process of creating a sprite animation. At the end of the this article we will use the animation we created in a simple HTML5 game.

The example code is based off the game development framework: BlocksJS. The full game framework with additional features can be downloaded from BlocksJS on GitHub. The source code for the examples in the article is available at the end.

What is a Sprite Animation?

Two dimensional frame-based animation can be achieved on HTML5 canvas by rendering an area of a single image on a given interval. The following five frame animation is rendered on a HTML5 canvas at one frame per second (1 fps).

Using the drawImage method of the canvas context we can change the source position to only draw a cropped portion of one image called a «sprite sheet».

What is a Sprite Sheet?

HTML5 canvas animation sprite sheets are fundamentally the same as CSS sprite sheets. A sprite sheet consists of muliple frames in one image. The following sprite sheet has 10 frames. The width of the image is 460 pixels. Therefore the frame width is 460/10 or 46 pixels.

Now Let’s Create a Sprite Animation

Let’s start by loading the sprite sheet image for the coin animation. Create a new Image object and then set its src property to the filename of the image which will load the image.

Next we define the sprite object so we can create one (or more later). Invoking the object will simply return an object with three public properties.

Grab access to the canvas element using getElementById and then set its dimensions. We will need the canvas’s context to draw to later.

Now we can create a sprite object which we will call coin . Using the options parameter we set properties of the object which will specify: the context of the canvas on which the sprite will be drawn, the sprite dimensions, and the sprite sheet image.

DrawImage Method

The key to creating sprites from one image is that the context’s drawImage method allows us to render a cropped section of the source image to the canvas.

context.drawImage( img , sx , sy , sw , sh , dx , dy , dw , dh )

img Source image object Sprite sheet
sx Source x Frame index times frame width
sy Source y
sw Source width Frame width
sh Source height Frame height
dx Destination x
dy Destination y
dw Destination width Frame width
dh Destination height Frame height

We will use the drawImage method in our sprite’s render method to draw one frame at a time.

Render

Time to draw to the canvas. The sprite function will need a render method that invokes the drawImage method on the canvas’ context. The parameters specify the source image and the bounding rectangle dimensions and position of the source sprite sheet and the destination canvas context.

Oh, and call the render method.

We have drawn the coin, but where is the animation?

Update

We need a method so we can update the position of the sprite sheet’s bound rectangle. Let’s call it. update . We need also need to keep track of where the animation is so let’s create some properties:

frameIndex The current frame to be displayed tickCount The number updates since the current frame was first displayed ticksPerFrame The number updates until the next frame should be displayed

We could just increment the frame index every time we call the update method, but when running a game at 60 frames per second we might want the animation to run at a slower fps. Tracking the ticks let’s use delay the animation speed. For example we could run the sprite animation at 15 fps by setting the ticksPerFrame to 4 on game loop running at 60 fps.

Each time the update method is called, the tick count is incremented. If the tick count reaches the ticks per frame the frame index increments the tick count resets to zero.

The render method can now move the bounding rectangle of the source sprite sheet based on the frame index to be displayed by replacing the sprite width with the frame width: that.width is replaced with that.width / numberOfFrames .

This works until the frame index is greater than the number of frames. We need a new property numberOfFrames and a conditional to ignore out of range values.

We want our coin to keep spinning after the first go around. We will need a new loop property and a conditional which resets the frame index and tick count if the last frame.

But wait! Without a loop the update will only run once. We need to run the update on a loop.

RequestAnimationFrame

We use requestAnimationFrame (See Paul Irish’s post for a requestAnimationFrame polyfill for support in older browsers) to update and render the sprite at the same rate that the browser repaints.

Close, but something is not quite right.

ClearRect Method

The clearRect method allows us to clear a region of the destination canvas between animation frames.


context.clearRect( x , y , width , height )

x Clear rectangle x position
y Clear rectangle y position
width Clear rectangle width
height Clear rectangle height

Clearing the canvas between frames gives us our complete sprite animation.

Sprite Animation Demo

Demo can be loaded here or downloaded at the end of the article.

Coin Tap Game

Now that we have learned how to create a sprite animation on HTML5 canvas we can use the game loop and animation to create a game. Let’s keep the game simple: tap a coin to get points.

To create our game we need to add a couple of event listeners for desktop ( mousedown ) and mobile ( touchstart ) and then use a simple circle collision detection to determine if the coin is tapped. If a coin is hit we remove the coin and create a new one resulting in a score based on the coin size. When creating new coins the size and speed of spin are randomized.

We are drawing more than one sprite on the canvas now, so instead of clearing the canvas when we render a sprite we need to we need to clear the canvas at the beginning the game loop. If we didn’t we would clear the all the previous sprites.

With these updates we can create our Coin Tap Game; let’s give it a try!

Простые анимации

Вероятно, самым большим ограничением является то, что когда фигура нарисована, её уже нельзя двигать. Чтобы изобразить движение нам нужно перерисовать фигуру и всё, что было нарисовано до неё. Перерисовка сложных кадров занимает много времени, и производительность сильно зависит от скорости компьютера, на котором она выполняется.

Основные шаги анимации

Ниже перечислены необходимые шаги для того, чтобы нарисовать кадр:

  1. Очистить canvas
    Если фигура, которую вы собираетесь нарисовать, не занимает всю площадь canvas (как фон, например), то всё что было нарисовано ранее необходимо стереть. Проще всего это сделать при помощи метода clearRect() .
  2. Сохранить изначальное состояние canvas
    Если вы изменяете любые настройки (такие как стили, трансформации и т.п.), которые затрагивают состояние canvas и вы хотите убедиться, что оригинальное состояние используется каждый раз, когда был отрисован кадр, то вам следует сохранить это оригинальное состояние.
  3. Нарисовать анимированные фигуры
    Шаг на котором вы собственно отрисовываете кадр.
  4. Восстановить состояние canvas
    Если вы сохраняли состояние, восстановите его, прежде чем отрисовывать новый кадр.

Управление анимацией

Фигуры отрисовываются на canvas либо напрямую — при помощи методов canvas, либо с помощью сторонних функций. В нормальной ситуации результат станет виден на canvas после окончания выполнения скрипта. К примеру, цикл for использовать для анимации нельзя.

Это значит, нужен способ выполнения функций отрисовки через интервалы времени. Есть два способа для управления такой анимацией.

Запланированные обновления

Первый — это функции window.setInterval() , window.setTimeout() , и window.requestAnimationFrame() , которые могут быть использованы для вызова некоторой функции, через заданный промежуток времени.

setInterval(function, delay) Начинает периодически исполнять функцию function каждые delay миллисекунд. setTimeout(function, delay) Запускает выполнение указанной функции function через delay миллисекунд. requestAnimationFrame(callback) Сообщает браузеру, что вы хотите выполнить анимацию, и запрашивает, чтобы браузер вызвал указанную функцию callback для обновления анимации перед следующей перерисовкой.

Если вы не планируете никакого взаимодействия с пользователем, вы можете использовать функцию setInterval() , которая многократно выполняет, предоставленный ей код. Если же вы планиуете создать игру, в которой контроль анимации осуществляется мышью или клавиатурой, то необходимо использовать setTimeout() . Установив EventListener , вы можете перехватываете любые действия пользователя и запустить соответствующие функции анимации.

В примерах ниже мы будем использовать функцию window.requestAnimationFrame() для контроля анимации. Функция requestAnimationFrame является более эффективной для создания анимации, так как новая итерация вызывается, когда система готова к отрисовке нового кадра. Количество вызовов в секунду примерно равно 60 и уменьшается, когда вкладка неактивна. Для более подробного изучения цикла анимации, особенно для игр, прочитайте статью Анатомия видеоигр В Зоне разработке игр.

Анимированная солнечная система

В этом примере анимируется небольшая модель солнечной системы.

Screenshot Live sample

Анимированные часы

В этом примере создаются анимированные часы, показывающие правильное время.

Screenshot Live sample

Зацикленная панорама

В этом примере панорама прокручивается слева направо. Мы используем фото национального парка Йосемити взятое из Википедии, но вы можете использовать любое изображение, большее элемента canvas.

Заметьте, что ширина и высота должны совпадать со значениями CanvasXZSize и CanvasYSize .

Анимация

Анимация через requestAnimationFrame


Теперь, когда мы знаем, как нарисовать много интересных штук, давайте оживим их. Первое, что нужно знать об анимации — это просто рисование одного и того же снова и снова. Когда вы вызываете функцию рисования, то она сразу же добавляет что-то на экран. Если вы хотите анимировать это, просто подождите несколько миллисекунд и нарисуйте это заново. Конечно, вы не хотите сидеть в ожидании пока цикл не прервётся браузером. Вместо этого вы должны нарисовать что-то, затем попросить браузер вызвать это снова через несколько миллисекунд. Самый простой способ сделать это — с помощью функции JavaScript setInterval() . Она будет вызывать вашу функцию рисования каждые N мс.

Однако в реальности мы никогда не должны использовать setInterval . setInterval всегда будет рисовать с одной скоростью, независимо от того, какой у пользователя компьютер, что делает пользователь и активна ли текущая страница. Короче говоря, это работает, но не эффективно. Вместо этого мы должны использовать новый API requestAnimationFrame .

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

requestAnimationFrame становится стандартом, но большинство браузеров поддерживает только свои собственные версии с префиксом. Например, Chrome использует webkitRequestAnimationFrame , а Mozilla поддерживает mozRequestAnimationFrame . Чтобы исправить это, мы воспользуемся скриптом Пола Ириша. Он просто соединяет разные варианты в новой функции: requestAnimFrame .

Попробуем простой пример, в котором мы анимируем прямоугольник на экране.

Базовая анимация прямоугольник с помощью requestAnimFrame (щёлкните для запуска)

Очистка фона

Теперь вы заметили проблему. Наша прямоугольник движется по экрану, обновляясь на пять пикселей через каждые 100 миллисекунд (или 10 кадров в сек.), но старый прямоугольник остаётся. И выглядит так, что прямоугольник становится только длиннее и длиннее. Помните, что холст это просто набор пикселей. Если вы установите несколько пикселей, то они будут оставаться там до тех пор, пока не изменятся. Итак, давайте очистим холст в каждом кадре, прежде чем мы нарисуем прямоугольник.

Рисование прямоугольника через очистку фона (щёлкните для запуска)

Симулятор частиц

Это всё, что на самом деле нужно для анимации. Рисовать что-то снова и снова. Попробуем нечто немного более сложное: симулятор частиц. Мы хотим, чтобы некоторые частицы падали вниз по экрану подобно снегу. Для этого мы реализуем классический алгоритм симулятора частиц:

Симулятор частиц содержит список зацикленных частиц. В каждом кадре положение всех частиц обновляется основываясь на некотором уравнении, при необходимости частицы уничтожаются/создаются на основе некоторого условия. Затем частицы рисуются. Вот простой пример снега.

Вначале мы создаём основу симулятора частиц. Это функция цикла, которая вызывается каждые 30 мс. Для структуры данных нам требуется пустой массив частиц и счётчик тактов. На каждой итерации цикла выполняется четыре части.

Функция createParticles проверяет, сколько у нас частиц. Если их меньше 100, то создаёт новую частицу. Обратите внимание, что проверка выполняется только каждые 10 тактов. Это позволяет начать с пустого экрана, а затем постепенно наращивать число частиц, а не создавать все 100 с самого начала. Вы можете настроить параметры в зависимости от желаемого эффекта. Я использую Math.random() и другую арифметику чтобы убедиться, что снежинки располагаются в разных местах и не выглядят одинаковыми. Так снег становится более натуральным.

Функция updateParticles довольно простая. Она обновляет координату каждой частицы, добавляя ей скорость. Это заставляет снежинку двигаться вниз по экрану.

Вот killParticles . Она проверяет что частица находится ниже нижнего края холста. В некоторых симуляторах вы уничтожаете частицу и удаляете её из списка. Поскольку это приложение показывает непрерывный снег, то мы повторно задействуем частицу, установив её обратно в 0.

Наконец рисуем частицы. Опять же это очень просто: очистите фон, нарисуйте круг с текущими координатами, радиусом и цветом частицы.

Теперь это выглядит так.

Симулятор частиц для снега (щёлкните для запуска)

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

Анимация спрайтов

Что такое спрайт?

Заключительным основным видом анимации является анимация спрайта. Так что такое спрайт?

Спрайт — это маленькое изображение, которое вы можете быстро рисовать на экране. Обычно спрайт на деле вырезают из большого изображения, которое называется спрайт-лист или мастер-изображение. Такой лист может содержать несколько различных спрайтов, вроде разных персонажей игры. Спрайт-лист также может содержать один символ в разных положениях. В итоге это даёт вам разные кадры анимации. Это классический стиль анимации: просто пролистывать разные рисунки снова и снова.

Зачем и когда использовать спрайты?

Спрайты хороши для нескольких вещей.

  • Во-первых, спрайт это изображение, которое, вероятно, рисуется быстрее, чем векторы, особенно сложные.
  • Во-вторых, спрайты чрезвычайно удобны, когда вам нужно рисовать одну штуку снова и снова. Например, в игре Space Invaders у вас есть куча пуль на экране, которые все выглядят одинаково. Гораздо быстрее загрузить спрайт пули один раз и рисовать его снова и снова.
  • В-третьих: спрайты быстро загружаются и рисуются как часть листа. Это позволяет загрузить единый файл для всего набора спрайтов гораздо быстрее, нежели полученную кучу отдельных изображений. Спрайты, как правило, также сжимаются лучше. Наконец, используется меньше памяти для хранения одного большого изображения, чем куча более мелких.
  • В конце концов, спрайты удобны для работы с анимацией, потому что получаются из таких инструментов рисования, как Фотошоп. Код просто листает изображения и его не волнует, что на картинке. Это значит, что ваш художник может легко обновить графику и анимацию, не касаясь кода.

Рисование спрайтов

Спрайты легко нарисовать, используя функцию drawImage. Эта функция может рисовать и растягивать часть изображения путём указания разных исходных и конечных координат. К примеру, предположим, что у нас есть следующий спрайт-лист и мы просто хотим нарисовать пятый спрайт слева.

Мы можем нарисовать только этот спрайт, указав координаты исходника:

Анимация спрайта

Как вы можете видеть на полном спрайт-листе, на деле это разные кадры анимации одного объекта, так что теперь пролистаем разные спрайты, чтобы создать анимацию. Мы сделаем это, отслеживая текущий кадр с помощью счётчика тактов.

Каждый раз при обновлении экран мы вычисляем текущий кадр анимации глядя на счётчик тактов. Операция деления по модулю (%) на 10 означает зациклить кадр от 0 до 9 снова и снова. Затем вычисляется координата х в зависимости от количества кадров. После чего рисуется изображение и обновляется счётчик тактов. Конечно, это может происходить слишком быстро, так что вы можете делить такты по модулю на 2 или 3, чтобы анимация бежала медленнее.

Анимация каждые 10 кадров для детализации (щёлкните для запуска)

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

Цукерберг рекомендует:  Старпер-стартапер - 47 лет, 0 опыта
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих