matter.js: is there any way to animate my sprite
Asked Answered
V

1

1

I know in traditional HTML5 canvas, we can use drawImage method (the longest one with 9 properties) and change frameX and frameY to make sprite sheet animation. But I am new to matter.js. I've checked matter.js document but still don't have any idea about how to animate my sprite. Here is my object:

const ball = Bodies.circle(340, 340, 10, {
  density: 0.0005,
  frictionAir: 0.06,
  restitution: 0,
  friction: 0,

  render: {
    sprite: {
      texture: "images/blueMonster.png", 
      yScale: 0.2,
      xScale: 0.2,
      isStatic: true,
    },
  },
  inertia: Infinity,
  label: "ball",
});

World.add(world, ball);

If I need to provide more info to solve this problem, please let me know. Thank you very much for your time!

Vincentia answered 8/12, 2020 at 22:27 Comment(1)
Welcome to SO! The built-in rendering is really for demonstration purposes. MJS can be added to your existing spritesheet code using traditional HTML5 canvas.Prospector
P
3

There may be a fundamental misconception here. Matter.js is a physics engine that can plug into any rendering front-end. You don't have to use the built-in MJS rendering engine which is primarily there for prototyping. You can use your existing HTML5 code or something like Phaser which has robust support for sprite sheets.

Here's a simple proof-of-concept using vanilla JS to render a sprite animation with MJS as the physics engine. The approach is to call Matter.Engine.update(engine); to run the engine each frame and use coin.position to draw the sprite. More complex animations might use vertices and angle as shown here and here in addition to the sprite sheet, but this is use-case dependent.

(async () => {
  const image = await new Promise((resolve, reject) => {
    const image = new Image();
    image.onload = () => resolve(image);
    image.onerror = reject;
    image.src = "https://art.pixilart.com/c7f297523ce57fc.png";
  });
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  canvas.width = 500;
  canvas.height = 250;
  
  const engine = Matter.Engine.create();
  const coin = Matter.Bodies.circle(100, 0, 100, {
    density: 0.0005,
    frictionAir: 0.06,
    restitution: 0,
    friction: 0,
  });
  const ground = Matter.Bodies.rectangle(
    0, 350, 1500, 170, {isStatic: true}
  );
  const mouseConstraint = Matter.MouseConstraint.create(
    engine, {element: canvas}
  );
  Matter.Composite.add(
    engine.world, [coin, ground, mouseConstraint]
  );
  
  const w = 200;
  const h = 170;
  let frameNumber = 0;
  
  (function rerender() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    const offset = (~~frameNumber * w) % image.width;
    const {x, y} = coin.position;
    ctx.drawImage(
      image,      // image
      offset,     // sx
      40,         // sy
      w,          // sWidth
      h,          // sHeight
      x - w / 2,  // dx
      y - h / 2,  // dy
      w,          // dWidth
      h           // dHeight
    );
    frameNumber += 0.1;
    Matter.Engine.update(engine);
    requestAnimationFrame(rerender);
  })();
})();
canvas {
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>
<canvas></canvas>

Another approach is to plop in a gif or video--easily done since you're just making a webpage in the DOM that happens to have physics attached. See how to round an image in matter.js for an example.

Prospector answered 15/12, 2020 at 7:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.