개발/Front-End

[Next.js] HTML Element 충돌 감지

ywwwon01 2025. 2. 16. 18:10

안녕하세요!!

 

이번에는 에어 하키를 구현하기 위해 꼭 필요했던 로직을 기록해 보겠습니다.

 

HTMl 요소 간 충돌을 감지하고, 충돌 발생시 이어서 적절한 로직을 수행하도록 했습니다.

 

그 상세한 로직 수행 내용을 적어보자면,

  • puck과 스테이지 벽 간 충돌 시 - puck이 벽으로부터 튕겨져 돌아오도록 처리
  • puck과 paddle 충돌 시 - puck이 paddle로부터 튕겨져 나가도록 처리
  • puck과 goalPost(골대) 충돌 시 - ⓐ 어느 쪽 골대에 충돌했냐에 따른 점수 카운트 처리 + ⓑ puck 위치 초기화 + ⓒ 카운트다운 재시작

라는 부분에서 적극! 활용되었습니다.

 

해당 로직을 구현하기 전 구글링을 통해 레퍼런스를 수집해 보니, MDN이나 다른 개발자분의 블로그에서도 확인할 수 있었습니다. (최하단 '레퍼런스' 목차 참고)

 

이런저런 레퍼런스를 참고하여 구현한 TypeScript 코드 및 아이디어에 대한 내용을 이어서 기술하겠습니다!

 

1. 직사각형 모양의 HTML Element 충돌 감지

src/pages/room/[id].tsx
const isCollidingWithWall = {
    left: puckRect!.left <= wholeStageRect!.left + STAGE_PADDING,
    right: puckRect!.right >= wholeStageRect!.right - STAGE_PADDING,
    top: puckRect!.top <= wholeStageRect!.top + STAGE_PADDING,
    bottom: puckRect!.bottom >= wholeStageRect!.bottom - STAGE_PADDING,
};​

 

무척 간단한 모습입니다.

 

 

각 요소의 left, right, top, bottom 값을 비교해 주는 원리로,

 

직사각형 모양의 HTML Element 간 충돌을 감지하는 것은 쉬운 일이었습니다.

 

2. 원 모양의 HTML Element 충돌 감지

원 모양의 HTML Element 간 충돌 감지에는 고민이 필요했습니다.

 

left, right, top, bottom의 값을 단순히 비교하는 것만으로는 위와 같은 상황에서의 충돌을 감지할 수 없었는데요..

 

src/pages/_lib/collistion.ts
import { CircleInfo } from "../model";

const getCircleInfo = (element: HTMLDivElement | null): CircleInfo | null => {
  if (!element) return null;
  const rect = element.getBoundingClientRect();
  const radius = rect.width / 2; // Assume the element is circular
  const centerX = rect.left + radius;
  const centerY = rect.top + radius;
  return { centerX, centerY, radius };
};

const areCirclesColliding = (circle1: CircleInfo, circle2: CircleInfo): boolean => {
  const dx = circle1.centerX - circle2.centerX;
  const dy = circle1.centerY - circle2.centerY;
  const distance = Math.sqrt(dx * dx + dy * dy);
  return distance <= circle1.radius + circle2.radius;
};

export { getCircleInfo, areCirclesColliding };​

 

 

위와 같이 작성하여 해결할 수 있었습니다.

 

게임 메인 로직에서 사용한 모습

 

게임이 동작하는 모습

 


 

 

 

이렇게 충돌 감지 로직에 대해서도 작성하면서,

 

Web 에어 하키 프로젝트를 진행하면서 생각했던 '이건 기록하면 좋겠는데?' 싶은 내용들은 모두 작성 완료하게 되었습니다.

 

추후 생각나는 바가 있거나 리팩토링.. 업데이트.. 최적화.. 배포.. 같은 것들을 하게 되면서 추가할 내용이 있다면 이어서 작성해 보겠습니다!!

 

감사합니다.

 

부록

코드 저장소 바로가기

https://github.com/yewon-saurus-mini-project/air-hockey-app
 

GitHub - yewon-saurus-mini-project/air-hockey-app

Contribute to yewon-saurus-mini-project/air-hockey-app development by creating an account on GitHub.

github.com

 

레퍼런스

https://developer.mozilla.org/ko/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection
 

충돌 감지 - 게임 개발 | MDN

이 학습은 Gamedev Canvas tutorial의 일곱 번째 단계입니다. Gamedev-Canvas-workshop/lesson7.html에서 이번 학습에서 완성된 코드를 확인할 수 있습니다.

developer.mozilla.org

 

https://4sii.tistory.com/23
 

javascript - 구글 공룡 게임 구현(5) - Collision detection(충돌감지)

dino 캐릭터의 움직임, cactus 들의 접근까지 구현했으니 그 둘이 부딪히면 게임오버되게 만들어보자 충돌감지라고 영어로는 Collision detection 이라고 하는데 게임에서는 빠져선 안되는 기능이다. 2D

4sii.tistory.com