Keyword : Pixijs, P2, Collision, Collision Callback, 


Box2D 적용이후 몬스터가 충돌을 감지했을때 HP를 깍으려고 시도했었다.

하지만 Box2D의 물리엔진 콜백 (Contact Listener ?)을 달기가 어려웠었다. (레퍼런스가 C++ 기준, 구현 방식도 원본과 다른상황)

이런 상황이라 엔진은 Box2D에서 P2로 교체했다.

ECMA6 을 이용한 클래스 기반으로 생성중이다.


<script src="library/P2/build/p2.js" type="text/javascript"></script>

index파일에 먼저 p2.js 파일을 포함, 로드시킨다.


this.world = new p2.World({
gravity:[0, 0]
});

this.world.solver.iterations = 20;
this.world.stiffness = 1000000;
this.world.relaxation = 4;
this.world.solver.tolerance = 0.02;
this.world.sleepMode = p2.World.NO_SLEEPING;

이후 world를 생성한다.

Gravity는 중력의 정도를 설정한다. (일반적으로 Y값에 -9.87 적용)

밑의 solver, relaxtion등의 설정은 필수는 아닌 옵션 설정이다.

충돌되기를 원하는 클래스에 Body와 Shape를 만들어 준다.


this.rigidBody = new p2.Body({
mass: 1,
position: [Device.app.screen.width / 2, Device.app.screen.height - 200]
});

유니티와 비슷하게 사용하기 위해 모든 변수명을 RigidBody로 설정

이후 충돌체의 모양을 결정한다.


this.circleShape = new p2.Circle({ radius: 20});
this.circleShape.collisionGroup = Device.PLAYER;
this.circleShape.collisionMask = Device.ENEMY | Device.GROUND;

이 코드의 경우에는 Collider를 원으로 설정했다.

collisionGroup과 collisionMask가 중요한데 이 부분을 설정하지 않는다면 모든 충돌체와 충돌검사를 수행한다.

이번에는 적, 바닥만 충돌처리를 하기 위해 MASK를 두 종류만 설정했다.


this.PLAYER = Math.pow(2, 0);
this.ENEMY = Math.pow(2, 1);
this.GROUND = Math.pow(2, 2);

collisionMask에 사용된 값은 위의 코드와 같이 정의되어 있다. (비트 연산을 수행하기 위해 2의 제곱으로 설정)


this.rigidBody.addShape(this.circleShape);

Shape의 설정이 마무리 됬으면 rigidBody에 AddShape 해준다.


this.world.addBody(rigidBody);

이후 맨처음 생성한 World에 rigidBody를 등록한다.


이렇게 까지 처리하면 화면에서 물체가 충돌되서 서로 반사되는 부분까지 확인이 가능하다. 

(확인이 안된다면 sprite의 x, y 좌표를 Update에서 rigidBody의 x, y 좌표로 업데이트 시켜준다.)


다음 물체끼리 충돌했을때 콜백으로 확인하고 싶다면


this.world.on('beginContact', this.BeginContact.bind(this) ); // << : Collision Callback

world의 on함수에 콜백을 등록한다. (beginContact는 충돌 시작시 콜백해주는 함수)


BeginContact(contact){
// Shape ID 대신 Body의 ID를 이용 (한개의 Body에 여러 Shape가 붙을수 있다.)
if( ( contact.shapeA.collisionGroup & contact.shapeB.collisionMask ) !== 0 && (contact.shapeB.collisionGroup & contact.shapeA.collisionMask) !== 0) // 다른 타입인지 검사
{
if(contact.shapeA.collisionGroup !== Device.GROUND && contact.shapeB.collisionGroup !== Device.GROUND) // 둘다 그라운드가 아닐때
{

contact.bodyA.parent.Collision();
contact.bodyB.parent.Collision();
// console.log("Collision Enemy && Player ");
}
}
}

위의 조건문을 이용해서 collisionGroup, collisionMask를 이용, 충돌하기를 원하는 대상들만 충돌처리를 실행할수 있다.

이벤트를 통해서 특정 함수를 실행해도 되고 

이번 코드의 경우 Body를 생성한뒤 parent에 this를 설정, 부모 클래스의 특정 함수를 실행시키는 방법으로 처리했었다.


이렇게 처리하면 Collision 발생시 특정 함수 실행 가능

'프로그래밍 > JavaScript' 카테고리의 다른 글

Threejs repeat  (0) 2018.07.04
Spine Attachment Off  (0) 2018.06.20
p2 reflection angle (반사각) 설정  (0) 2018.04.13
HTML5 휴대폰 터치 처리  (0) 2018.04.12
PIXI.js, box2d 적용  (0) 2018.04.03

+ Recent posts