프로그래밍 언어/Python

[Python] cave 게임 소스 코드 분석

연습장이 2023. 7. 3. 20:42
728x90
반응형

개요

  간단한 가로 스크롤 게임이다. 많은 직사각형을 뿌리면서 가로 방향으로 나열해서 동굴을 표현하였다. 프레임마다 모든 직사각형을 왼쪽 방향으로 움직이고, 맨 앞(왼쪽 끝)의 직사각형을 제거, 오른쪽 끝에 새로운 직사각형을 추가해 가로 방향의 스크롤을 구현하였다.

 

게임 화면

 

소스 코드

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 27 23:05:14 2023

@author: june
"""

""" cave - Copyright 2016 Kenichiro Tanaka """
# 게임을 종료하기 위해 sys 라이브러리를 가져옴
import sys
# random 패키지에서 radint 라이브러리를 가져옴
from random import randint 
# 게임을 만들기 위해 pygame 패키지를 다 가져옴
import pygame
"""
pygame 패키지의 locals 서브모듈 중 
QUIT : 이벤트가 종료를 의미할 경우를 체크하기 위함
Rect : 동굴을 표현할 직사각형을 표현하기 위함
KEYDOWN : 방향키를 아래로 해서 우주선이 내려감을 표현하기 위함
K_SPACE : 스페이스를 눌러 우주선이 올라감을 표현하기 위함
"""
from pygame.locals import QUIT, Rect, KEYDOWN, K_SPACE

# pygame을 초기화한다.
pygame.init()
# 키를 누르고 있을 때 반본적으로 키를 입력할 수 있도록 한다.
pygame.key.set_repeat(5, 5)
# 800x600 크기의 화면을 만든다.
SURFACE = pygame.display.set_mode((800, 600))
# 시간값을 할당하는 변수를 선언한다.
FPSCLOCK = pygame.time.Clock()

def main():
    """ 메인 루틴 """
    # 동굴을 구성하는 직사각형의 수
    walls = 80
    # 내 캐릭터(우주선)의 Y 좌표
    ship_y = 250
    # 내 캐릭터가 상하로 이동할 때의 속도
    velocity = 0
    # 점수
    score = 0
    # 동굴의 기울기로 위 아래 동굴이 움직이는 연출을 위함인듯 함
    slope = randint(1, 6)
    # 글씨체 가져옴
    sysfont = pygame.font.SysFont(None, 36)
    # 배 이미지 가져옴
    ship_image = pygame.image.load("C:/Users/june/.spyder-py3/Samples/games/cave/ship.png")
    # 배가 동굴에 부딪혀서 게임오버 되었을 때 이미지 가져옴
    bang_image = pygame.image.load("C:/Users/june/.spyder-py3/Samples/games/cave/bang.png")
    # 동굴을 구성하는 직사각형을 저장하는 배열
    holes = []
    # 직사각형을 반복문으로 생성하여 배열에 저장
    for xpos in range(walls):
        holes.append(Rect(xpos * 10, 100, 10, 400))
    # 게임시작 시 게임오버 되지 않은 상태로 초기화
    game_over = False
    
    while True:
        # 스페이스 버튼을 처음엔 안누르고 있으니 False 로 초기화
        is_space_down = False
        # 게임이 종료되었는지 확인. 그게 아니면 스페이스 버튼이 눌렸는지 확인
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_SPACE:
                    is_space_down = True
        
        # 내 캐릭터를 이동
        if not game_over:
            # while문이 한번 돌 때마다 점수 10점씩 추가
            score += 10
            # 누르고 있으면 점점 빨라짐
            velocity += -3 if is_space_down else 3
            # 속도 만큼 내 캐릭터 이동
            ship_y += velocity
            
            #  동굴을 스크롤함. 가장 오른쪽(끝) 배열값 가져옴
            edge = holes[-1].copy()
            # 천장이나 바닥에 부딪혔는지 확인하기 위해 변수값 생성
            test = edge.move(0, slope)
            # 천장이나 바닥에 부딪혔으면
            if test.top <= 0 or test.bottom >= 600:
                # 벽의 방향을 바꿔줌
                slope = randint(1, 6) * (-1 if slope > 0 else 1)
                # Y 방향의 크기를 20만큼 작게 해서 동굴이 위아래로 움직이는 느낌을 주도록 함
                edge.inflate_ip(0, -20)
            # 기울기가 적용된 새로운 끝 값을 생성함
            edge.move_ip(10, slope)
            # 그 값을 배열 끝에 추가
            holes.append(edge)
            # 화면에서 왼쪽 끝(지나간 값) 배열을 제거
            del holes[0]
            # 전체를 10 왼쪽으로 이동
            holes = [x.move(-10, 0) for x in  holes]
            
            # 충돌?
            if holes[0].top > ship_y or \
                holes[0].bottom < ship_y + 80:
                    game_over = True
            
        # 그리기
        SURFACE.fill((0, 255, 0))
        for hole in holes:
            pygame.draw.rect(SURFACE, (0, 0, 0), hole)
        SURFACE.blit(ship_image, (0, ship_y))
        score_image = sysfont.render("Practicer's score is {}".format(score), True, (0, 0, 255))
        SURFACE.blit(score_image, (500, 20))
        
        if game_over:
        	# 게임오버면 내 캐릭터가 폭발하는 이미지를 가져옴
            SURFACE.blit(bang_image, (0, ship_y-40))
        # 위 내용들을 반영하여 게임 화면에 갱신함    
        pygame.display.update()
        # 1초에 15번 while이 수행됨
        FPSCLOCK.tick(15)

# 메인 함수를 호출함. 사실 상 위 내용들은 정의에 불과하고 아래가 실행 되어야 함
if __name__ == '__main__':
    main()

 

* 참고문헌

- 다카나 겐이치로 저, "게임으로 배우는 파이썬"

728x90
반응형