И так, сегодня я расскажу про создание простенького спрайтового движка, с поддержкой сортировки по глубине.
Для начала давайте создадим класс Sprite:
- function Sprite(_img, _frames) {
- this.img = _img;
- this.frames = _frames;
- this.frameWidth = _img.width/_frames;
- }
При создании спрайта мы передаем указатель на нашу картинку и количество кадров анимации, ширина одного фрейма рассчитается самостоятельно. Ах да, картинки которые буду использовать для теста:
Теперь нужно загрузить эти изображения и создать спрайты:
- var loaded = 0;
- var allImgs = 3;
- function imgonload() {
- loaded++;
- if (loaded == allImgs) {
- afterLoad();
- }
- }
- var img1 = new Image();
- img1.src = ‘img1.png’;
- img1.onload = imgonload;
- var img2 = new Image();
- img2.src = ‘img2.png’;
- img2.onload = imgonload;
- var img3 = new Image();
- img3.src = ‘img3.png’;
- img3.onload = imgonload;
- var spr1, spr2, spr3;
- function afterLoad() {
- spr1 = new Sprite(img1, 3);
- spr2 = new Sprite(img2, 3);
- spr3 = new Sprite(img3, 3);
- }
Данный код тоже очень простой, на нем останавливаться я не буду.
Теперь создаем SpriteEngine — именно он будет отвечать за рендер наших спрайтов.
- function SpriteEngine(_layers){
- this.layers = _layers;
- this.renderList = []; //Массив очереди для рендера
- this.ctx;
- this.startRender = function(_ctx) {
- this.ctx = _ctx;
- this.renderList.length = 0;
- for (var i = 0; i < this.layers; i++) {
- this.renderList[i] = [];
- }
- }
- this.drawSprite = function(_s, _x, _y, _frame, _layer) {
- //Просчитываем какой кусок нужно отрисовать и добавляем
- //это в очередь для рендера
- if (_frame <= _s.frames) {
- this.renderList[_layer-1].push({
- img: _s.img,
- x: _x, y: _y,
- xonimg: _frame*_s.frameWidth,
- yonimg: 0,
- imgwidth: _s.frameWidth,
- imgheight: _s.img.height
- });
- }
- }
- this.endRender = function() {
- //Тут собственно и отрисовываем
- for (var i = 0; i < this.layers; i++) {
- for (var j = 0; j < this.renderList[i].length; j++) {
- var e = this.renderList[i][j];
- this.ctx.drawImage(e.img, e.xonimg, e.yonimg, e.imgwidth, e.imgheight, e.x, e.y, e.imgwidth, e.imgheight);
- }
- }
- }
- }
Могут возникнуть вопросы по поводу renderList, который по сути является «массивом массивов» (тобиш двумерным). Первый массив хранит слой, второй — объекты с параметрами для рендера.
Теперь добавлю создание SpriteEngin’a, отрисовку наших спрайтов и регулярно увеличивающеюся переменную frame которая отвечает за текущий кадр анимации:
- …
- var frame = 0;
- setInterval(function() {
- if (frame < 2) {
- frame++;
- } else {
- frame = 0;
- }
- }, 500);
- var ctx = document.getElementById(‘c’).getContext(‘2d’);
- var se = new SpriteEngine(3);
- …
- function afterLoad() {
- …
- setInterval(function() {
- ctx.fillStyle = ‘#007F46’;
- ctx.fillRect( 0, 0, 640, 480);
- se.startRender(ctx);
- se.drawSprite(spr1, 100, 100, frame, 3);
- se.drawSprite(spr2, 116, 116, frame, 2);
- se.drawSprite(spr3, 132, 132, frame, 1);
- se.endRender();
- }, 25);
- }
Сохраняем, ловим баги и вуаля:) Нужно заметить, что нумерация слоев начинается с 1, причем, чем больше номер слоя, тем «дальше» он от нас находится. Максимально количество слоев мы передаем при создании SpriteEngine.
Исходники — тык.
P. S.: Если кто-нибудь куда-нибудь зальет — буду благодарен:)
ссылка на оригинал статьи http://habrahabr.ru/post/167437/
Добавить комментарий