본문 바로가기
프로그래밍 언어/Python

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

by 연습장이 2023. 7. 3.
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
반응형