physics.js로 물리엔진을 알아보자(2)

gicomong·2021년 8월 10일
2

physics.js의 공식 튜토리얼을 따라하면서, 물리엔진 라이브러리를 알아보자!


1. canvas 추가하기

  • 먼저 html에서 canvas를 추가한다.
  • 만약 간단하게 테스트해보고 싶다면 physicsJS 홈페이지의 코드 편집기를 쓰자.
<canvas id="viewport" width="500" height="500"></canvas>



2. 물리 엔진 설정하기

물리 엔진의 경우 js에서 설정한다.

A. 렌더러 설정하기

  • 랜더러는 시뮬레이션의 뷰포트(사용자에게 보여지는 영역)를 설정한다.
  • el의 경우 canvas태그의 id값을 넣어주면 된다.
  • world.add를 사용해 랜더러를 world에 적용해준다.
Physics(function(world){
  const renderer = Physics.renderer('canvas', {
    el: 'viewport',
    width: 500,
    height: 500
  })
  world.add(renderer);
  ...
})

B. 사물 객체 생성하기

  • Physics.body('사물유형', { 옵션 })을 사용해 사물객체를 생성한다.
  • 생성한 사물 객체를 world.add를 사용해 world에 추가한다.
 ...
 const square1 = Physics.body('rectangle', {
 	 x: 250,      //x 위치
 	 y: 250,      //y축 위치
	 width: 50,
   height: 50
 });
const square2 = Physics.body('rectangle', {
 	  x: 280,
    y: 350,
    width: 50,
    height: 50
 });
 world.add(square1);  //추가
 world.add(square2);  

C. 시뮬레이션 실행하기

  • utils.ticker를 사용하여 애니메이션 루프를 진행시킨다.
  • 시뮬레이션 작동시키는데, world의 간격을 실제 시간으로 설정한다. (a)
  • ticker.start()를 실행하여 애니메이션 루프를 실행시킨다. (b)
  • 매 프레임마다 뷰를 새로 랜더링한다. (c)
//4. 시뮬레이션 돌리기(실행시키기)
 Physics.util.ticker.on(function(time, dt) {
 	world.step(time);           //(a)
 })
 Physics.util.ticker.start(); //(b)
 
 world.on('step', function() {
 	world.render();             //(c)
 })

D. 동작 추가하기

  • Physics.behavior(동작)을 사용해 world에 물리 법칙(?)을 추가한다.
  • constant-acceleration는 중력을 의미한다. (a)
  • body-impulse-response를 지정하면 충돌에 반응할 수 있게 된다. (b)
  • body-collision-detection은 객체끼리 충돌이 발생하게 한다. (c)
  • sweep-prune을 지정하여 광범위한 위상 충돌을 감지할 수 있다. (d)
//5. 동작 추가하기 (중력)
 world.add(Physics.behavior('constant-acceleration') );      //(a)
 world.add(Physics.behavior('body-impulse-response'));       //(b)
 world.add( Physics.behavior('body-collision-detection') );  //(c)
 world.add( Physics.behavior('sweep-prune') );   //(d)

E. 경계 만들기

  • 현재는 경계를 규정하지 않아, 코드를 실행하면 사물이 아래로 계속 떨어진다! (추락 상태)
  • 하지만 경계를 규정해주면 사물이 경계 내부에서 동작하도록 할 수 있다.
  • Physics.aabb(minX , minY , maxX , maxY)을 사용해 경계를 만들어준다. (a)
  • aabb: bound를 하여 경계(aabb)에 충돌시 탄성(bound)를 준다. (b)
  • restitution은 복원성으로 원래대로 돌아가는 정도를 설정할 수 있다. (c)
 const bounds = Physics.aabb(0, 0, 500, 500);  //(a)
    
 world.add(Physics.behavior('edge-collision-detection', {
   aabb: bounds,     //(b)
   restitution: 0.3  //(c)
  }) );

F. 결과

  • 위와 같은 과정을 거치면 이런 모습이 탄생한다!

G. 전체 코드

Physics(function (world) {
  const renderer = Physics.renderer("canvas", {
    el: "viewport",
    width: 500,
    height: 500,
  });
  world.add(renderer);

  const square1 = Physics.body("rectangle", {
    x: 250,
    y: 250,
    width: 50,
    height: 50,
  });
  const square2 = Physics.body("rectangle", {
    x: 280,
    y: 350,
    width: 50,
    height: 50,
  });
  world.add(square1);
  world.add(square2);

  Physics.util.ticker.on(function (time, dt) {
    world.step(time);
  });
  Physics.util.ticker.start(); //동작 시키기

  world.on("step", function () {
    world.render(); //매 프레임마다 뷰를 새로 고치도록 함
  });

  world.add(Physics.behavior("constant-acceleration"));
  world.add(Physics.behavior("body-impulse-response"));
  world.add(Physics.behavior("body-collision-detection")); //몸체끼리 충돌발생
  world.add(Physics.behavior("sweep-prune")); //광범위한 위상 충돌 감지

  const bounds = Physics.aabb(0, 0, 500, 500);

  world.add(
    Physics.behavior("edge-collision-detection", {
      aabb: bounds, //충돌시 탄성 주기
      restitution: 0.3, //복원성(원래대로 돌아가는 정도)
    })
  );
});
profile
이전에 본 포스팅이 없다구요? 티스토리로 이사갔어요! (새 글은 이제 티스토리에서 개재합니다~)

0개의 댓글