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차원에서 폭넓게 응용할 수 있다는 점이 매우 큰 장점입니다.
아래는 필요한 코드와 데이터 전체를 다운로드 받을 수 있는 링크입니다.