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

D50888599a25e1653030109cfd0743f1?s=128

Will Boyd

May 18, 2018
Tweet

Transcript

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

  2. None
  3. BODIES WORLD ENGINE RUNNER RENDER △

  4. BODIES WORLD ENGINE RUNNER RENDER △ The physical objects that

    are being simulated
  5. The collection of bodies in a shared space BODIES WORLD

    ENGINE RUNNER RENDER △
  6. BODIES WORLD ENGINE RUNNER RENDER △ Updates the simulation of

    the world
  7. BODIES WORLD ENGINE RUNNER RENDER △ Continuously updates the engine

  8. BODIES WORLD ENGINE RUNNER RENDER △ Visualizes the output of

    the engine as a <canvas> element
  9. <!DOCTYPE html> <html> <head> <title>Minimal Setup</title> <script src="matter.min.js" defer></script> <script

    src="my.js" defer></script> </head> <body></body> </html> Minimal HTML
  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
  11. // params: x, y, radius let ball = Matter.Bodies.circle(400, 100,

    50); Matter.World.add(engine.world, ball); Simple Body
  12. y x (0, 0)

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

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

    height
  15. DEMO TIME! MINIMAL SETUP

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

    BOARD!
  17. BOUNDARY WALLS

  18. BOUNDARY WALLS DIVIDER WALLS

  19. BOUNDARY WALLS DIVIDER WALLS PEGS

  20. BOUNDARY WALLS DIVIDER WALLS PEGS BEADS

  21. let render = Matter.Render.create({ element: document.body, engine: engine, options: {

    width: 560, height: 800, background: ‘#f8f9fa', wireframes: false } }); Setting Render Options
  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
  23. function wall(x, y, width, height) { return Matter.Bodies.rectangle(x, y, width,

    height, { isStatic: true, render: { fillStyle: '#868e96' } }); } Abstracting Wall Creation
  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
  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
  26. function peg(x, y) { return Matter.Bodies.circle(x, y, 14, { isStatic:

    true, render: { fillStyle: '#82c91e' } }); } Peg Creation
  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
  28. function bead() { return Matter.Bodies.circle(280, 40, 11, { render: {

    fillStyle: '#e64980' } }); } Bead Creation
  29. function dropBead() { Matter.World.add(engine.world, bead()); } let dropBeadInterval = setInterval(dropBead,

    2000); Dropping Beads
  30. DEMO TIME! GALTON BOARD (ROUND 1)

  31. Matter.Common.random(min, max); function rand(min, max) { return Math.random() * (max

    - min) + min; } Randomness - vs -
  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
  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
  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
  35. function peg(x, y) { return Matter.Bodies.circle(x, y, 14, { label:

    'peg', // other properties here... }); } Peg Labels
  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
  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
  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
  39. DEMO TIME! GALTON BOARD (ROUND 2)

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

  41. DEMO TIME! MATTER TOOLS

  42. <!DOCTYPE html> <html> <head> <title>Matter Tools</title> <script src="matter.min.js" defer></script> <script

    src="matter-tools.gui.min.js" defer></script> <script src="matter-tools.demo.min.js" defer></script> <script src="my.js" defer></script> </head> <body></body> </html> Matter Tools HTML
  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
  44. MatterTools.Demo.create({ appendTo: document.body, tools: { gui: true }, examples: [

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

    { id: 'galton-board', init: initGaltonBoard, } ] }); Matter Tools Setup
  46. let mouseConstraint = Matter.MouseConstraint.create(engine, { mouse: Matter.Mouse.create(render.canvas) }); Matter.World.add(engine.world, mouseConstraint);

    Mouse Control
  47. DEMO TIME! LIGHTNING ROUND

  48. DEMO TIME! PINBALL

  49. None
  50. None
  51. None
  52. ATTRACTORS + COLLISION FILTERS

  53. ATTRACTORS + COLLISION FILTERS CONSTRAINTS

  54. ATTRACTORS + COLLISION FILTERS CONSTRAINTS COMPOSITES

  55. None
  56. None
  57. None
  58. None
  59. DEMO TIME! PAGE INTERACTIONS

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