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 Slide

  2. View Slide

  3. BODIES WORLD ENGINE RUNNER RENDER

    View Slide

  4. BODIES WORLD ENGINE RUNNER RENDER

    The physical objects that are
    being simulated

    View Slide

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

    View Slide

  6. BODIES WORLD ENGINE RUNNER RENDER

    Updates the simulation of the
    world

    View Slide

  7. BODIES WORLD ENGINE RUNNER RENDER

    Continuously updates the engine

    View Slide

  8. BODIES WORLD ENGINE RUNNER RENDER

    Visualizes the output of the
    engine as a element

    View Slide




  9. Minimal Setup





    Minimal HTML

    View Slide

  10. // 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 Slide

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

    View Slide

  12. y
    x
    (0, 0)

    View Slide

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

    View Slide

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

    View Slide

  15. DEMO TIME!
    MINIMAL SETUP

    View Slide

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

    View Slide

  17. BOUNDARY WALLS

    View Slide

  18. BOUNDARY WALLS
    DIVIDER WALLS

    View Slide

  19. BOUNDARY WALLS
    DIVIDER WALLS
    PEGS

    View Slide

  20. BOUNDARY WALLS
    DIVIDER WALLS
    PEGS
    BEADS

    View Slide

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

    View Slide

  22. // 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 Slide

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

    View Slide

  24. 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 Slide

  25. 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 Slide

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

    View Slide

  27. 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 Slide

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

    View Slide

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

    View Slide

  30. DEMO TIME!
    GALTON BOARD (ROUND 1)

    View Slide

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

    View Slide

  32. 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 Slide

  33. 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 Slide

  34. 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 Slide

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

    View 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 Slide

  37. 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 Slide

  38. 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 Slide

  39. DEMO TIME!
    GALTON BOARD (ROUND 2)

    View Slide

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

    View Slide

  41. DEMO TIME!
    MATTER TOOLS

    View Slide




  42. Matter Tools







    Matter Tools HTML

    View Slide

  43. 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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

  47. DEMO TIME!
    LIGHTNING ROUND

    View Slide

  48. DEMO TIME!
    PINBALL

    View Slide

  49. View Slide

  50. View Slide

  51. View Slide

  52. ATTRACTORS + COLLISION FILTERS

    View Slide

  53. ATTRACTORS + COLLISION FILTERS
    CONSTRAINTS

    View Slide

  54. ATTRACTORS + COLLISION FILTERS
    CONSTRAINTS
    COMPOSITES

    View Slide

  55. View Slide

  56. View Slide

  57. View Slide

  58. View Slide

  59. DEMO TIME!
    PAGE INTERACTIONS

    View Slide

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

    View Slide