모든 자료는 physics.js 공식문서를 보고 작성하였습니다.
matter.js
, physics.js
, melon.js
등이 있다.world
, body
, renderer
, event
, behavior
등으로 구성되어있다. show code
를 클릭하여 해당 코드를 수정할 수 있으며hide code
-> update
를 클릭하면 해당 코드의 동작을 볼 수 있다.world
는 말 그대로 세계이며, 우리가 만들 물리엔진을 구축하는 곳이다.//방법1
const world = Physics();
//방법2
Physics(function(world){
// use "world"
});
//방법3
Physics(function(world){
// use "world"
});
// 각각의 시뮬레이션 월드 만들기
const ballSim = function(world){
//ball 시뮬레이션 생성가능
}
const chainSim = function(world) {
//chain 생성하기
}
//여러 시뮬레이션 월드 추가하기
const init = function() {
const ballWorld = Physics(ballSim);
const chainWorld = Physics(chainSim);
}
Physics({
timestep: 1000.0 / 160, //시간 간격 설정
maxIPF: 16, //한 step당 최대 반복 횟수
integrator: 'verlet'
}, function(world){
//world 구축하기
})
step
메소드를 사용하여 현재 시간을 매개변수로 넘겨준다.window.requestAnimationFrame
을 사용해 애니메이션 루프 내에서 시뮬레이션을 진행시키기도 한다.Physics.util.ticker
를 제공해준다!ticker
메소드는 requestAnimationFrame을 사용하므로 필요할 경우 polyfil 해야한다.ticker.on
을 사용해 이벤트를 구독하고, start
로 진행시키면 된다.//ticker.on으로 구독하기
Physics.util.ticker.on(function(time) {
world.step(time); //월드의 step이 현재 시간을 따라 진행
})
//ticker 시작하기
Physics.util.ticker.start();
add()
를 이용하여 여러가지 것(몸체, 행동, 랜더러 등)을 추가할 수 있다.renderer
)와 하나의 통합자(integrator
)만 추가할 수 있다.Physics.body
를 사용해 이 객체들을 만들 수 있다.//원 사물 객체 만들기
const ball = Physics.body("circle", {
x: 50, //x좌표
y: 30, //y좌표
vx: 0.2 //x방향으로 속도
vy: 0.01 //y방향으로 속도
radius: 20, //반지름
})
//world에 원 추가하기
world.add(ball);
behavior
(동작)은 world
에 적용할 물리 규칙을 정의한다.world
는 마찰이 없는 무한한 진공 상태가 된다.constant-acceleration
)를 설정하면 된다.//중력 정의하기
const gravity = Physics.behavior('constant-acceleration', {
acc: {x:0, y:0.0004}. //기본값
})
// world에 중력이라는 동작을 추가하기
world.add(gravity);
viewport
(사용자에게 보여지는 영역)를 정의한다.Dom
, html canvas
랜더링을 위한 랜더러도 있는데, 이 경우 커스텀 랜더러를 만들어야할 가능성이 높지만, 어렵지 않다!const renderer = Physics.renderer('canvas', {
el: 'element-id',
width: 500,
height: 300,
meta: false, // don't display meta data
styles: {
// set colors for the circle bodies
'circle' : {
strokeStyle: 'hsla(60, 37%, 17%, 1)',
lineWidth: 1,
fillStyle: 'hsla(60, 37%, 57%, 0.8)',
angleIndicator: 'hsla(60, 37%, 17%, 0.4)'
}
}
});
// add the renderer
world.add( renderer );
world
의 상태를 캔버스에 랜더링하려면, 모든 단계(step)에서 world.render
메소드를 호출해야한다.var renderer = Physics.renderer('canvas', {
//...
});
// add the renderer
world.add( renderer );
world.on('step', function(){
//step 마다 render를 실행시켜야함
world.render();
});
integrators
는 body의 물리적 특성을 수치적으로 통합한다. Physics({
integrator: 'verlet'
}, function(world){
// set up...
});
// equivalent to...
Physics(function(world){
world.add( Physics.integrator('verlet') );
// set up...
});
//예시
Physics(function(world){
//1.보여지는 영역의 높이, 너비 설정
var viewWidth = 500;
var viewHeight = 300;
//2.뷰포트 설정
var renderer = Physics.renderer('canvas', {
el: 'viewport',
width: viewWidth,
height: viewHeight,
meta: false, // don't display meta data
styles: {
// set colors for the circle bodies
'circle' : {
strokeStyle: '#351024',
lineWidth: 1,
fillStyle: '#d33682',
angleIndicator: '#351024'
}
}
});
//3. 랜더리 추가하기
world.add( renderer );
//4. 각 step마다 랜더링하기
world.on('step', function(){
world.render();
});
// 5.bounds of the window
var viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight);
// 6. constrain objects to these bounds
world.add(Physics.behavior('edge-collision-detection', {
aabb: viewportBounds,
restitution: 0.99,
cof: 0.99
}));
// 7. add a circle
world.add(
Physics.body('circle', {
x: 50, // x-coordinate
y: 30, // y-coordinate
vx: 0.2, // velocity in x-direction
vy: 0.01, // velocity in y-direction
radius: 20
})
);
// 8. ensure objects bounce when edge collision is detected
world.add( Physics.behavior('body-impulse-response') );
// 9. add some gravity
world.add( Physics.behavior('constant-acceleration') );
// 10. subscribe to ticker to advance the simulation
Physics.util.ticker.on(function( time, dt ){
world.step( time );
});
// 11. start the ticker
Physics.util.ticker.start();
});
다음 포스팅에서는 공식문서의 예시를 돌려보고 코드를 분석해보자!