matter-js icon indicating copy to clipboard operation
matter-js copied to clipboard

How to create moving platform with some friction value for a platformer?

Open ProgrammingLife opened this issue 1 year ago • 2 comments

I can make my platform and set a static property for it but it will not allow me to move the platform from left to right with velocity/force to move my platform with a player standing on it. Also I can't set a huge mass to the platform since the huge difference between objects is not good. Anyway, platform still mutable by a player and it fly away in some direction. So what can I do else?

ProgrammingLife avatar Apr 17 '23 22:04 ProgrammingLife

So you want to create like a moving rectangle, and players can jump on it and walk on it?

The second part of your message very confusing to me, maybe if you had some example would be more clear. I am also learning matter-js, but you can change a body's position with: Body.setPosition(body, {x, y}).

So, if you want to move it from left to right you can give it a constant y value and "animate" the x value.

Kibergx avatar Apr 30 '23 17:04 Kibergx

setPosition is a good idea, but the problem is that the player doesn't move along with the moving static platform. I'm not sure what OP's exact situation is (a minimal, runnable example would be great!) but here's the sliding problem (with a somewhat hacky fix--happy to hear a better solution):

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
</head>
<body>
<script>
const engine = Matter.Engine.create();
const render = Matter.Render.create({
  element: document.body,
  engine: engine
});
const player = Matter.Bodies.rectangle(200, 100, 40, 40, {
  inertia: Infinity,
  friction: 0.008,
  frictionAir: 0.04,
});
const platform = Matter.Bodies.rectangle(200, 260, 300, 40, {
  isStatic: true,
});
const ground = Matter.Bodies.rectangle(390, 430, 810, 60, {
  isStatic: true
});
const keyHandlers = {
  ArrowRight: () => {
    Matter.Body.applyForce(player, {
      x: player.position.x,
      y: player.position.y
    }, {x: 0.003, y: 0})
  },
  ArrowLeft: () => {
    Matter.Body.applyForce(player, {
      x: player.position.x,
      y: player.position.y
    }, {x: -0.003, y: 0})
  },
  ArrowUp: () => {
    if (
      Matter.Collision.collides(player, platform) ||
      Matter.Collision.collides(player, ground)
    ) {
      Matter.Body.applyForce(player, {
        x: player.position.x,
        y: player.position.y
      }, {x: 0, y: -0.09});
    }
  },
};

const keysDown = new Set();
document.addEventListener("keydown", event => {
  if (event.code in keyHandlers) {
    event.preventDefault();
    keysDown.add(event.code);
  }
});
document.addEventListener("keyup", event => {
  if (event.code in keyHandlers) {
    event.preventDefault();
    keysDown.delete(event.code);
  }
});

let d = 0;
Matter.Events.on(engine, "beforeUpdate", event => {
  [...keysDown].forEach(k => keyHandlers[k]());
  Matter.Body.setPosition(platform, {
    x: platform.position.x + Math.cos(d += 0.01) / 3,
    y: platform.position.y,
  });

  // Somewhat hacky workaround:
  // if (Matter.Collision.collides(player, platform)) {
  //   Matter.Body.setPosition(player, {
  //     x: player.position.x + Math.cos(d += 0.01) / 3,
  //     y: player.position.y,
  //   });
  // }
});

Matter.Composite.add(engine.world, [player, platform, ground]);
Matter.Render.run(render);
const runner = Matter.Runner.create();
Matter.Runner.run(runner, engine);
</script>
</body>
</html>

ggorlen avatar Oct 03 '23 19:10 ggorlen