[Front-End] PhysicsJS物理引擎

前言

最近接小遊戲的案子裡面需要用到物理運算,稍微記錄一下PhysicsJS的使用。

PhysicsJS

PhysicsJS,裡面有API的使用及打包下載。

範例

函式會回傳world,所以宣告後可以方便之後使用,詳細的API請看官方文件。

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
var myWorld = Physics(function(world){
var viewWidth = 500;
var viewHeight = 300;
var renderer = Physics.renderer('canvas', {
el: 'viewport',
width: viewWidth,
height: viewHeight,
meta: false,
styles: {
'circle' : {
strokeStyle: '#351024',
lineWidth: 1,
fillStyle: '#d33682',
angleIndicator: '#351024'
}
}
});
world.add( renderer );
world.on('step', function(){
world.render();
});
var viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight);
world.add(Physics.behavior('edge-collision-detection', {
aabb: viewportBounds,
restitution: 0.99,
cof: 0.99
}));
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
})
);
world.add( Physics.behavior('body-impulse-response') );
world.add( Physics.behavior('constant-acceleration') );
Physics.util.ticker.on(function( time, dt ){
world.step( time );
});
Physics.util.ticker.start();
});

world.add()

要動態新增一個物件,可使用add()

1
2
3
4
5
6
7
var box = Physics.body('rectangle',{
x: 0 ,
y: 0 ,
width: 100 ,
height: 100
});
myWorld.add(box) ;

body.view.src

物件使用圖片。

1
2
box.view = new Image();
box.view.src = "1.png" ;

body.state

取得物件的狀態,詳細請看文件。

1
var x = box.state.pos.y ;

使用自己的Canvas

如果想要用自己的Canvas,可創好world後記錄每一個物件的狀態,再繪圖到自己的Canvas。

drawBody

旋轉起來會很麻煩,旋轉是整個畫布一起旋轉所以需搭配位移,懶人可直接參考內部的Code。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var drawBody = function( body, view, ctx, offset ){
var pos = body.state.pos
,os = body.offset
,v = body.state.vel
,t = this._interpolateTime || 0
,x
,y
,ang
,aabb
;
offset = offset || this.options.offset;
x = pos._[0] + offset.x + v._[0] * t;
y = pos._[1] + offset.y + v._[1] * t;
ang = body.state.angular.pos + body.state.angular.vel * t;
ctx.save();
ctx.translate( x, y );
ctx.rotate( ang );
ctx.translate( os._[0], os._[1] );
ctx.drawImage(view, -view.width/2, -view.height/2, view.width, view.height);
ctx.restore();
}

因此我們只要將參數傳遞進去即可。

1
drawBody(box,box.view,ctx,box.offset);

碰撞偵測

1
2
3
4
5
6
7
myWorld.on('collisions:detected', function( data ){
var coll;
for (var i = 0, l = data.collisions.length; i < l; i++){
coll = data.collisions[ i ];
//coll.bodyA 和 coll.bodyB ...
}
});