수박 게임
알고리즘과게임콘텐츠 A+Pygame과 Pymunk를 활용해 물리 충돌 기반의 공 합성 규칙을 작성하고 전체 게임 루프를 완성했습니다.
- 개발 기간
- 2023.10 ~ 2023.11
- 팀 구성
- 대학 수업 팀 프로젝트
- 담당 역할
- 조장 · 게임 루프·공 합성·모듈 데이터 연결
같은 크기의 구체를 떨어뜨려 합치면서 더 큰 단계와 높은 점수를 노리는 물리 퍼즐 게임입니다. ‘알고리즘과게임콘텐츠’ 과목의 기말 팀 과제로 Python의 Pygame과 Pymunk를 활용해 제작했습니다. 저는 조장을 맡아 메인 루프와 충돌 병합 알고리즘을 작성하고, 팀원들이 만든 개별 모듈을 하나로 묶었습니다.
흩어진 기능을 플레이 가능한 루프로 통합
마감이 다가왔을 때 개별 파일은 작성되어 있었으나 서로 데이터를 주고받지 못해 실행조차 되지 않는 상태였습니다. 남은 과제를 정리해 팀원들과 공유한 뒤, 구체 생성 → 물리 연산 → 동일 크기 병합 → 점수 가산의 네 단계를 중심으로 호출 순서를 새로 잡았습니다.
Game.run() 내부에서는 입력 감지, 물리 공간 및 스프라이트 갱신, 병합 판정, 제한선 초과 검사, 화면 그리기 순으로 매 프레임을 진행합니다. 물리 위치가 갱신된 직후 충돌 여부를 검사하고, 그 결과로 바뀐 단계와 점수가 곧바로 렌더링에 반영되도록 순서를 맞췄습니다.
self.handle_events()
self.update_physics_and_sprites()
self.merge_colliding_equal_balls()
self.check_ball_touched_boundary()
self.draw()
게임 오버 조건에 도달하면 물리 연산과 병합 검사를 멈추고 재시작·종료 키 입력만 받도록 분기했습니다. clock.tick(60)으로 초당 프레임 상한을 맞추고, 매 틱마다 space.step(1/60)으로 물리 시간을 전진시켰습니다. 개별 함수를 작성하는 것 못지않게 실행 순서와 상태 분기를 설계하는 일이 게임의 완성도를 좌우한다는 점을 배웠습니다.
접점 정보와 반지름을 조합한 합성 판정
병합 조건은 두 구체 사이에 물리적 접점이 존재하고 반지름이 일치하는 경우로 정의했습니다. 이중 반복문으로 전체 쌍을 순회하되, 안쪽 인덱스를 i + 1부터 시작해 자기 자신과의 비교나 동일 쌍의 중복 검사를 피했습니다.
Pymunk의 shapes_collide()로 두 도형의 접점을 구하고, 반환된 points 배열이 비어 있지 않을 때만 반지름 일치 여부를 확인했습니다. 기하학적인 충돌 계산은 물리 엔진에 맡기고, 그 위에 탐색 루프와 단계 상승 규칙을 얹는 방식으로 구현했습니다.
조건에 부합하면 두 중심점의 평균 좌표에 다음 단계의 구체를 생성해 관리 리스트와 스프라이트 그룹에 등록한 뒤 점수를 올립니다. 기존에 부딪힌 두 객체는 리스트·스프라이트 그룹·물리 공간(space)에서 모두 제거했습니다. 최고 단계끼리 만난 경우에는 새 객체를 만들지 않고 점수만 가산한 뒤 소멸시켰습니다.
순회 도중 리스트 원소가 바뀌어 인덱스 오류가 나지 않도록, 한 쌍이라도 병합이 일어나면 즉시 함수에서 return하도록 처리했습니다. 이에 따라 한 프레임에는 최대 한 쌍만 합쳐지며, 동시에 맞닿은 다른 후보들은 곧바로 다음 프레임에서 처리됩니다.
결과와 구조적 한계

분산되어 있던 모듈의 입출력을 맞추고 버그를 잡아 기한 내에 완주 가능한 빌드를 제출했고, 과목 성적으로 A+를 받았습니다. 공식 문서에서 외부 라이브러리의 API 명세를 찾아 읽고 프로젝트 요구사항에 맞게 응용하는 훈련이 되었습니다.
다만 당시 작성한 방식은 충돌 이벤트 콜백을 쓰지 않고 매 프레임 모든 쌍을 전수 조사합니다. 화면에 놓인 객체 수가 n개일 때 비교 횟수가 최대 n(n - 1) / 2번에 달해 시간 복잡도가 O(n²)이 됩니다. 개수가 늘어날수록 연산 부담이 커지고, 동시 다발적인 병합이 프레임을 건너 순차 처리되는 한계가 있습니다.
이를 다시 개선한다면 Pymunk의 충돌 핸들러 콜백으로 접촉 쌍만 수집해 두고, 물리 스텝이 끝난 뒤 한 번에 처리하는 구조로 바꾸고 싶습니다. 이미 병합에 사용된 객체만 집합(Set)으로 걸러내면 서로 무관한 여러 쌍을 같은 프레임에 합칠 수 있습니다. 아울러 리스트 등록 순서에 의존하던 판정 기준 대신, 화면 중앙과의 거리처럼 명확한 우선순위 규칙을 도입해 볼 수 있습니다.
협업에서 배운 점
초기에 팀원들의 Python 숙련도 차이를 세심하게 파악하지 못해, 막바지 통합과 핵심 로직 작성이 제게 쏠리는 아쉬움이 남았습니다. 이후 팀 프로젝트에서는 시작 단계에 각자 다뤄본 기술 범위를 먼저 확인하고, 작업 단위를 더 작고 명확한 입출력 단위로 쪼개어 배분하려 노력하고 있습니다. 짧은 중간 점검과 코드 공유를 자주 거치며 팀원 모두가 자기 손으로 기능을 완성해 볼 수 있는 환경을 만들고자 합니다.