← 전체 프로젝트

수박 게임

알고리즘과게임콘텐츠 A+

Pygame과 Pymunk를 활용해 물리 충돌 기반의 공 합성 규칙을 작성하고 전체 게임 루프를 완성했습니다.

개발 기간
2023.10 ~ 2023.11
팀 구성
대학 수업 팀 프로젝트
담당 역할
조장 · 게임 루프·공 합성·모듈 데이터 연결
PythonPygamePymunk
수박 게임 게임 화면

같은 크기의 구체를 떨어뜨려 합치면서 더 큰 단계와 높은 점수를 노리는 물리 퍼즐 게임입니다. ‘알고리즘과게임콘텐츠’ 과목의 기말 팀 과제로 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 숙련도 차이를 세심하게 파악하지 못해, 막바지 통합과 핵심 로직 작성이 제게 쏠리는 아쉬움이 남았습니다. 이후 팀 프로젝트에서는 시작 단계에 각자 다뤄본 기술 범위를 먼저 확인하고, 작업 단위를 더 작고 명확한 입출력 단위로 쪼개어 배분하려 노력하고 있습니다. 짧은 중간 점검과 코드 공유를 자주 거치며 팀원 모두가 자기 손으로 기능을 완성해 볼 수 있는 환경을 만들고자 합니다.

다른 프로젝트 보기
© 2026 이유찬
Built with Astrofy