바운스볼 (Bounce Ball)
중력이 적용되는 공을 좌우로 움직이며, 타일 맵을 타고 점프해 출구(타일 4)에 닿으면 다음 스테이지로 넘어가는 플랫포머입니다. 맵은 가로로 10개 구역이 이어진 구조이고, 카메라가 스크롤되며 넓은 한 판이 이어집니다.
맵과 타일 종류
-
그리드는 스테이지마다 20×20이며, 한 칸 크기는
boxCount = 20으로 나눈canvas.width / 20(주석상 20px 기준)입니다. -
maps배열에 스테이지가 10개 정의되어 있습니다. 타일 값: 0 빈칸, 1 벽, 2 가시(밟으면 즉시 게임 오버), 3 슈퍼 점프 발판, 4 출구(다음 스테이지 전환), 5 시작 지점(공 스폰). -
월드 X좌표는 스테이지 인덱스마다
stageIdx * canvas.width만큼 밀려 있어, 화면에는ctx.translate(-cameraX, 0)로 보이는 구간만큼 잘려 보입니다.
조작 방법
-
키보드:
ArrowLeft/ArrowRight를 누르는 동안 좌우 가속 방향이 켜집니다. 방향키와 스페이스는 스크롤 방지를 위해preventDefault가 걸려 있습니다. -
모바일:
leftBtn/rightBtn이 있으면 포인터 다운/업으로 같은 플래그를 사용합니다.
물리와 충돌
-
매 프레임
ball.dy += gravity로 낙하가 붙고, 상수는gravity = 0.08,jumpForce = -2.2,moveSpeed = 1.4입니다. -
공 반지름은 3(
ball.r). 벽 충돌은 네 모서리 점을 격자에 투영해checkWall로 검사합니다. -
좌우 벽(타일 1)에 닿으면 수평 속도가 반대로 튕기고(
±moveSpeed * 2.3), 동시에ball.dy = jumpForce * 0.8로 벽을 타고 튀어 오르는 느낌이 납니다. 공중에서는ball.dx *= 0.95로 마찰처럼 줄어듭니다. -
발판(바닥)에 착지하면
ball.dy가 점프력으로 설정됩니다. 착지한 칸이 슈퍼 점프 타일이면jumpForce * 1.6, 일반 바닥이면jumpForce이며 착지 시ball.dx = 0으로 수평이 정리됩니다. 천장에는ball.dy = 0으로 막힙니다. -
checkWall에서 타일 3이 감지되면 벽(1)보다 우선해 슈퍼 점프로 처리됩니다. -
공 중심 격자 검사(
checkTiles)로 가시(2)를 밟으면gameOver(), 화면 아래로ball.y > canvas.height + 100이면 추락 판정으로 게임 오버입니다.
스테이지 전환과 카메라
-
출구 타일 4에 닿으면
startTransition()이 호출됩니다. 아직 마지막 스테이지가 아니면currentStage가 올라가고,targetCameraX += canvas.width로 카메라 목표가 한 화면 폭만큼 이동합니다. -
전환 중에는
isTransitioning일 때 물리 대신cameraX가 목표에 가까워지도록 보간((targetCameraX - cameraX) * 0.08)되고, 끝나면 다시 플레이가 이어집니다. 다음 맵의 시작 타일 5 위치로 공이 다시 놓입니다. -
마지막 스테이지에서 출구에 도달하면 ALL CLEAR!로
showGameOverModal(10, true)가 호출됩니다. 랭킹에 저장되는 점수 값은 이 경우 코드상 10으로 고정입니다.
연출과 랭킹
-
공의 잔상은
ball.trail에 좌표를 쌓고 최대 12프레임만 유지하며, 보라색 계열로 투명도를 주어 그립니다. -
게임 오버 시 모달 문구는
최고 도달: STAGE ${currentStage + 1}형태(1부터 표기)로 나옵니다. -
랭킹 등록 시
saveGameScore("bounce", nickname, stageScore)를 사용합니다. 올 클리어는stageScore === 10, 중도 사망·추락은 도달한 스테이지 번호(위와 같은 1 기반 값)가 넘어갑니다. 닉네임은 2자 이상입니다.
플레이 팁
- 벽에 닿을 때마다 위로 튀어 오르므로, 협곡 구간에서는 좌우를 번갈아 벽에 붙이는 리듬이 중요합니다.
- 노란 슈퍼 점프 타일은 일반 바닥보다 높이 튀므로, 다음 발판·출구 위치를 미리 보고 밟을 타이밍을 잡으면 안전합니다.
- 카메라가 움직이는 동안에는 입력이 잠시 물리 업데이트에서 빠지므로, 전환이 끝난 뒤 다시 움직이는지 확인하는 것이 좋습니다.