레슨 5 / 8·20분
충돌 감지와 이벤트
충돌 필터링과 이벤트 심화
Matter.js는 충돌 필터링 시스템을 통해 어떤 바디끼리 충돌할지 세밀하게 제어할 수 있습니다. collisionFilter의 category와 mask를 비트 연산으로 설정하여 그룹 간 충돌을 허용하거나 차단합니다. Events 시스템은 collisionStart, collisionActive, collisionEnd, beforeUpdate, afterUpdate 등 다양한 시점에 훅을 걸 수 있습니다.
javascript
const { Events, Bodies, World, Body } = Matter;
// ── 충돌 필터 (Collision Filter) ──
// category: 비트 플래그 (1, 2, 4, 8, 16, ...)
// mask: 충돌 가능한 카테고리의 비트 OR 조합
const categoryA = 0x0001; // 그룹 A (1)
const categoryB = 0x0002; // 그룹 B (2)
const categoryC = 0x0004; // 그룹 C (4)
// 그룹 A: B와만 충돌
const ballA = Bodies.circle(200, 100, 25, {
label: 'ballA',
collisionFilter: {
category: categoryA,
mask: categoryB, // B와만 충돌
},
render: { fillStyle: '#e74c3c' },
});
// 그룹 B: A, C 모두와 충돌
const ballB = Bodies.circle(400, 100, 25, {
label: 'ballB',
collisionFilter: {
category: categoryB,
mask: categoryA | categoryC, // A와 C 모두 충돌
},
render: { fillStyle: '#3498db' },
});
// 그룹 C: B와만 충돌
const ballC = Bodies.circle(600, 100, 25, {
label: 'ballC',
collisionFilter: {
category: categoryC,
mask: categoryB,
},
render: { fillStyle: '#2ecc71' },
});
World.add(engine.world, [ballA, ballB, ballC]);javascript
// ── 이벤트 심화: 게임 로직에 활용 ──
let score = 0;
// 충돌 시작
Events.on(engine, 'collisionStart', (event) => {
event.pairs.forEach((pair) => {
const labels = [pair.bodyA.label, pair.bodyB.label];
// 특정 바디 충돌 감지
if (labels.includes('player') && labels.includes('coin')) {
const coin = pair.bodyA.label === 'coin' ? pair.bodyA : pair.bodyB;
score += 10;
World.remove(engine.world, coin);
console.log('점수: ' + score);
}
// 위험 구역 충돌
if (labels.includes('player') && labels.includes('hazard')) {
console.log('게임 오버!');
}
});
});
// 충돌 지속 중 (매 프레임)
Events.on(engine, 'collisionActive', (event) => {
event.pairs.forEach((pair) => {
// 지속 충돌 중인 바디 처리
});
});
// 엔진 업데이트 전/후 훅
Events.on(engine, 'beforeUpdate', (event) => {
// 물리 연산 전에 바디 상태 조정
// 예: 속도 제한, 영역 이탈 체크
const bodies = Composite.allBodies(engine.world);
bodies.forEach((body) => {
// 화면 밖으로 나간 바디 제거
if (body.position.y > 700) {
World.remove(engine.world, body);
}
});
});- •collisionFilter.category — 바디의 충돌 그룹 (비트 플래그)
- •collisionFilter.mask — 충돌 허용 그룹 마스크 (비트 OR)
- •collisionStart — 충돌이 처음 시작될 때 발생
- •collisionActive — 충돌이 유지되는 동안 매 프레임 발생
- •collisionEnd — 충돌이 끝났을 때 발생
- •beforeUpdate / afterUpdate — 물리 엔진 업데이트 전후 훅
- •event.pairs — 충돌한 바디 쌍 배열 (bodyA, bodyB)
💡
충돌 필터의 category와 mask는 비트 연산을 사용합니다. category는 반드시 2의 거듭제곱(1, 2, 4, 8...)이어야 하며, mask에는 여러 카테고리를 | (OR) 연산자로 결합합니다. 기본값은 category: 0x0001, mask: 0xFFFFFFFF(모두 충돌)입니다.