06. 여섯 번째 수업: 파이썬 파이게임(PyGame) 식 충돌 감지 매커니즘

게임 프로그래밍에서 원(원형 실드나 캐릭터, 운석 콜라이더 방어망) 의 충돌 로직은 사각형(AABB) 충돌보다 훨씬 계산이 아름답고 최적화가 강력합니다. “접선인가? 통과해버린 할선인가? 스쳐만 지나간 빗나감인가?”

우리가 앞에서 줄기차게 배운 중심점 좌표와 레이저 간의 “방향과 척도(Distance) 반경 비교 매크로” 가 파이썬 엔진에서 실제 충돌 충격파를 어떻게 찍어내는지 파이썬으로 가동해 보겠습니다!


1. 거리($\mathbf{d}$) 와 반지름($\mathbf{r}$) 의 배틀그라운드

게임 속 둥근 혜성(우주선 실드) 의 중심을 $C(xc, yc)$ 라 하고 방어막 반경을 $r$ 이라고 합시다. 이 둥근 실드를 향해 일직선 레이저 빔 한 줄기가 발사되어 날아갑니다. (이 레이저의 직선 방정식은 $ax + by + c = 0$ 꼴입니다.)

만약 레이저가 행성 방패 안에 닿아버린다면 (할선, 관통 데미지! 교점 생성!) 파이썬 컴퓨터는 모니터 화면 거리 단축키(직선과 점 사이의 거리 공식) 를 냅다 계산하여 반지름의 락다운 임계치와 교차 대입 비교를 때립니다.

  • $d = \frac{ a \times xc + b \times yc + c }{\sqrt{a^2 + b^2}}$ (이것이 중심 픽셀에서부터 레이저 빔까지 그은 가장 짧은 수직 최단 거리 스캐너!)

이 $d$ 가 산출되는 순간, 파이게임 콜라이더 충돌 로직은 $1$ 밀리초만에 결과를 스크린에 Print 시킵니다.

# [Python Code] 행성 실드(원) 과 레이저(직선) 의 충돌 스캐너 시뮬레이션
import math

class SpacePlanetCircle:
    def __init__(self, x, y, radius):
        self.cx = x       # 중심 X
        self.cy = y       # 중심 Y
        self.r = radius   # 방어막 반경 (레이더 경계선 영역 크기)

def laser_collision_scanner(planet, a, b, c):
    """
    레이저 선: a*x + b*y + c = 0 과 행성 충돌 스캐너를 돌린다.
    """
    # 1. 점(행성 정중앙 배꼽) 과 직선(레이저 궤적 선) 사이의 거리 d 를 계산
    # (모니터 픽셀상에서 레이저가 내 심장에 가장 가까이 빗겨 쳐 지나간 순간의 최단 갭 차이 계산)
    distance = abs(a * planet.cx + b * planet.cy + c) / math.sqrt(a**2 + b**2)
    
    print(f"|스캐너 레포트| 레이저 궤적과 내 심장의 최단 거리: {distance:.2f}px / 내 방어만 반경: {planet.r}px")
    
    # 2. 반지름 방어막 크기 임계치(Limit) 와 피가 튀는 비교 판정!
    if distance > planet.r:
        return "▶ [빗나감 (Missing!)] 다행입니다! 레이저가 방어막 바깥으로 멀리 스쳐 허공으로 날아갔습니다."
    elif distance == planet.r:  # (컴퓨터 부동소수점 오차 때문에 사실 math.isclose() 가 좋음)
        return "▶ [접선 스파크 (Grazed / Tangent!)] 오 마이 갓! 방어막 외곽 끝자락 단 1픽셀을 스치고 방어막이 덜덜 떨립니다! (접점 발생)"
    else:
        return "▶ [할선 관통 폭파 (Pierced / Secant!)] 데미지 작렬! 레이저가 방어막을 뚫고 내부를 난도질하며 관통해 박혔습니다! (비상경보)"

# ------ 시뮬레이션 콘라드 레이더 가동 ------- 
# (중심 0,0, 방어막 반경 5짜리 지구 행성 방어막 전개!)
earth_shield = SpacePlanetCircle(0, 0, 5)

# 1. 빗나가는 레이저 스크립트 발사 (y = 10, 즉 0*x + 1*y - 10 = 0)
print(laser_collision_scanner(earth_shield, 0, 1, -10))

# 2. 정확히 스치는 접선 스파크 발사 (x = 5 우측 끝단 스치기, 즉 1*x + 0*y - 5 = 0)
print(laser_collision_scanner(earth_shield, 1, 0, -5))

# 3. 배꼽을 무자비하게 뚫고 쳐지나가는 할선 (y = x, 즉 1*x - 1*y + 0 = 0)
print(laser_collision_scanner(earth_shield, 1, -1, 0))

2. 콘솔에 터져 나온 충돌 판정 (실전 스파크)

|스캐너 레포트| 레이저 궤적과 내 심장의 최단 거리: 10.00px / 내 방어만 반경: 5px
▶ [빗나감 (Missing!)] 다행입니다! 레이저가 방어막 바깥으로 멀리 스쳐 허공으로 날아갔습니다.

|스캐너 레포트| 레이저 궤적과 내 심장의 최단 거리: 5.00px / 내 방어만 반경: 5px
▶ [접선 스파크 (Grazed / Tangent!)] 오 마이 갓! 방어막 외곽 끝자락 단 1픽셀을 스치고 방어막이 덜덜 떨립니다! (접점 발생)

|스캐너 레포트| 레이저 궤적과 내 심장의 최단 거리: 0.00px / 내 방어만 반경: 5px
▶ [할선 관통 폭파 (Pierced / Secant!)] 데미지 작렬! 레이저가 방어막을 뚫고 내부를 난도질하며 관통해 박혔습니다! (비상경보)

어떻습니까? 무의식적으로 중학교 수학 교재에서 보던 “원의 중심에서 직선까지의 거리 $d$ 값과 원의 반지름 크기 $r$ 값의 크고 작음을 무작정 비교하세요!” 는 사실 단순 암기식이 아니었습니다. 그것은 현대의 우주 시뮬레이션 엔진, 자동차 자율 주행 라이다 스캐너망, 수만 마리의 슈팅 게임 총알 충돌 여부를 프레임 단위로 백만 번씩 모니터에 걸러내는 실시간 프로그래밍 Collision System 매크로 필터의 정수 그 자체였습니다!

행성 방어막의 반지름 반경 크기인 r과, 원의 중심에서 직선 레이저까지 최단 거리로 스캔해낸 d수치를 비교하여 거리가 멀면 빗나감, 같으면 접선 스파크, 더 짧으면 방어막 관통으로 파이썬 터미널 로그를 뿜어내는 충돌 콜라이더 엔진 처리 SVG

우주와 세계는 둥글고 원만하게 돌아갑니다. 그 원의 철벽을 두드리는 직선(레이저) 의 기하학적 난타전 액션과, 원 안을 복제해 채우고 도는 ‘원주각 불변 카메라 마법’ 스킬북 튜토리얼 과정을 이것으로 마칩니다. 수고하셨습니다. 다음 게임은 세상에서 가장 악마 같은 도박 카지노 베팅 모자이크, 파괴와 조합의 확률(Probability 1) 의 세계로 돌아오겠습니다!

서브목차