[파이썬] 지렁이게임 충돌처리: 벽·몸통 판정이 꼬일 때 고치는 순서

지렁이게임을 만들 때 마지막까지 발목 잡는 게 충돌처리입니다. 분명 벽에 닿았는데 안 죽거나, 반대로 여유가 있는데 갑자기 게임오버가 뜨는 경우가 있죠. 특히 코드가 조금만 길어져도 “어느 타이밍에서 판정해야 하는지”가 헷갈려서 버그가 반복됩니다.

오늘은 파이썬 지렁이게임 충돌처리를 기준으로 벽 충돌, 몸통 충돌, 먹이 처리 순서를 실전 관점에서 정리합니다. 핵심은 로직을 늘리는 게 아니라, 판정 순서를 고정하는 겁니다. 이 순서만 잡으면 대부분의 충돌 버그는 빠르게 사라집니다.

파이썬 지렁이게임 충돌처리 예시 이미지 1

파이썬 지렁이게임 충돌처리, 순서 고정만 해도 버그가 크게 줄어듭니다

충돌 버그가 반복되는 진짜 이유

초보 단계에서는 보통 한 루프 안에 이동, 충돌, 먹이, 그리기를 섞어서 작성합니다. 이렇게 되면 “이동 전 좌표”를 기준으로 충돌을 볼 때도 있고, “이동 후 좌표”를 기준으로 볼 때도 있어 결과가 흔들립니다. 벽 충돌이 들쑥날쑥하게 보이는 이유가 여기 있습니다.

가장 안정적인 방식은 매 루프마다 동일한 순서를 지키는 것입니다. 1) 다음 머리 좌표 계산, 2) 벽/몸통 충돌 체크, 3) 충돌 없으면 실제 이동 반영, 4) 먹이 체크, 5) 화면 렌더. 이 다섯 단계로 고정하면 디버깅 포인트가 명확해집니다.

좌표 체계를 먼저 고정하세요(픽셀 vs 셀)

지렁이게임은 보통 격자 기반입니다. 그런데 좌표를 픽셀 단위와 셀 단위를 섞어 쓰면 충돌 판정이 쉽게 어긋납니다. 예를 들어 몸통은 셀 좌표 리스트인데 머리만 픽셀 좌표로 비교하면, 값이 같은 것처럼 보여도 실제 비교는 실패합니다.

실전에서는 셀 단위로 통일하는 편이 안전합니다. 예를 들어 화면이 600×400이고 셀 크기가 20이면, 좌표 유효 범위는 x: 0~29, y: 0~19입니다. 경계 판정도 훨씬 깔끔해집니다.

CELL = 20
GRID_W = 600 // CELL  # 30
GRID_H = 400 // CELL  # 20

# 머리 위치 (셀 좌표)
head_x, head_y = 10, 8

# 벽 충돌
if head_x < 0 or head_x >= GRID_W or head_y < 0 or head_y >= GRID_H:
    game_over = True

실수 포인트

>>=를 잘못 쓰는 경우가 많습니다. 마지막 유효 인덱스는 GRID_W - 1이므로, 충돌 조건은 반드시 >= GRID_W 형태여야 합니다.

벽 충돌보다 먼저 해야 할 것: 다음 좌표 계산

충돌 판정을 현재 머리 좌표로 하면 한 박자 늦게 죽는 버그가 생깁니다. 먼저 다음 좌표를 계산한 뒤 그 좌표로 벽/몸통 충돌을 확인해야 판정이 자연스럽습니다.

dx, dy = direction  # (1,0), (-1,0), (0,1), (0,-1)
next_head = (snake[0][0] + dx, snake[0][1] + dy)

# 1) 벽 체크
x, y = next_head
if x < 0 or x >= GRID_W or y < 0 or y >= GRID_H:
    game_over = True

# 2) 몸통 체크
if next_head in snake:
    game_over = True

여기서 몸통 체크를 in snake로 단순화할 수 있지만, 꼬리가 같은 프레임에 이동하는 조건(먹이 미섭취 시)은 예외 처리가 필요할 수 있습니다. 이걸 놓치면 “정상 이동인데 자기 몸통 충돌”로 오탐지됩니다.

몸통 충돌 오탐지 줄이는 실전 규칙

먹이를 먹지 않은 프레임에서는 꼬리가 한 칸 빠집니다. 따라서 다음 머리 좌표가 “현재 꼬리 위치”인 경우는 충돌이 아닐 수 있습니다. 반대로 먹이를 먹는 프레임은 꼬리가 유지되므로 같은 조건에서도 충돌이 맞습니다. 이 차이를 구분하지 않으면 충돌 버그가 반복됩니다.

will_eat = (next_head == food)

body_to_check = snake if will_eat else snake[:-1]
if next_head in body_to_check:
    game_over = True

이 규칙 하나로 지렁이가 몸을 스치며 도는 구간에서 생기던 오탐지 대부분이 정리됩니다. 실제로 학생 과제 디버깅할 때도 이 부분을 넣으면 버그 해결 속도가 확 올라갑니다.

파이썬 지렁이게임 충돌처리 예시 이미지 2

게임오버 처리도 분리해야 안정적입니다

충돌이 발생한 프레임에 바로 루프를 끊어버리면, 마지막 화면이 그려지지 않아 사용자 입장에서 “왜 죽었는지”가 모호해집니다. 실전에서는 상태를 분리해서 처리하는 게 좋습니다.

추천 흐름은 이렇습니다. 충돌 시 state = GAME_OVER로 전환하고, 렌더 단계에서 게임오버 UI를 보여준 뒤 입력(재시작/종료)을 받습니다. 이 구조면 충돌 버그와 UI 버그를 별도로 볼 수 있어 유지보수가 쉬워집니다.

디버깅 로그는 좌표 3개만 찍어도 충분

복잡하게 전부 출력하지 말고 아래만 로그로 남기세요. 현재 머리, 다음 머리, 음식 위치. 이 세 값만 보면 충돌 오탐의 80%는 바로 원인이 보입니다.

자주 묻는 질문으로 마무리 점검

벽에 닿기 전에 죽어요

셀 단위와 픽셀 단위를 섞어 비교했을 가능성이 큽니다. 좌표 체계를 먼저 통일하세요.

몸통 충돌이 랜덤하게 나요

먹이 섭취 프레임 예외 처리가 빠졌는지 확인하세요. snake[:-1] 비교 규칙이 핵심입니다.

재시작하면 바로 다시 죽어요

방향값이나 snake 리스트 초기화가 완전하지 않은 경우가 많습니다. 게임 상태 전환 시 관련 변수 전체를 함께 리셋해야 합니다.

정리: 충돌처리는 코드량보다 판정 순서가 중요합니다

파이썬 지렁이게임 충돌처리에서 중요한 건 복잡한 알고리즘이 아니라 일관된 순서입니다. 다음 좌표 계산 → 벽 체크 → 몸통 체크 → 이동 반영 → 먹이 처리. 이 순서를 고정하면 버그가 줄고, 글을 보는 사람도 바로 따라 할 수 있습니다.

다음 단계로는 점수별 속도 증가 로직과 충돌처리를 합쳐 “후반 난이도 튜닝”을 해보세요. 여기까지 하면 단순 예제에서 완성도 있는 게임 글로 올라갑니다.

댓글 남기기

광고보고 콘텐츠 계속 읽기
원치않으시면 뒤로가기를 해주세요
광고보고 콘텐츠 계속 읽기
원치않으시면 뒤로가기를 해주세요