matter.js 라이브러리를 이용하여 구현하고자 하는 결과는 아래와 같습니다.
먼저 HTML 코드입니다.
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="style_matter.js.css"> <script src="decomp.js"></script> <script src="pathseg.js"></script> <script src="matter.0.16.1.js"></script> <script src="app_matter.js.js" defer></script> </head> <body> <div></div> </body> </html>
지형은 SVG 데이터를 통해 좌표를 뽑아오는데 이를 위해 matter.js 이외에도 decomp.js와 pathseg.js 라이브러리가 필요합니다. div 요소에 강체 시뮬레이션의 결과가 표시됩니다. 다음은 CSS입니다.
* { outline: none; padding: 0; margin: 0; } body { display: flex; justify-content: center; align-items: center; width: 100%; height: 100vh; }
div 요소를 화면 중심에 놓기 위한 것이 전부입니다. 이제 js 코드를 살펴보겠습니다.
먼저 아래의 코드로 기본 코드를 작성합니다.
const engine = Matter.Engine.create(); const world = engine.world; const render = Matter.Render.create({ element: document.querySelector("div"), engine: engine, options: { width: 800, height: 600, wireframes: false, background: 'black' } }); Matter.Render.run(render); const runner = Matter.Runner.create(); Matter.Runner.run(runner, engine);
다음으로 지형과 지형 속에 사각형 물체를 구성하는 코드입니다.
fetch("./terrain.svg") .then((response) => { return response.text(); }) .then((raw) => { return (new window.DOMParser()).parseFromString(raw, "image/svg+xml"); }) .then(function(root) { const paths = Array.prototype.slice.call(root.querySelectorAll('path')); const vertices = paths.map((path) => { return Matter.Svg.pathToVertices(path, 30); }); const terrain = Matter.Bodies.fromVertices(400, 350, vertices, { isStatic: true, render: { fillStyle: '#2c3e50', strokeStyle: '#2c3e50', lineWidth: 1, } }, true); Matter.World.add(world, terrain); const bodyOptions = { frictionAir: 0.1, friction: 0.5, restitution: 0.1 }; Matter.World.add(world, Matter.Composites.stack(100, 200, 40, 10, 15, 15, (x, y) => { if (Matter.Query.point([terrain], { x: x, y: y }).length === 0) { return Matter.Bodies.polygon(x, y, 4, 10, bodyOptions); } })); } );
끝으로 마우스를 통해 사각형 객체를 드레그하여 옮길 수 있도록 합니다.
const mouse = Matter.Mouse.create(render.canvas), mouseConstraint = Matter.MouseConstraint.create(engine, { mouse: mouse, constraint: { stiffness: 0.2, render: { visible: false } } }); Matter.World.add(world, mouseConstraint);
matter.js는 매우 정교한 강체 시뮬레이션에는 적합하지 않으나 시각적인 면에서 다양한 물리 효과를 2차원에서 폭넓게 응용할 수 있다는 점이 매우 큰 장점입니다.
아래는 필요한 코드와 데이터 전체를 다운로드 받을 수 있는 링크입니다.