pile·
프론트엔드·카카오 엔터테인먼트 FE카카오 엔터테인먼트 FE·

바나나 먹는 미니언 게임을 만들어 보자(feat. 캔버스)

캔버스로 만들어진 게임 '뱀서(Vampire Survivors)' 에서 자극을 받아, 떨어지는 바나나를 미니언으로 받는 간단한 게임을 캔버스로 구현한 기록이다. 이미지 로드부터 이동·잔상 제거·객체 생성·충돌 판정까지 게임 루프의 최소 구성을 순서대로 만든다.

핵심 포인트
  • 게임 규칙은 넷이다. 미니언은 캔버스 하단에 있고, 좌우로만 움직이며, 바나나가 위에서 랜덤한 위치로 떨어지고, 미니언을 움직여 받는다.
  • 이미지 로드는 비동기이므로 프로미스로 감싼 로드 함수를 만들고, 로드 완료 시점에 얻는 크기와 Image 객체를 변수에 저장한다.
  • 부드러운 이동은 `requestAnimationFrame` 으로 처리한다.
  • 움직이면 이전 위치에 잔상이 남는데, 매 프레임 `clearRect` 로 캔버스를 지우는 것으로 해결한다. 이것을 빼먹었을 때의 화면도 함께 보여준다.
  • 충돌 판정은 미니언이 바나나의 좌표 범위 안에 있는지 검사해, 맞으면 해당 바나나를 배열에서 제거하는 방식이다.
상세 정리
  • 개발 환경과 함께 바나나·미니언 이미지를 준비하는 것에서 시작하며, 이미지 출처도 마지막에 밝힌다.
  • 변수 설계: 캔버스와 두 이미지의 레퍼런스, 바나나의 너비·높이와 좌표, 미니언의 좌표를 각각 선언한다.
  • 바나나는 여러 개가 동시에 존재하고 시간이 지날수록 빨라져야 하므로 속도 관련 변수를 따로 둔다. 배수로 곱해야 해서 초기값을 1로 잡는다.
  • 키보드 입력은 좌우 이동 판단용 변수로 관리하고, 미니언 이동량과 바나나 생성 주기도 변수로 뺀다.
  • 초기 위치: 미니언은 캔버스 최하단 중앙에 놓는다.
  • 입력 처리: `keydown` 계열 이벤트에서 대문자 A 도 고려해 소문자로 변환한 뒤 판정하며, WASD 와 방향키를 모두 받는다.
  • 경계 처리: 좌표를 갱신하는 함수와 별도로, 미니언이 캔버스 밖으로 나가지 않도록 좌표 상한·하한을 잡는 함수를 둔다.
  • 바나나 생성: 랜덤한 x 위치에서 만들되, 서서히 나타나게 하려고 초기 y 를 바나나 높이만큼 뺀 값으로 둔다. 생성 주기는 0.5초(`CREATE_BANANA_TIME = 500`)다.
  • 여러 개를 그려야 하므로 바나나는 좌표를 가진 배열로 저장하고 배열 길이만큼 반복하며 좌표를 갱신한다.
  • 제거 조건 두 가지: 미니언이 못 받아 화면 아래로 나간 경우와, 미니언이 받은 경우다. 둘 다 index 를 받아 해당 바나나를 지우는 함수로 처리한다.
  • 충돌 판정 조건문은 x 좌표 기준으로 그림을 그려 설명한다.
  • 글에서 다루지 않았지만 점수 표시와 게임 상태를 제어하는 버튼도 함께 만들었다고 밝히고 전체 코드를 공개한다.
왜 읽나캔버스를 처음 만져 보는 프론트엔드 개발자에게 게임 루프·잔상 제거·충돌 판정이라는 기본기를 작은 예제 하나로 훑게 해 준다.
카카오 엔터테인먼트 FE
카카오 엔터테인먼트 FE 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2