📜 ⬆️ ⬇️

Creating a sprite engine

Once upon a time, in my debut post , I promised to talk about creating sprite animation with sorting by depth ... Well, promises must be kept :)


And so, today I will talk about creating a simple sprite engine, with support for sorting by depth.
First, let's create a Sprite class :

Copy Source | Copy HTML
  1. function Sprite (_img, _frames) {
  2. this .img = _img;
  3. this .frames = _frames;
  4. this .frameWidth = _img.width / _frames;
  5. }

')
When creating a sprite, we pass a pointer to our image and the number of animation frames, the width of one frame is calculated by itself. Oh yeah, the pictures that I will use for the test:
image
image
image
Now you need to load these images and create sprites:

Copy Source | Copy HTML
  1. var loaded = 0 ;
  2. var allImgs = 3 ;
  3. function imgonload () {
  4. loaded ++;
  5. if (loaded == allImgs) {
  6. afterLoad ();
  7. }
  8. }
  9. var img1 = new Image ();
  10. img1.src = 'img1.png' ;
  11. img1.onload = imgonload;
  12. var img2 = new Image ();
  13. img2.src = 'img2.png' ;
  14. img2.onload = imgonload;
  15. var img3 = new Image ();
  16. img3.src = 'img3.png' ;
  17. img3.onload = imgonload;
  18. var spr1, spr2, spr3;
  19. function afterLoad () {
  20. spr1 = new Sprite (img1, 3 );
  21. spr2 = new Sprite (img2, 3 );
  22. spr3 = new Sprite (img3, 3 );
  23. }


This code is also very simple, I will not dwell on it.
Now we create SpriteEngine - it will be responsible for the render of our sprites.

Copy Source | Copy HTML
  1. function SpriteEngine (_layers) {
  2. this .layers = _layers;
  3. this .renderList = []; // Queue Array For Render
  4. this .ctx;
  5. this .startRender = function (_ctx) {
  6. this .ctx = _ctx;
  7. this .renderList.length = 0 ;
  8. for ( var i = 0 ; i < this .layers; i ++) {
  9. this .renderList [i] = [];
  10. }
  11. }
  12. this .drawSprite = function (_s, _x, _y, _frame, _layer) {
  13. // Calculate which piece to draw and add
  14. // this is in the queue for rendering
  15. if (_frame <= _s.frames) {
  16. this .renderList [_layer- 1 ] .push ({
  17. img: _s.img,
  18. x: _x, y: _y,
  19. xonimg: _frame * _s.frameWidth,
  20. yonimg: 0 ,
  21. imgwidth: _s.frameWidth,
  22. imgheight: _s.img.height
  23. });
  24. }
  25. }
  26. this .endRender = function () {
  27. // Actually draw here
  28. for ( var i = 0 ; i < this .layers; i ++) {
  29. for ( var j = 0 ; j < this .renderList [i] .length; j ++) {
  30. var e = this .renderList [i] [j];
  31. this .ctx.drawImage (e.img, e.xonimg, e.yonimg, e.imgwidth, e.imgheight, ex, ey, e.imgwidth, e.imgheight);
  32. }
  33. }
  34. }
  35. }


There may be questions about the renderList , which is essentially an “array of arrays” (a two-dimensional tobish). The first array stores the layer, the second - objects with parameters for rendering.
Now I’ll add the creation of SpriteEngin, the rendering of our sprites and the regularly increasing frame variable that is responsible for the current frame of the animation:

Copy Source | Copy HTML
  1. ...
  2. var frame = 0 ;
  3. setInterval ( function () {
  4. if (frame < 2 ) {
  5. frame ++;
  6. } else {
  7. frame = 0 ;
  8. }
  9. }, 500 );
  10. var ctx = document.getElementById ( 'c' ). getContext ( '2d' );
  11. var se = new SpriteEngine ( 3 );
  12. ...
  13. function afterLoad () {
  14. ...
  15. setInterval ( function () {
  16. ctx.fillStyle = '# 007F46' ;
  17. ctx.fillRect ( 0 , 0 , 640 , 480 );
  18. se.startRender (ctx);
  19. se.drawSprite (spr1, 100 , 100 , frame, 3 );
  20. se.drawSprite (spr2, 116 , 116 , frame, 2 );
  21. se.drawSprite (spr3, 132 , 132 , frame, 1 );
  22. se.endRender ();
  23. }, 25 );
  24. }


We save, catch bugs and voila :) It should be noted that the numbering of the layers starts from 1, and the more the layer number, the “farther” it is from us. We transfer the maximum number of layers when creating SpriteEngine.

Sources - tyk .
PS: If someone pours somewhere - I will be grateful :)

Source: https://habr.com/ru/post/167437/


All Articles