3

I am making a game called Perfectly Balanced (it's based off an iWatch game) and I'm using Matter.js

The problem is that when you press space/click to drop the body, if there are already some bodies on the ground, they bounce and fall apart.

Screenshot

I've tried setting all of the bodies (except for the ground) restitution to 0, but it still bounces.

The code can be found here

// HTML elements
const container = document.querySelector('div#container');

// module aliases
let Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Body = Matter.Body,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite,
    Events = Matter.Events;

// create an engine
let engine = Engine.create();
engine.world.gravity.y *= 1;
engine.velocityIterations = 6;
engine.positionIterations = 10;
engine.constraintIterations = 8;

// create a renderer
let render = Render.create({
  element: container,
  engine: engine,
  options: {
    wireframes: false,
    width: 400,
    height: 400,
    background: 'cyan',
    hasBounds: true
  }
});

// create ground
let ground = Bodies.rectangle(render.options.width / 2, render.options.height - 10, render.options.width - 10, 10, {
  isStatic: true,
  render: {
    fillStyle: 'white'
  }
});

let current = 0;
let score = 0;
let step = 1;

let camera_y = 0;

// add all of the bodies to the world
Composite.add(engine.world, ground);

// run the renderer
Render.run(render);

// create runner
let runner = Runner.create();

// run the engine
Runner.run(runner, engine);

// before tick
Events.on(runner, "beforeTick", () => {
  if (typeof current == 'number')
  {
    current++;

    if (current >= 30)
    {
      if (step == 3)
      {
        current = Bodies.rectangle(20, 35, Math.random() * 100 + 80, 10);
        //Body.setMass(current, current.mass * 2);
      }
      else
      {
        current = Bodies.rectangle(20, 35, 30, 60);
        //Body.setMass(current, current.mass / 2);
      }
  
      step++;
  
      if (step >= 4)
        step = 1;
  
      Body.setStatic(current, true);
  
      if (!current.render)
        current.render = {};
  
      current.render.fillStyle = 'white';

      Body.setMass(current, 1);

      current.friction = 1;
      current.frictionAir = 0;
      current.frictionStatic = 100;
      current.restitution = 0;
      current.slop = 0.8;
      current.inertia = 100;
      current.inverseInertia = 1 / current.inertia;
  
      Composite.add(engine.world, current);
    }
  }
  else
  {
    if (!current._dir)
      current._dir = 1;
  
    if (current._dir == 1 && current.position.x >= render.options.width - 20)
      current._dir = -1;
    else if (current._dir == -1 && current.position.x <= 20)
      current._dir = 1;
  
    Body.setPosition(current, {
      x: current.position.x + 2 * current._dir,
      y: current.position.y
    });
  }
});

// after tick
Events.on(runner, "afterTick", () => {
  // draw score
  render.context.font = '30px Arial';
  render.context.fillText(score, 5, 30);

  // move camera
  render.bounds.min.y = camera_y;
  render.bounds.max.y = camera_y + render.options.height;

  // death
  
});

// on space
const clickHandler = e => {
  if (
    typeof current != 'number' && (
      (e.type == 'keydown' && e.code == 'Space') ||
      (e.type == 'touchstart') ||
      (e.type == 'mousedown')
    )
  )
  {
    Body.setStatic(current, false);
    Body.setAngularVelocity(current, 0);
    Body.setVelocity(current, { x: 0, y: 0 });
    
    current = 0;

    score++;
  }
};
window.addEventListener('keydown', clickHandler);
render.canvas.addEventListener('touchstart', clickHandler);
render.canvas.addEventListener('mousedown', clickHandler);

// on window resize
const resizeHandler = e => {
  if (window.innerWidth < window.innerHeight)
  {
    container.style.width = '100vw';
    container.style.height = 'auto';
  }
  else
  {
    container.style.width = 'auto';
    container.style.height = '100vh';
  }
};
window.addEventListener('resize', resizeHandler);
resizeHandler();
body
{
  margin: 0px;

  width: 100vw;
  height: 100vh;

  display: flex;

  align-items: center;
  justify-content: center;
}

div#container
{
  display: flex;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Perfectly Balanced</title>
  <link href="style.css" rel="stylesheet" type="text/css" />

  <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js" integrity="sha512-5T245ZTH0m0RfONiFm2NF0zcYcmAuNzcGyPSQ18j8Bs5Pbfhp5HP1hosrR8XRt5M3kSRqzjNMYpm2+it/AUX/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script src="script.js" defer></script>
</head>
<body>
  <div id="container">
    
  </div>
</body>
</html>
LuisAFK
  • 846
  • 4
  • 22
  • 1
    @ggorlen The code is posted now. If you place two bricks near each other and a platform on top (like a bridge) and drop another brick on top, it bounces even though all bodies's restitution is set to 0 – LuisAFK Jun 06 '22 at 16:42
  • Awesome, thanks. So it seems like you'd want to set the bodies static when they hit the ground, otherwise they will move and react when struck. What's the objective of the game? – ggorlen Jun 06 '22 at 16:52
  • @ggorlen You want to get as high as possible without anything falling (Perfectly Balanced). And I can't make them static because I need them to be able to fall if you place something in an _unbalanced position_ – LuisAFK Jun 06 '22 at 17:04

0 Answers0