How to flip sprites horizontally using HTML5 canvas?

I am trying to do animation with texture atlas:

enter image description here

and it works well when the character is facing right. I'm trying to flip it horizontally, but it gets the wrong position:

enter image description here

Here is my current code:

<canvas id="c" width="200" height="100" style="background: #000"></canvas>

var metaData = [
        {x:0,y:0,w:35,h:38,offsetX:3,offsetY:9},
        {x:37,y:0,w:31,h:37,offsetX:6,offsetY:10},
        {x:70,y:0,w:65,h:47,offsetX:0,offsetY:1},
        {x:137,y:0,w:65,h:47,offsetX:0,offsetY:1},
        {x:204,y:0,w:61,h:46,offsetX:1,offsetY:1},
        {x:267,y:0,w:42,h:46,offsetX:1,offsetY:1},
        {x:311,y:0,w:43,h:44,offsetX:1,offsetY:3},
        {x:356,y:0,w:38,h:37,offsetX:6,offsetY:10},
        {x:396,y:0,w:35,h:34,offsetX:6,offsetY:13},
        {x:433,y:0,w:33,h:37,offsetX:7,offsetY:10},
        {x:468,y:0,w:36,h:40,offsetX:5,offsetY:7},
        {x:506,y:0,w:34,h:39,offsetX:6,offsetY:8}
],
dx = 0, //position x
dy = 0, //position y
index = 0; //frame index

(function draw() {
    context2D.clearRect(0,0,c.width,c.height);

    var cur = metaData[index];

    if(facingRight) {
        context2D.drawImage(
            img,
            cur.x, cur.y,
            cur.w, cur.h,
            dx + cur.offsetX, dy + cur.offsetY,
            cur.w, cur.h
        );
    } else {
        context2D.save();
        context2D.translate(cur.w,0);
        context2D.scale(-1,1);
        context2D.drawImage(
            img,
            cur.x, cur.y,
            cur.w, cur.h,
            dx, dy + cur.offsetY,
            cur.w, cur.h
        );
        context2D.restore();
    }

    index = ++index % metaData.length;

    setTimeout(draw,100);
})();

      

I use scale(-1,1)

to flip the sprite, but I don't know how to keep it in the same position as the right one. Should I correct the offset value?

Please, any help would be appreciated :)

+3


source to share


1 answer


You would have saved a lot of time by taking an image editor and making all the sprites fit at the same size throughout the sprite.

No metadata

strangeness needed , the code is much simpler (one w

, one h

, x = w * i

etc.

For example, your largest sprite is about 70 pixels wide, so you should place all other sprites in one of these boxes:

empty sprite sheet with border

Now it looks like all of your sprites have the same front leg position. Thus, you should use it as an anchor point to align all your sprites.



Something like that:

sprite sheet with sprites and border Note that for all sprites, the front leg is always in the same position relative to its own box.

It's now pretty easy to code the animation of this sprite and even flip it:

const ssheet = new Image();
ssheet.src = 'https://i.stack.imgur.com/kXKIc.png'; // same without borders
ssheet.onload = startSheetAnim;

function startSheetAnim(evt) {
  const ctx = c.getContext('2d');
  const h = 49;
  const w = 70;
  let i = 0;

  function anim() {
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, c.width, c.height);
    ctx.drawImage(ssheet,
      (i * w), 1, w, h,
      0, 0, w, h
    );
    // scale (flip-x) and translate
    ctx.setTransform(-1, 0, 0, 1, w * 2, 0);
    ctx.drawImage(ssheet,
      (i * w), 1, w, h,
      0, 0, w, h
    );

    i = (i + 1) % 12
    setTimeout(anim, 100);
  }
  anim();
}
      

<canvas id="c"></canvas>
      

Run codeHide result


+2


source







All Articles