Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploring 2D Physics in JavaScript

Exploring 2D Physics in JavaScript

Let's play with physics in JavaScript! This talk will introduce you to Matter.js, an open source physics engine powered by JavaScript. You'll learn how to create fun and interesting physics-based interactions, even if you have no prior experience. By the end of the talk, you'll be ready to create your own physics-based demos, games, and web page interactions.

Demos for this talk can be viewed here: https://lonekorean.github.io/javascript-physics/.

All source code is available here: https://github.com/lonekorean/javascript-physics.

Learn more about Matter.js here: http://brm.io/matter-js/.

Will Boyd

May 18, 2018
Tweet

More Decks by Will Boyd

Other Decks in Technology

Transcript

  1. EXPLORING
    2D PHYSICS
    IN JAVASCRIPT
    WILL BOYD @lonekorean

    View full-size slide

  2. BODIES WORLD ENGINE RUNNER RENDER

    View full-size slide

  3. BODIES WORLD ENGINE RUNNER RENDER

    The physical objects that are
    being simulated

    View full-size slide

  4. The collection of bodies in a
    shared space
    BODIES WORLD ENGINE RUNNER RENDER

    View full-size slide

  5. BODIES WORLD ENGINE RUNNER RENDER

    Updates the simulation of the
    world

    View full-size slide

  6. BODIES WORLD ENGINE RUNNER RENDER

    Continuously updates the engine

    View full-size slide

  7. BODIES WORLD ENGINE RUNNER RENDER

    Visualizes the output of the
    engine as a element

    View full-size slide




  8. Minimal Setup





    Minimal HTML

    View full-size slide

  9. // engine
    let engine = Matter.Engine.create();
    // render
    let render = Matter.Render.create({
    element: document.body,
    engine: engine
    });
    Matter.Render.run(render);
    // runner
    let runner = Matter.Runner.create();
    Matter.Runner.run(runner, engine);
    Basic Setup

    View full-size slide

  10. // params: x, y, radius
    let ball = Matter.Bodies.circle(400, 100, 50);
    Matter.World.add(engine.world, ball);
    Simple Body

    View full-size slide

  11. ( , )
    y
    x
    radius
    Matter.Bodies.circle(x, y, radius);

    View full-size slide

  12. Matter.Bodies.rectangle(x, y, width, height);
    ( , )
    y
    x
    width
    height

    View full-size slide

  13. DEMO TIME!
    MINIMAL SETUP

    View full-size slide

  14. Matemateca (IME/USP)/Rodrigo Tetsuo Argenton
    CC-BY-SA 4.0
    LET’S MAKE
    A GALTON BOARD!

    View full-size slide

  15. BOUNDARY WALLS

    View full-size slide

  16. BOUNDARY WALLS
    DIVIDER WALLS

    View full-size slide

  17. BOUNDARY WALLS
    DIVIDER WALLS
    PEGS

    View full-size slide

  18. BOUNDARY WALLS
    DIVIDER WALLS
    PEGS
    BEADS

    View full-size slide

  19. let render = Matter.Render.create({
    element: document.body,
    engine: engine,
    options: {
    width: 560,
    height: 800,
    background: ‘#f8f9fa',
    wireframes: false
    }
    });
    Setting Render Options

    View full-size slide

  20. // params: x, y, width, height, options
    let bottom = Matter.Bodies.rectangle(280, 800, 560, 20, {
    isStatic: true,
    render: {
    fillStyle: '#868e96'
    }
    });
    Matter.World.add(engine.world, bottom);
    Adding Bottom Wall

    View full-size slide

  21. function wall(x, y, width, height) {
    return Matter.Bodies.rectangle(x, y, width, height, {
    isStatic: true,
    render: {
    fillStyle: '#868e96'
    }
    });
    }
    Abstracting Wall Creation

    View full-size slide

  22. Matter.World.add(engine.world, [
    wall(280, 0, 560, 20), // top
    wall(280, 800, 560, 20), // bottom
    wall(0, 400, 20, 800), // left
    wall(560, 400, 20, 800), // right
    ]);
    Adding Boundary Walls

    View full-size slide

  23. for (let x = 0; x <= 560; x += 80) {
    let divider = wall(x, 610, 20, 360);
    Matter.World.add(engine.world, divider);
    }
    Adding Divider Walls

    View full-size slide

  24. function peg(x, y) {
    return Matter.Bodies.circle(x, y, 14, {
    isStatic: true,
    render: {
    fillStyle: '#82c91e'
    }
    });
    }
    Peg Creation

    View full-size slide

  25. let isStaggerRow = false;
    for (let y = 200; y <= 400; y += 40) {
    let startX = isStaggerRow ? 80 : 40;
    for (let x = startX; x <= 520; x+= 80) {
    Matter.World.add(engine.world, peg(x, y));
    }
    isStaggerRow = !isStaggerRow;
    }
    Field Of Pegs

    View full-size slide

  26. function bead() {
    return Matter.Bodies.circle(280, 40, 11, {
    render: {
    fillStyle: '#e64980'
    }
    });
    }
    Bead Creation

    View full-size slide

  27. function dropBead() {
    Matter.World.add(engine.world, bead());
    }
    let dropBeadInterval = setInterval(dropBead, 2000);
    Dropping Beads

    View full-size slide

  28. DEMO TIME!
    GALTON BOARD (ROUND 1)

    View full-size slide

  29. Matter.Common.random(min, max);
    function rand(min, max) {
    return Math.random() * (max - min) + min;
    }
    Randomness
    - vs -

    View full-size slide

  30. function dropBead() {
    let droppedBead = bead();
    Matter.Body.setVelocity(droppedBead, {
    x: rand(-0.05, 0.05),
    y: 0
    });
    Matter.Body.setAngularVelocity(droppedBead, rand(-0.05, 0.05));
    Matter.World.add(engine.world, droppedBead);
    }
    Making Things Less Perfect

    View full-size slide

  31. function dropBead() {
    let droppedBead = bead();
    Matter.Body.setVelocity(droppedBead, {
    x: rand(-0.05, 0.05),
    y: 0
    });
    Matter.Body.setAngularVelocity(droppedBead, rand(-0.05, 0.05));
    Matter.World.add(engine.world, droppedBead);
    }
    Making Things Less Perfect

    View full-size slide

  32. function peg(x, y) {
    return Matter.Bodies.circle(x, y, 14, {
    restitution: 0.5,
    // other properties here...
    });
    }
    function bead() {
    return Matter.Bodies.circle(280, 40, 11, {
    restitution: 0.5,
    // other properties here...
    });
    }
    Adding Some Bounce

    View full-size slide

  33. function peg(x, y) {
    return Matter.Bodies.circle(x, y, 14, {
    label: 'peg',
    // other properties here...
    });
    }
    Peg Labels

    View full-size slide

  34. Matter.Events.on(engine, ‘collisionStart', lightPeg);
    function lightPeg(event) {
    event.pairs
    .filter((pair) => pair.bodyA.label === 'peg')
    .forEach((pair) => {
    pair.bodyA.render.fillStyle = '#4c6ef5';
    });
    }
    Lighting Up Pegs

    View full-size slide

  35. Matter.Events.on(engine, ‘collisionStart', lightPeg);
    function lightPeg(event) {
    event.pairs
    .filter((pair) => pair.bodyA.label === 'peg')
    .forEach((pair) => {
    pair.bodyA.render.fillStyle = '#4c6ef5';
    });
    }
    Lighting Up Pegs

    View full-size slide

  36. Matter.Events.on(engine, ‘collisionStart', lightPeg);
    function lightPeg(event) {
    event.pairs
    .filter((pair) => pair.bodyA.label === 'peg')
    .forEach((pair) => {
    pair.bodyA.render.fillStyle = '#4c6ef5';
    });
    }
    Lighting Up Pegs

    View full-size slide

  37. DEMO TIME!
    GALTON BOARD (ROUND 2)

    View full-size slide

  38. LET’S TALK ABOUT
    DEBUGGING
    WITH MATTER TOOLS!

    View full-size slide

  39. DEMO TIME!
    MATTER TOOLS

    View full-size slide




  40. Matter Tools







    Matter Tools HTML

    View full-size slide

  41. function initGaltonBoard() {
    // existing code goes here...
    return {
    engine: engine,
    render: render,
    canvas: render.canvas,
    runner: runner,
    stop: function() {
    Matter.Render.stop(render);
    Matter.Runner.stop(runner);
    clearInterval(dropBeadInterval);
    }
    };
    }
    Repackage Existing Code

    View full-size slide

  42. MatterTools.Demo.create({
    appendTo: document.body,
    tools: { gui: true },
    examples: [
    {
    id: 'galton-board',
    init: initGaltonBoard,
    }
    ]
    });
    Matter Tools Setup

    View full-size slide

  43. MatterTools.Demo.create({
    appendTo: document.body,
    tools: { gui: true },
    examples: [
    {
    id: 'galton-board',
    init: initGaltonBoard,
    }
    ]
    });
    Matter Tools Setup

    View full-size slide

  44. let mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse: Matter.Mouse.create(render.canvas)
    });
    Matter.World.add(engine.world, mouseConstraint);
    Mouse Control

    View full-size slide

  45. DEMO TIME!
    LIGHTNING ROUND

    View full-size slide

  46. DEMO TIME!
    PINBALL

    View full-size slide

  47. ATTRACTORS + COLLISION FILTERS

    View full-size slide

  48. ATTRACTORS + COLLISION FILTERS
    CONSTRAINTS

    View full-size slide

  49. ATTRACTORS + COLLISION FILTERS
    CONSTRAINTS
    COMPOSITES

    View full-size slide

  50. DEMO TIME!
    PAGE INTERACTIONS

    View full-size slide

  51. THANKS!
    WILL BOYD @lonekorean
    ★ brm.io/matter-js/
    ★ lonekorean.github.io/javascript-physics/

    View full-size slide