FE 개발자를 위한 안드로이드 후려치기 #4 바텀시트 만들기
웹에서 2D 물리엔진 사용하기 #1 Matter.js 시작하기
2018-11-30
Explanation
오늘은 웹에서 2D 물리 엔진을 사용해보려 합니다~ 물리 엔진에 관련해서 몇가지 라이브러리들이 있는데요. 짧게 알아봤을때, Box2Djs와 Matter.js 이렇게 두개를 찾아 볼 수 있었어요. 그리고 저는 이중에서 Matter.js에 대해 공부하고 공부한 내용을 조금씩 정리해보려 합니다.
저도 아직 사용해 본 지 얼마 되지 않아서 잘 모르는 부분이 많고, 글에도 틀린 부분이 많을 수 있습니다.
우선 간단하게 Matter.js의 ‘Getting started’을 그대로 실행해보면 아래와 같습니다.
참고링크. Matter.js – Getting started
헐… 신기방기…
1 2 3 4 5 6 7 |
// module aliases var Engine = Matter.Engine, Render = Matter.Render, World = Matter.World, Bodies = Matter.Bodies; ... |
간단하게 ‘Getting started’의 코드를 보았을때, 가장 기본이 되는 부분은 Engine, Render, World, Bodies 인가봐요. Engine은 이름 그대로 물리 엔진을 구현해주는 역할, World는 그 물리 엔진이 적용되는 공간을 의미하는 것 같고, Bodies는 그 공간안의 오브제들에 관련한 일을 하고 Render는 공간안에서 오브제들의 변화를 지속적으로 Canvas에 반복해서 그려 애니메이션을 구현해주는 것 같아요.
참고 소스는 깃허브 https://github.com/falsy/blog-post-example/tree/master/matter-js-quick-start를 통해 확인하셔도 되고 아래의 JSFiddle를 참고하셔도 될 거 같아요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
import Matter from 'matter-js'; // 윈도우(브라우저)의 크기를 변수에 담습니다. const windowHeight = window.innerHeight; const windowWidth = window.innerWidth; // Matter-js const Engine = Matter.Engine; const Render = Matter.Render; const World = Matter.World; const Bodies = Matter.Bodies; const Events = Matter.Events; // 이 밖에도 // console.log(Matter); 를 찍어보면 알 수 있듯이 // Composite, Constraint, Mouse ... 등 많은 기능들이 있습니다. // 이 부분은 다음 글에서 천천히 추가적으로 정리해보려 합니다. // 엔진을 생성합니다. const engine = Engine.create(); const world = engine.world; engine.world.gravity.y = 0.1; // engine.world.gravity 는 중력?? 이라고 해야하나 y축으로 떨어지는 속도를 정합니다. // 0 보다 작으면 오브제들이 위로 올라갑니다. // engine.world.gravity.x 속성도 있어서 오른쪽 또는 왼쪽으로 쏠리게 할 수도 있습니다. // Bodies에서 오브제를 만듭니다. // 이름 그대로 circle은 원, rectangle은 사각형을 만듭니다. // 자세한 정보는 공식 홈페이지를 참고하는게 더 좋을 것 같지만 // Bodies.circle(x축 위치값, y축 위치값, 반지름값, 옵션); // Bodies.rectangle(x축 위치값, y축 위치값, 너비값, 높이값, 옵션); // 입니다. const circle = Bodies.circle(windowWidth/2, 50, 10, { friction: 0.2, // 단어 그대로 마찰력 값입니다. (0~1) restitution: 0.8, // 단어 그대로 복원력 입니다. (0~1) render: { fillStyle: '#000', strokeStyle: '#000', lineWidth: 1 } // fillStyle 은 채워질 색, strokeStyle은 선색, lineWidth 선 굵기 }); const ground = Bodies.rectangle(windowWidth/2, windowHeight-50, windowWidth/3, 10, { isStatic: true // 고정된 위치의 오브제 }); // 이 밖에 options 값들이 어떤것들이 있는지 아직 다 잘 알지 못해서, 공부해서 추후에 자세히 추가하겠습니다. // World에 위 오브제들을 추가합니다. World.add(engine.world, [circle, ground]); // 렌더를 생성합니다. const render = Render.create({ element: document.body, engine: engine, options: { width: windowWidth, height: windowHeight, // 기본값은 wireFrames 값이 ture이고 false를 주지 않으면 // 위에 작성한 Bodies.circle의 render 옵션이 적용되지 않습니다. wireframes: false, background: '#fff' } }); // 엔진을 실행하고 Engine.run(engine); // 렌더를 실행합니다. Render.run(render); // 몇가지 이벤트를 추가합니다. // render 객체의 canvas는 DOM body에 추가 될 canvas 엘리먼트를 가리킵니다. render.canvas.addEventListener("click", (e) => { // 캔버스를 마우스로 클릭하면 // 현재 마우스 위치에 반지름이 10인 원을 만들어서 const box = Bodies.circle(e.offsetX, e.offsetY, 10, { friction: 0.2, restitution: 0.8 }); // 공간에 추가합니다. World.add(engine.world, box); }, false); // 1초 간격으로 setInterval(() => { // 가로 중앙, 상단에서 50px 떨어진 곳에 반지름이 10인 원을 만들어서 const box = Bodies.circle(windowWidth/2, 50, 10, { friction: 0.2, restitution: 0.8 }); // 공간에 추가합니다. World.add(engine.world, box); }, 1000); // 아까 위에 선언한 Matter에서 지정되어 있는 이벤트 인데요. // 그중에 'collisionStart'은 오브제 간 충돌의 시작한 시점의 이벤트입니다. Events.on(engine, "collisionStart", (event) => { // 오브제들이 충돌하면 console.log를 출력합니다. console.log('collision'); }); // 첫번째 글이라 자세히 적진 않았지만 인자로 받은 event의 값으로 // 충돌한 오브제 A와 오브제 B를 구분하여 이벤트를 처리해 줄 수도 있습니다. |