[Programming]/[Language]

[Python] 나도코딩_활용편1 / Finished 22.08.17

김파고띠 2022. 7. 18. 22:36

나도 코딩 [활용편1]

공부 & 정리


| 공부 자료

Pygame_Basic.zip
0.01MB
Pygame_Project.zip
0.04MB


[1] 소개

활용편은
	- 라이브러리 기초 사용법
	- 8개의 실전 프로젝트
		> 원래는 각 프로젝트마다 두꺼운 책 한권 분량이기 때문에,
		개발에 필요한 라이브러리의 기초 사용법은 다루지만
		모든 내용을 깊게 다루지는 않는다
고로 목적을
	어떻게 파이썬을 활용할 수 있는지 파악하는 것.
    마음에 드는 프로젝트를 발견 시 더 자세히, 깊게 다루는
    방식으로 공부를 진행하는 것을 추천

[2] 활용편1 소개

활용편 1은 게임 개발

Pygame이라는 게임 개발용 라이브러리가 있다.

Pygame을 활용해서 옛날 오락실 게임을 만들어 볼 것

[3] 환경설정 & 프레임

 

| 환경설정

1. 라이브러리 설치
	터미널에 pip install pygame 코드 실행
    + python anywhere에서는 bash console에서 실행

| 문제 발견

'''

에러 내용 :
	No available video device error

설명 :
    현재 IDE 혹은 에디터를 사용할 수 없는 환경이다 보니
    클라우드 기반 IDE를 사용하는데 구름 IDE에서 에러에 봉착
    구름 IDE는 화면이 없는 환경이기 때문에 발생하는 문제라고 판단됌

임시 해결법 :
    우선 소프트웨어 스택으로 python을 선택한 후에 아래쪽 템플릿을 선택할 수 있는 곳에서
    pygame 템플릿을 선택함. 그 이후에 설치된 컨테이너 안에 있는
    index.py에 코드를 작성하고, new run pyqt를 이용해서 코드를 실행한다

Reference
1.
https://forum.goorm.io/topic/7065/%EA%B5%AC%EB%A6%84ide%EC%97%90%EC%84%9C-pygame-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94%EB%B2%95/2
2.
http://13.124.228.240/topic/11053/%EA%B5%AC%EB%A6%84-ide-pygame-tkinter-%EC%82%AC%EC%9A%A9-%EC%A7%88%EB%AC%B8%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4/2

------------------------------------------------------------------------------

해결하고 싶은 점 :
	1. index.py가 아닌 다른 파일을 통해서 실행할 수 있는 방법은 없나

'''

 

| 프레임

| CODE

import pygame

# 초기화 (반드시 필요)
pygame.init()

# 화면 크기 설정
screen_width = 480 # 가로 크기
screen_height = 640 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

# 화면 타이틀 설정
pygame.display.set_caption("Hero Game") # 게임 이름

# 이벤트 루프
running = True #게임이 진행중인가?
while running:
	for event in pygame.event.get(): # 어떤 이벤트가 발생하였는가?
    	if event.type == pygame.QUIT: # 창이 닫히는 이벤트가 발생하였는가?
        	running = False # 게임이 진행중이 아님 ( 값 변경 )
'''
사용자의 동작(키 입력/마우스 클릭)을 계속 검사하는 이벤트 루프
Pygame에서는 이벤트 루프가 계속 실행되고 있어야 창이 꺼지지 않는다.
'''

# pygame 종료
pygame.quit()

[4] 배경

배경 코드를 작성할 때 [3]환경설정&프레임에서 사용한 소스 코드를 사용하지 않고

새로 작성할텐데 그것은 새로 작성할 부분도, 추가할 부분이 있기도 하고

어떻게 달라지는지 복습을 하기 위함

BUT

index.py 파일이 아닐 시에는 pyqt에서 작동하지 않아서 우선 이 문제를 해결하기 전까지는

index.py에서 소스 코드를 진행하기로 함

 

| CODE

# 2_background.py

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

# 배경 이미지 불러오기
background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/background.png")

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    screen.blit(background, (0,0)) # 배경 그리기 (= (0,0)은 좌표값 (x,y)_좌상단 꼭짓점 기준 )
    # screen.fill((0,0,255)) # 배경을 색으로 채우는 것
    
    pygame.display.update() # 게임화면을 다시 그리기! ( 배경을 프레임마다 계속 그리는 것 )

pygame.quit()

'''
이미지 경로 지정 시
일반 경로로 했을 때는 안되었는데,
절대 경로로 다시 해보니 되었다.
절대 경로와 상대 경로의 차이점에 대해서
알아볼 필요가 있다는 생각이 들었다.
'''

[5] 캐릭터

 

| CODE

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/background.png")

# 캐릭터(스프라이트) 불러오기
character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/character.png")
character_size = character.get_rect().size # 이미지의 크기를 구해줌
character_width = character_size[0] # 캐릭터의 가로 크기
character_height = character_size[1] # 캐릭터의 세로 크기
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 ) # 화면 가로의 절반 크기에 해당하는 곳에 위치
character_y_pos = screen_width - character_height # 화면 세로 크기 가장 아래 해당하는 곳에 위치

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    screen.blit(background, (0,0))
    
    screen.blit(character, (character_x_pos, character_y_pos)) # 캐릭터 그리기

    pygame.display.update()

pygame.quit()

'''
character_x_pos, character_y_pos의 좌표값이
단순히 screen의 가로, 세로 값이 아닌 이유는
입력된 좌표값의 (오른쪽, 밑)으로 그려지기 때문에
그만큼의 계산을 해준 후에 좌표값을 입력하는 것
'''

[6] 키보드 이벤트

 

| 문제 발견

'''
에러 내용 :
inconsistent use of tabs and spaces in indentation

설명 :
파이썬에서는 같은 길이의 공백이더라도
탭을 이용한 것과 스페이스바를 이용한 것을 다르게 읽기 때문에
통일을 해주어야 한다

해결법 :
	1) 탭 혹은 스페이스바 한쪽으로 통일을 하면된다
    2) autopep8이라는 모듈을 설치한다
    	autopep8?
        	파이썬 코드를 자동으로 pep8 스타일 가이드에 맞추어 수정해준다.
'''

| CODE

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/background.png")

character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height

# 이동할 좌표
to_x = 0
to_y = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN: # 키가 눌러졌는지 확인
            if event.key == pygame.K_LEFT: # 캐릭터를 왼쪽으로
                to_x -= 1
            elif event.key == pygame.K_RIGHT: # 캐릭터를 오른쪽으로
                to_x += 1
            elif event.key == pygame.K_UP: # 캐릭터를 위로
                to_y -= 1
            elif event.key == pygame.K_DOWN: # 캐릭터를 아래로
                to_y += 1
    
        if event.type == pygame.KEYUP: #방향키를 떼면 멈춤
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                to_y = 0
    
    character_x_pos += to_x
    character_y_pos += to_y
    
    # 가로 경계값 처리
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    # 세로 경계값 처리
    if character_y_pos < 0:
        character_y_pos = 0
    elif character_y_pos > screen_height - character_height :
        character_y_pos = screen_height - character_height
        
    screen.blit(background, (0,0))
    
    screen.blit(character, (character_x_pos, character_y_pos))

    pygame.display.update()

pygame.quit()

[7] FPS

FPS : Frame per second ( 초당 프레임 )

 

| CODE

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/background.png")

character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height

to_x = 0
to_y = 0

# 이동 속도
character_speed = 0.6

running = True
while running:
    dt = clock.tick(10) # 게임화면의 초당 프레임 수를 설정
    
    # FPS 몇인지 출력할 수 있는 코드
    # print("FPS" + str(clock.get_fps()))
    
    # 캐릭터가 1초 동안에 100만큼 이동 시?
    # 10 fps : 1초 동안 10번 동작 > 1번에 10만큼, 10*10=100
    # 20 fps : 1초 동안 20번 동작 > 1번에 5만큼, 5*20=100
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        # character_speed로 변경
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                to_x += character_speed
            elif event.key == pygame.K_UP:
                to_y -= character_speed
            elif event.key == pygame.K_DOWN:
                to_y += character_speed
    
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                to_y = 0
    
    # 프레임이 달라진다고 게임 자체의 속도가 변하면 안됌
    # 그렇기 때문에 값에 dt값을 곱한다
    
    character_x_pos += to_x * dt
    character_y_pos += to_y * dt
    
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    if character_y_pos < 0:
        character_y_pos = 0
    elif character_y_pos > screen_height - character_height :
        character_y_pos = screen_height - character_height
        
    screen.blit(background, (0,0))
    
    screen.blit(character, (character_x_pos, character_y_pos))

    pygame.display.update()

pygame.quit()

[8] 충돌 처리

 

| CODE

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/background.png")

character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height

to_x = 0
to_y = 0

# 적 캐릭터 불러오기
enemy = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/enemy.png")
enemy_size = enemy.get_rect().size # 이미지의 크기를 구해줌
enemy_width = enemy_size[0] # 캐릭터의 가로 크기
enemy_height = enemy_size[1] # 캐릭터의 세로 크기
enemy_x_pos = ( screen_width / 2 ) - ( enemy_width / 2 ) # 화면 가로의 절반 크기에 해당하는 곳에 위치
enemy_y_pos = ( screen_height / 2 ) - ( enemy_height / 2 ) # 화면 세로의 절반 크기에 해당하는 곳에 위치

character_speed = 0.6

running = True
while running:
    dt = clock.tick(10)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                to_x += character_speed
            elif event.key == pygame.K_UP:
                to_y -= character_speed
            elif event.key == pygame.K_DOWN:
                to_y += character_speed
    
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                to_y = 0
    
    character_x_pos += to_x * dt
    character_y_pos += to_y * dt
    
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    if character_y_pos < 0:
        character_y_pos = 0
    elif character_y_pos > screen_height - character_height :
        character_y_pos = screen_height - character_height
        
    # 충돌 처리를 위한 rect 정보 업데이트
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    enemy_rect = enemy.get_rect()
    enemy_rect.left = enemy_x_pos
    enemy_rect.top = enemy_y_pos
    
    # 충돌 처리
    if character_rect.colliderect(enemy_rect):
        print("Crashed")
        running = False
        
    screen.blit(background, (0,0))
    
    screen.blit(character, (character_x_pos, character_y_pos))
    screen.blit(enemy, (enemy_x_pos, enemy_y_pos)) # 적 캐릭터 그리기

    pygame.display.update()

pygame.quit()

[9] 텍스트

import pygame

pygame.init()

screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Game")

clock = pygame.time.Clock()

background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/background.png")

character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height

to_x = 0
to_y = 0

enemy = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/enemy.png")
enemy_size = enemy.get_rect().size
enemy_width = enemy_size[0]
enemy_height = enemy_size[1]
enemy_x_pos = ( screen_width / 2 ) - ( enemy_width / 2 )
enemy_y_pos = ( screen_height / 2 ) - ( enemy_height / 2 )

character_speed = 0.6

# 폰트 정의
game_font = pygame.font.Font(None, 40) # 폰트 객체 생성 (폰트, 크기)

# 총 시간
total_time = 10

# 시간 계산
start_ticks = pygame.time.get_ticks() # 현재 tick을 받아옴

running = True
while running:
    dt = clock.tick(60)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                to_x += character_speed
            elif event.key == pygame.K_UP:
                to_y -= character_speed
            elif event.key == pygame.K_DOWN:
                to_y += character_speed
    
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                to_y = 0

    character_x_pos += to_x * dt
    character_y_pos += to_y * dt
    
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    if character_y_pos < 0:
        character_y_pos = 0
    elif character_y_pos > screen_height - character_height :
        character_y_pos = screen_height - character_height

    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    enemy_rect = enemy.get_rect()
    enemy_rect.left = enemy_x_pos
    enemy_rect.top = enemy_y_pos
    
    if character_rect.colliderect(enemy_rect):
        print("Win")
        running = False
    
    screen.blit(background, (0,0))
    
    screen.blit(character, (character_x_pos, character_y_pos))
    screen.blit(enemy, (enemy_x_pos, enemy_y_pos))

    # 타이머 집어 넣기
    # 경과 시간 계산
    elapsed_time = (pygame.time.get_ticks() - start_ticks) / 1000
    # 경과 시간(ms)을 1000으로 나누어서 초(s) 단위로 표시
    
    timer = game_font.render(str(int(total_time - elapsed_time)), True, (255, 255, 255))
    # (출력할 글자, True, 글자 색상)
    screen.blit(timer, (10, 10))
    
    if (total_time - elapsed_time) <= 0:
        print("Time-out")
        running = False
    
    pygame.display.update()

# 잠시 대기
pygame.time.delay(2000) # 2초 정도 대기 (ms)

pygame.quit()

| Dig

'''

의문점 :
    elapsed_time 변수 안에 [ (pygame.time.get_ticks() - start_ticks) / 1000 ] 값을 집어 넣는데,
    이미 pygame.time.get_ticks()이 할당된 start_ticks를 왜 빼는지 이해가 되지 않는다.

시도 :
그래서 2가지 방법을 추가적으로 시도 해봤다.
    1. start_ticks / 1000
    2. pygame.time.get_ticks() / 1000

해결 :
	pygame.time.get_ticks() - start_ticks를 한 이유는
    pygame.time.get_ticks()는 pygame.init()이 실행된 순간부터 얻은 tick이고,
    start_ticks는 이벤트 루프 안에서 실행된 순간부터의 tick이기 때문에
    뺀 것인가에 대한 생각을 했다.

아쉬운 점 :
	이 결론에 대한 피드백을 받을 곳이 없는 것이 아쉽다
    
Ref :
	https://www.pygame.org/docs/ref/time.html
    >
    pygame.time.get_ticks()는
    pygame.init()이 실행된 이후 밀리초 단위로 값을 반환
    실행되기 전에는 항상 0.

'''

[10] 게임 개발 프레임

 

| CODE

설명 : 게임을 만들 때 기본적인 프레임을 구성해본 것

import pygame

#############################################################
# 기본 초기화 (반드시 해야하는 것들)

pygame.init()

# 화면 크기 설정
screen_width = 480 # 가로 크기
screen_height = 640 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

# 화면 타이틀 설정
pygame.display.set_caption("Hero Game") # 게임 이름

# FPS
clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # 3. 게임 캐릭터 위치 정의
  
    # 4. 충돌 처리
    
	# 5. 화면에 그리기
    
    pygame.display.update()
    

pygame.quit()

[11] 퀴즈 전반전

 

| QUIZ

주제 :
하늘에서 떨어지는 똥 피하기 게임을 만든다

게임 조건 :
	1. 캐릭터는 화면 가장 아래에 위치, 좌우로만 이동 가능
	2. 똥은 화면 가장 위에서 떨어짐. X 좌표는 매번 랜덤으로 설정
	3. 캐릭터가 똥을 피하면 다음 똥이 다시 떨어짐
	4. 캐릭터가 똥과 충돌하면 게임 종료
	5. FPS는 30으로 고정

게임 이미지 :
	1. 배경 : 640 * 480 ( 세로 가로 ) - background.png
	2. 캐릭터 : 70 * 70 - character.png
	3. 똥 : 70 * 70 - enemy.png

| CODE

import pygame

#############################################################
# 기본 초기화 (반드시 해야하는 것들)

pygame.init()

# 화면 크기 설정
screen_width = 480 # 가로 크기
screen_height = 640 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

# 화면 타이틀 설정
pygame.display.set_caption("Quiz") # 게임 이름

# FPS
clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

# 배경 만들기
background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/background.png")

# 캐릭터 만들기
character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/character.png")
character_size = character.get_rect().character_size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = (screen_width/2) - (character_width/2)
character_y_pos = screen_height - character_height

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # 3. 게임 캐릭터 위치 정의
  
    # 4. 충돌 처리
    
	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    screen.blit(character, (character_x_pos, character_y_pos))
    
    pygame.display.update()
    
pygame.quit()

[12] 퀴즈 후반전


| CODE

import pygame
import random

#############################################################
# 기본 초기화 (반드시 해야하는 것들)

pygame.init()

# 화면 크기 설정
screen_width = 480 # 가로 크기
screen_height = 640 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

# 화면 타이틀 설정
pygame.display.set_caption("Quiz") # 게임 이름

# FPS
clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

# 배경 만들기
background = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/background.png")

# 캐릭터 만들기
character = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = (screen_width/2) - (character_width/2)
character_y_pos = screen_height - character_height

# 이동 위치
to_x = 0
character_speed = 10

# 똥 만들기
ddong = pygame.image.load("/workspace/NanoCod_Utl_1_Game/study_files/enemy.png")
ddong_size = ddong.get_rect().size
ddong_width = ddong_size[0]
ddong_height = ddong_size[1]
ddong_x_pos = random.randint(0, screen_width - ddong_width)
ddong_y_pos = 0
ddong_speed = 20


running = True
while running:
    dt = clock.tick(30)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                to_x += character_speed
                
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0

    # 3. 게임 캐릭터 위치 정의
    character_x_pos += to_x
        
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width:
        character_x_pos = screen_width - character_width
            
    ddong_y_pos += ddong_speed
        
    if ddong_y_pos > screen_height:
        ddong_y_pos = 0
        ddong_x_pos = random.randint(0, screen_width - ddong_width)

    # 4. 충돌 처리
    
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    ddong_rect = ddong.get_rect()
    ddong_rect.left = ddong_x_pos
    ddong_rect.top = ddong_y_pos
    
    if character_rect.colliderect(ddong_rect):
        print("Crush!")
        running = False
    
	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    screen.blit(character, (character_x_pos, character_y_pos))
    screen.blit(ddong, (ddong_x_pos, ddong_y_pos))
    
    pygame.display.update()
    
pygame.quit()

[13] 프로젝트 설명

 

| Project

Project :
	오락실 Pang 게임 만들기

게임 조건 :
	1. 캐릭터는 화면 아래에 위치, 좌우로만 이동 가능
    2. 스페이스를 누르면 무기를 쏘아 올림
    3. 큰 공 1개가 나타나서 바운스
    4. 무기에 닿으면 공은 작은 크기 2개로 분할, 가장 작은 크기의 공은 사라짐
    5. 모든 공을 없애면 게임 종료 (성공)
    6. 캐릭터는 공에 닿으면 게임 종료 (실패)
    7. 시간 제한 99초 초과 시 게임 종료 (실패)
    8. FPS는 30으로 고정 (필요시 speed 값을 조정)
    
게임 이미지 :
	1. 배경 : 640 * 480 (가로 세로) - background.png
    2. 무대 : 640 * 50 - stage.png
    3. 캐릭터 : 60 * 30 - character.png
    4. 무기 : 20 * 430 - weapon.png
    5. 공 : 160 * 160, 80 * 80, 40 * 40, 20 * 20 - balloon1.png ~ balloon4.png

[14] 배경과 캐릭터

import pygame
import os # os 모듈 import

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__) # 현재 파일의 위치 변환
image_path = os.path.join(current_path, "images") # images 폴더 위치 반환
# 배경 만들기
background = pygame.image.load(os.path.join(image_path, "background.png"))
# 스테이지 만들기
stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1] # 스테이지 높이 위에 캐릭터를 두기 위해 사용
# 캐릭터 만들기
character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

running = True
while running:
    dt = clock.tick(60)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos,character_y_pos))
    
    pygame.display.update()
    
pygame.quit()

[15] 무기와 키보드 이벤트

import pygame
import os

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images")

background = pygame.image.load(os.path.join(image_path, "background.png"))

stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1]

character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

# 무기 만들기
weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

# 무기는 한 번에 여러 발 발사 가능
weapons = []

# 무기 이동 속도
weapon_speed = 10 

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT: # 캐릭터를 왼쪽으로
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT: # 캐릭터를 오른쪽으로
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE: # 무기 발사
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    # 무기 위치 조정 ( 한줄 for 활용 )
    weapons = [ [w[0], w[1] - weapon_speed] for w in weapons ]
    	# 무기 위치를 위로
    	# 100, 200 -> 180, 160, 140, ...
        # 500, 200 -> 180, 160, 140, ...
        # 무기의 x좌표 값은 변함이 없지만, 무기의 y좌표 값은 변한다 ( 무기를 쏘고나면 줄어드니까 )
    
    # 천장에 닿은 무기 없애기
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    # 순서대로 그리기 때문에 이렇게 위치를 조정해야 무기가 스테이지, 캐릭터 밑에 그려짐 ( 레이어 상에서 우선 )
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos,character_y_pos))
    
    pygame.display.update()
    
pygame.quit()

 


[16] 공 만들기 & [17] 공 튕기기

 

| CODE

import pygame
import os

#############################################################

pygame.init()

screen_width = 640 # 가로 크기
screen_height = 480 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang") # 게임 이름

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images") # images

background = pygame.image.load(os.path.join(image_path, "background.png"))

stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1] # 스테이지 높이 위에 캐릭터를 두기 위해 사용

character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

weapons = []

weapon_speed = 10

# 공 만들기 (4개 크기에 대해 따로 처리)
ball_images =[
    pygame.image.load(os.path.join(image_path, "balloon1.png")),
    pygame.image.load(os.path.join(image_path, "balloon2.png")),
    pygame.image.load(os.path.join(image_path, "balloon3.png")),
    pygame.image.load(os.path.join(image_path, "balloon4.png"))
]

# 공 크기에 따른 최초 스피드
ball_speed_y = [-18, -15, -12, -9] # index 0, 1, 2, 3에 해당하는 값

# 공들
balls = []

# 최초 발생하는 큰 공 추가
balls.append({
    "pos_x" : 50, # 공의 X좌표
    "pos_y" : 50, # 공의 Y좌표
    "img_idx" : 0, # 공의 이미지 인덱스
    "to_x" : 3, # x축 이동방향, -3이면 왼쪽으로, 3이면 오른쪽으로
    "to_y" : -6, # y축 이동방향
    "init_spd_y" : ball_speed_y[0] # y 최초 속도
})

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE:
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    weapons = [ [w[0], w[1] - weapon_speed] for w in weapons ]
    
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
    # 공 위치 정의
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]
        
        ball_size = ball_images[ball_img_idx].get_rect().size
        ball_width = ball_size[0]
        ball_height = ball_size[1]
        
    	# 가로벽에 닿았을 때 공 이동 위치 변경 (튕겨 나오는 효과)
        if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
            ball_val["to_x"] = ball_val["to_x"] * -1
        
        # 세로 위치
        # 스테이지에 튕겨서 올라가는 처리
        if ball_pos_y >= screen_height - stage_height - ball_height :
            ball_val["to_y"] = ball_val["init_spd_y"]
        else: # 그 외의 모든 경우에는 속도를 증가 (속도 줄여나감/마이너스로 증가)
            ball_val["to_y"] += 0.5
    
        ball_val["pos_x"] += ball_val["to_x"]
        ball_val["pos_y"] += ball_val["to_y"]
    
    # 4. 충돌 처리
    
	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
    
    for idx, val in enumerate(balls):
        ball_pos_x = val["pos_x"]
        ball_pos_y = val["pos_y"]
        ball_img_idx = val["img_idx"]
        screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos,character_y_pos))
    
    
        
    pygame.display.update()
    
pygame.quit()

| +

# for 변수_1, 변수_2 in enumerate( ) :

# 1번째 변수는 인덱스가, 2번째 변수는 인덱스에 해당하는 값이 뜸
# 즉 리스트를 순회하면서 인덱스와 그 인덱스에 해당하는 값이 뜸

lst = ["Hero", "Harvey", "Cookie"]

for l_idx, l_val in enumerate(lst):
    print(l_idx, l_val)

[18] 충돌처리

| Code

import pygame
import os

#############################################################

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images")

background = pygame.image.load(os.path.join(image_path, "background.png"))

stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1]

character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

weapons = []

weapon_speed = 10

ball_images =[
    pygame.image.load(os.path.join(image_path, "balloon1.png")),
    pygame.image.load(os.path.join(image_path, "balloon2.png")),
    pygame.image.load(os.path.join(image_path, "balloon3.png")),
    pygame.image.load(os.path.join(image_path, "balloon4.png"))
]

ball_speed_y = [-18, -15, -12, -9]

balls = []

balls.append({
    "pos_x" : 50,
    "pos_y" : 50,
    "img_idx" : 0,
    "to_x" : 3,
    "to_y" : -6,
    "init_spd_y" : ball_speed_y[0]
})

# 사라질 무기, 공 정보 저장 변수
weapon_to_remove = -1
ball_to_remove = -1

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE:
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    weapons = [ [ w[0], w[1] - weapon_speed] for w in weapons ]
    
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]
        
        ball_size = ball_images[ball_img_idx].get_rect().size
        ball_width = ball_size[0]
        ball_height = ball_size[1]
        
        if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
            ball_val["to_x"] = ball_val["to_x"] * -1
        
        if ball_pos_y >= screen_height - stage_height - ball_height :
            ball_val["to_y"] = ball_val["init_spd_y"]
        else:
            ball_val["to_y"] += 0.5
    
        ball_val["pos_x"] += ball_val["to_x"]
        ball_val["pos_y"] += ball_val["to_y"]
    
    # 4. 충돌 처리
    
    # 캐릭터 정보 업데이트
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]

        # 공 rect 정보 업데이트
        ball_rect = ball_images[ball_img_idx].get_rect()
        ball_rect.left = ball_pos_x
        ball_rect.top = ball_pos_y
        
        # 공과 캐릭터 충돌 처리
        if character_rect.colliderect(ball_rect):
            running = False
            break
        
        for weapon_idx, weapon_val in enumerate(weapons):
            weapon_pos_x = weapon_val[0]
            weapon_pos_y = weapon_val[1]
            
            # 무기 rect 정보 업데이트
            weapon_rect = weapon.get_rect()
            weapon_rect.left = weapon_pos_x
            weapon_rect.top = weapon_pos_y
            
            # 충돌 체크
            if weapon_rect.colliderect(ball_rect):
                # 원래는 공을 쪼개는 것인데 우선 다음 장에서 하니까 없애는 것으로 코딩
                weapon_to_remove = weapon_idx
                ball_to_remove = ball_idx
                break
    
    # 충돌된 공 or 무기 없애기
    if weapon_to_remove > -1 :
        del weapons[weapon_to_remove]
        weapon_to_remove = -1
    if ball_to_remove > -1 :
        del balls[ball_to_remove]
        ball_to_remove = -1
                

	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
    
    for idx, val in enumerate(balls):
        ball_pos_x = val["pos_x"]
        ball_pos_y = val["pos_y"]
        ball_img_idx = val["img_idx"]
        screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos, character_y_pos))
    
        
    pygame.display.update()
    
pygame.quit()

[19] 공 쪼개기

import pygame
import os

#############################################################

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images")

background = pygame.image.load(os.path.join(image_path, "background.png"))

stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1]

character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

weapons = []

weapon_speed = 10

ball_images =[
    pygame.image.load(os.path.join(image_path, "balloon1.png")),
    pygame.image.load(os.path.join(image_path, "balloon2.png")),
    pygame.image.load(os.path.join(image_path, "balloon3.png")),
    pygame.image.load(os.path.join(image_path, "balloon4.png"))
]

ball_speed_y = [-18, -15, -12, -9]

balls = []

balls.append({
    "pos_x" : 50,
    "pos_y" : 50,
    "img_idx" : 0,
    "to_x" : 3,
    "to_y" : -6,
    "init_spd_y" : ball_speed_y[0]
})

weapon_to_remove = -1
ball_to_remove = -1

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE:
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    weapons = [ [ w[0], w[1] - weapon_speed] for w in weapons ]
    
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]
        
        ball_size = ball_images[ball_img_idx].get_rect().size
        ball_width = ball_size[0]
        ball_height = ball_size[1]
        
        if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
            ball_val["to_x"] = ball_val["to_x"] * -1
        
        if ball_pos_y >= screen_height - stage_height - ball_height :
            ball_val["to_y"] = ball_val["init_spd_y"]
        else:
            ball_val["to_y"] += 0.5
    
        ball_val["pos_x"] += ball_val["to_x"]
        ball_val["pos_y"] += ball_val["to_y"]
    
    # 4. 충돌 처리
    
    # 캐릭터 정보 업데이트
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]

        ball_rect = ball_images[ball_img_idx].get_rect()
        ball_rect.left = ball_pos_x
        ball_rect.top = ball_pos_y
        
        if character_rect.colliderect(ball_rect):
            running = False
            break
        
        for weapon_idx, weapon_val in enumerate(weapons):
            weapon_pos_x = weapon_val[0]
            weapon_pos_y = weapon_val[1]
            
            weapon_rect = weapon.get_rect()
            weapon_rect.left = weapon_pos_x
            weapon_rect.top = weapon_pos_y
            
            if weapon_rect.colliderect(ball_rect):

                weapon_to_remove = weapon_idx
                ball_to_remove = ball_idx
                
                # 가장 작은 크기의 공이 아니라면 다음 단계의 공으로 나눠주기
                if ball_img_idx < 3:
                    # 현재 공 크기 정보를 가지고 옴
                    ball_width = ball_rect[0]
                    ball_height = ball_rect[1]
                    
                    # 나눠진 공 정보
                    small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                    small_ball_width = small_ball_rect.size[0]
                    small_ball_height = small_ball_rect.size[1]
                    
                    # 왼쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : -3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]  
                    })
                    
                    # 오른쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : 3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                    })
                break
    
    if weapon_to_remove > -1 :
        del weapons[weapon_to_remove]
        weapon_to_remove = -1
    if ball_to_remove > -1 :
        del balls[ball_to_remove]
        ball_to_remove = -1

	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
    
    for idx, val in enumerate(balls):
        ball_pos_x = val["pos_x"]
        ball_pos_y = val["pos_y"]
        ball_img_idx = val["img_idx"]
        screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos, character_y_pos))
        
    pygame.display.update()
    
pygame.quit()

[20] 게임 오버

# 1. 모든 공을 없애면 게임 종료 (성공)
# 2. 캐릭터는 공에 닿으면 게임 종료 (실패)
# 3. 시간 제한 99초 초과 시 게임 종료 (실패)
    
import pygame
import os

#############################################################

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "images")

background = pygame.image.load(os.path.join(image_path, "background.png"))

stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1]

character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

weapons = []

weapon_speed = 10

ball_images =[
    pygame.image.load(os.path.join(image_path, "balloon1.png")),
    pygame.image.load(os.path.join(image_path, "balloon2.png")),
    pygame.image.load(os.path.join(image_path, "balloon3.png")),
    pygame.image.load(os.path.join(image_path, "balloon4.png"))
]

ball_speed_y = [-18, -15, -12, -9]

balls = []

balls.append({
    "pos_x" : 50,
    "pos_y" : 50,
    "img_idx" : 0,
    "to_x" : 3,
    "to_y" : -6,
    "init_spd_y" : ball_speed_y[0]
})

weapon_to_remove = -1
ball_to_remove = -1

# Font 정의
game_font = pygame.font.Font(None, 40)
total_time = 100
start_ticks = pygame.time.get_ticks() # 시작 시간 정의

# 게임 종료 메시지
# TimeOut (시간초과, 실패)
# Mission Complete (성공)
# Game Over (캐릭터 공에 맞음, 실페)
game_result = "Game Over"

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE:
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    weapons = [ [w[0], w[1] - weapon_speed] for w in weapons ]
    
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]
        
        ball_size = ball_images[ball_img_idx].get_rect().size
        ball_width = ball_size[0]
        ball_height = ball_size[1]
        
        if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
            ball_val["to_x"] = ball_val["to_x"] * -1

        if ball_pos_y >= screen_height - stage_height - ball_height :
            ball_val["to_y"] = ball_val["init_spd_y"]
        else:
            ball_val["to_y"] += 0.5
    
        ball_val["pos_x"] += ball_val["to_x"]
        ball_val["pos_y"] += ball_val["to_y"]
    
    # 4. 충돌 처리
    
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]

        ball_rect = ball_images[ball_img_idx].get_rect()
        ball_rect.left = ball_pos_x
        ball_rect.top = ball_pos_y
        
        # 공과 캐릭터 충돌 처리
        # game_result는 처음 할당되는 것이 "Game Over"이기 때문에 별도로 바꿔줄 필요 없음
        if character_rect.colliderect(ball_rect):
            running = False
            break
        
        for weapon_idx, weapon_val in enumerate(weapons):
            weapon_pos_x = weapon_val[0]
            weapon_pos_y = weapon_val[1]
            
            weapon_rect = weapon.get_rect()
            weapon_rect.left = weapon_pos_x
            weapon_rect.top = weapon_pos_y
            
            if weapon_rect.colliderect(ball_rect):

                weapon_to_remove = weapon_idx
                ball_to_remove = ball_idx
                
                if ball_img_idx < 3:
                
                    ball_width = ball_rect[0]
                    ball_height = ball_rect[1]
                    
                    small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                    small_ball_width = small_ball_rect.size[0]
                    small_ball_height = small_ball_rect.size[1]
                    
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : -3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]  
                    })
                    
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : 3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                    })
                break
    
    if weapon_to_remove > -1 :
        del weapons[weapon_to_remove]
        weapon_to_remove = -1
        
    if ball_to_remove > -1 :
        del balls[ball_to_remove]
        ball_to_remove = -1
    
    # 모든 공을 없앤 경우 게임 종료 (성공)
    if len(balls) == 0 :
        game_result = "Mission Complete"
        running = False

	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
    
    for idx, val in enumerate(balls):
        ball_pos_x = val["pos_x"]
        ball_pos_y = val["pos_y"]
        ball_img_idx = val["img_idx"]
        screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos, character_y_pos))
    
    # 경과 시간 계산
    elapsed_time = (pygame.time.get_ticks() - start_ticks) / 1000 # ms -> s
    timer = game_font.render("Time : {}".format(int(total_time - elapsed_time)), True, (255, 255, 255))
    screen.blit(timer, (10, 10))
    
    # 시간 초과했다면
    if total_time - elapsed_time <= 0 :
        game_result = "Time Out"
        running = False
    
    pygame.display.update()
    
    # 게임 오버 메시지
    msg = game_font.render(game_result, True, (255, 255, 0)) # 노란색
    msg_rect = msg.get_rect(center=(int(screen_width/2), int(screen_height)))
    screen.blit(msg, msg_rect)
    pygame.display.update() # 한번 더 필요
    
    # 2초 대기
    pygame.time.delay(2000) # 게임 오버 메시지 출력 후 바로 pygame.quit()되면 안되니까
    
pygame.quit()

[21] 버그 수정

 

! Problem & Solution

# 이중 for문을 탈출하는 법

#예시

balls = [1, 2, 3, 4]
weapons = [11, 22, 3, 44]

for ball_idx, ball_val in enumerate(balls):
    print("ball :", ball_val)
    for weapon_idx, weapon_val in enumerate(weapons):
        print("weapons :", weapon_val)
        if ball_val == weapon_val:
            print("공과 무기가 충돌")
            break
    else:
        continue
    print("바깥 for 문 break")
    break
    
    # if 조건 :
    # 	동작
    # else :
	#	그 이외의 동작
    
'''
for 바깥 조건:
	바깥동작
	for 안쪽조건:
    	안쪽동작
        if 충돌하면:
        	break
    else:
    	continue
    break
'''

| Code

# ~~

    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]

        # 공 rect 정보 업데이트
        ball_rect = ball_images[ball_img_idx].get_rect()
        ball_rect.left = ball_pos_x
        ball_rect.top = ball_pos_y
        
        # 공과 캐릭터 충돌 처리
        # game_result는 처음 할당되는 것이 "Game Over"이기 때문에 별도로 바꿔줄 필요 없음
        if character_rect.colliderect(ball_rect):
            running = False
            break
        
        for weapon_idx, weapon_val in enumerate(weapons):
            weapon_pos_x = weapon_val[0]
            weapon_pos_y = weapon_val[1]
            
            # 무기 rect 정보 업데이트
            weapon_rect = weapon.get_rect()
            weapon_rect.left = weapon_pos_x
            weapon_rect.top = weapon_pos_y
            
            # 충돌 체크
            if weapon_rect.colliderect(ball_rect):

                weapon_to_remove = weapon_idx
                ball_to_remove = ball_idx
                
                # 가장 작은 크기의 공이 아니라면 다음 단계의 공으로 나눠주기
                if ball_img_idx < 3:
                    # 현재 공 크기 정보를 가지고 옴
                    ball_width = ball_rect[0]
                    ball_height = ball_rect[1]
                    
                    # 나눠진 공 정보
                    small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                    small_ball_width = small_ball_rect.size[0]
                    small_ball_height = small_ball_rect.size[1]
                    
                    # 왼쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : -3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]  
                    })
                    
                    # 오른쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : 3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                    })
                break
        else : # 계속 게임을 진행
            continue # 안쪽 for문 조건이 맞지 않으면 continue, 바깥 for 문 계속 수행
        break # 안쪽 for 문에서 break를 만나면 여기로 진입 가능, 2중 for 문을 한번에 탈출

'''
for 바깥 조건:
	바깥동작
	for 안쪽조건:
    	안쪽동작
        if 충돌하면:
        	break
    else:
    	continue
    break
'''

# ~~

[Whole]

# 1. 모든 공을 없애면 게임 종료 (성공)
# 2. 캐릭터는 공에 닿으면 게임 종료 (실패)
# 3. 시간 제한 99초 초과 시 게임 종료 (실패)
    
import pygame
import os # os 모듈 import

#############################################################

pygame.init()

screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Hero Pang")

clock = pygame.time.Clock()

#############################################################

# 1. 사용자 게임 초기화 (배경 화면, 게임 이미지, 좌표, 속도, 폰트 등)

current_path = os.path.dirname(__file__) # 현재 파일의 위치 변환
image_path = os.path.join(current_path, "images") # images 폴더 위치 반환
# 배경 만들기
background = pygame.image.load(os.path.join(image_path, "background.png"))
# 스테이지 만들기
stage = pygame.image.load(os.path.join(image_path, "stage.png"))
stage_size = stage.get_rect().size
stage_height = stage_size[1] # 스테이지 높이 위에 캐릭터를 두기 위해 사용
# 캐릭터 만들기
character = pygame.image.load(os.path.join(image_path, "character.png"))
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = ( screen_width / 2 ) - ( character_width / 2 )
character_y_pos = screen_height - character_height - stage_height

character_to_x = 0

character_speed = 5

# 무기 만들기
weapon = pygame.image.load(os.path.join(image_path, "weapon.png"))
weapon_size = weapon.get_rect().size
weapon_width = weapon_size[0]

# 무기는 한 번에 여러 발 발사 가능
weapons = []

# 무기 이동 속도
weapon_speed = 10 


# 공 만들기 (4개 크기에 대해 따로 처리)
ball_images =[
    pygame.image.load(os.path.join(image_path, "balloon1.png")),
    pygame.image.load(os.path.join(image_path, "balloon2.png")),
    pygame.image.load(os.path.join(image_path, "balloon3.png")),
    pygame.image.load(os.path.join(image_path, "balloon4.png"))
]

# 공 크기에 따른 최초 스피드
ball_speed_y = [-18, -15, -12, -9] # index 0, 1, 2, 3에 해당하는 값

# 공들
balls = []

# 최초 발생하는 큰 공 추가
balls.append({
    "pos_x" : 50, # 공의 X좌표
    "pos_y" : 50, # 공의 Y좌표
    "img_idx" : 0, # 공의 이미지 인덱스
    "to_x" : 3, # x축 이동방향, -3이면 왼쪽으로, 3이면 오른쪽으로
    "to_y" : -6, # y축 이동방향
    "init_spd_y" : ball_speed_y[0] # y 최초 속도
})

# 사라질 무기, 공 정보 저장 변수
weapon_to_remove = -1
ball_to_remove = -1

# Font 정의
game_font = pygame.font.Font(None, 40)
total_time = 100
start_ticks = pygame.time.get_ticks() # 시작 시간 정의

# 게임 종료 메시지
# TimeOut(시간초과, 실패)
# Mission Complete(성공)
# Game Over (캐릭터 공에 맞음, 실페)
game_result = "Game Over"

running = True
while running:
    dt = clock.tick(60)
    
    # 2. 이벤트 처리 (키보드, 마우스 등)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT: # 캐릭터를 왼쪽으로
                character_to_x -= character_speed
            elif event.key == pygame.K_RIGHT: # 캐릭터를 오른쪽으로
                character_to_x += character_speed
            elif event.key == pygame.K_SPACE: # 무기 발사
                weapon_x_pos = character_x_pos + ( character_width / 2 ) - ( weapon_width / 2 )
                weapon_y_pos = character_y_pos
                weapons.append([weapon_x_pos, weapon_y_pos])
        
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                character_to_x = 0
                
    # 3. 게임 캐릭터 위치 정의
    
    character_x_pos += character_to_x
  
    if character_x_pos < 0 :
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width :
        character_x_pos = screen_width - character_width
    
    # 무기 위치 조정 ( 한줄 for 활용 )
    weapons = [ [w[0], w[1] - weapon_speed] for w in weapons ]
    	# 무기 위치를 위로
    	# 100, 200 -> 180, 160, 140, ...
        # 500, 200 -> 180, 160, 140, ...
        # 무기의 x좌표 값은 변함이 없지만, 무기의 y좌표 값은 변한다 ( 무기를 쏘고나면 줄어드니까 )
    
    # 천장에 닿은 무기 없애기
    weapons = [ [w[0], w[1]] for w in weapons if w[1] > 0 ]
    
    # 공 위치 정의
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]
        
        ball_size = ball_images[ball_img_idx].get_rect().size
        ball_width = ball_size[0]
        ball_height = ball_size[1]
        
        
    	# 가로벽에 닿았을 때 공 이동 위치 변경 (튕겨 나오는 효과)
        if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
            ball_val["to_x"] = ball_val["to_x"] * -1
        
        # 세로 위치
        # 스테이지에 튕겨서 올라가는 처리
        if ball_pos_y >= screen_height - stage_height - ball_height :
            ball_val["to_y"] = ball_val["init_spd_y"]
        else: # 그 외의 모든 경우에는 속도를 증가 (속도 줄여나감/마이너스로 증가)
            ball_val["to_y"] += 0.5
    
        ball_val["pos_x"] += ball_val["to_x"]
        ball_val["pos_y"] += ball_val["to_y"]
    
    # 4. 충돌 처리
    
    # 캐릭터 정보 업데이트
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    for ball_idx, ball_val in enumerate(balls):
        ball_pos_x = ball_val["pos_x"]
        ball_pos_y = ball_val["pos_y"]
        ball_img_idx = ball_val["img_idx"]

        # 공 rect 정보 업데이트
        ball_rect = ball_images[ball_img_idx].get_rect()
        ball_rect.left = ball_pos_x
        ball_rect.top = ball_pos_y
        
        # 공과 캐릭터 충돌 처리
        # game_result는 처음 할당되는 것이 "Game Over"이기 때문에 별도로 바꿔줄 필요 없음
        if character_rect.colliderect(ball_rect):
            running = False
            break
        
        for weapon_idx, weapon_val in enumerate(weapons):
            weapon_pos_x = weapon_val[0]
            weapon_pos_y = weapon_val[1]
            
            # 무기 rect 정보 업데이트
            weapon_rect = weapon.get_rect()
            weapon_rect.left = weapon_pos_x
            weapon_rect.top = weapon_pos_y
            
            # 충돌 체크
            if weapon_rect.colliderect(ball_rect):

                weapon_to_remove = weapon_idx
                ball_to_remove = ball_idx
                
                # 가장 작은 크기의 공이 아니라면 다음 단계의 공으로 나눠주기
                if ball_img_idx < 3:
                    # 현재 공 크기 정보를 가지고 옴
                    ball_width = ball_rect[0]
                    ball_height = ball_rect[1]
                    
                    # 나눠진 공 정보
                    small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                    small_ball_width = small_ball_rect.size[0]
                    small_ball_height = small_ball_rect.size[1]
                    
                    # 왼쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : -3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]  
                    })
                    
                    # 오른쪽으로 튕겨나가는 작은 공
                    balls.append({
                        "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2),
                        "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                        "img_idx" : ball_img_idx - 1,
                        "to_x" : 3,
                        "to_y" : -6,
                        "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                    })
                break
        else : # 계속 게임을 진행
            continue # 안쪽 for문 조건이 맞지 않으면 continue, 바깥 for 문 계속 수행
        break # 안쪽 for 문에서 break를 만나면 여기로 진입 가능, 2중 for 문을 한번에 탈출

'''
for 바깥 조건:
	바깥동작
	for 안쪽조건:
    	안쪽동작
        if 충돌하면:
        	break
    else:
    	continue
    break
'''
    
    # 충돌된 공 or 무기 없애기
    if weapon_to_remove > -1 :
        del weapons[weapon_to_remove]
        weapon_to_remove = -1
        
    if ball_to_remove > -1 :
        del balls[ball_to_remove]
        ball_to_remove = -1
    
    # 모든 공을 없앤 경우 게임 종료 (성공)
    if len(balls) == 0 :
        game_result = "Mission Complete"
        running = False

	# 5. 화면에 그리기
    screen.blit(background, (0,0))
    
    # 순서대로 그리기 때문에 이렇게 위치를 조정해야 무기가 스테이지, 캐릭터 밑에 그려짐 ( 레이어 상에서 우선 )
    for weapon_x_pos, weapon_y_pos in weapons :
        screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
    
    for idx, val in enumerate(balls):
        ball_pos_x = val["pos_x"]
        ball_pos_y = val["pos_y"]
        ball_img_idx = val["img_idx"]
        screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
        
    screen.blit(stage, (0,screen_height - stage_height))
    screen.blit(character, (character_x_pos, character_y_pos))
    
    # 경과 시간 계산
    elapsed_time = (pygame.time.get_ticks() - start_ticks) / 1000 # ms -> s
    timer = game_font.render("Time : {}".format(int(total_time - elapsed_time)), True, (255, 255, 255))
    screen.blit(timer, (10, 10))
    
    # 시간 초과했다면
    if total_time - elapsed_time <= 0 :
        game_result = "Time Out"
        running = False
    
    pygame.display.update()
    
    # 게임 오버 메시지
    msg = game_font.render(game_result, True, (255, 255, 0)) # 노란색
    msg_rect = msg.get_rect(center=(int(screen_width/2), int(screen_height)))
    screen.blit(msg, msg_rect)
    pygame.display.update()
    
    # 2초 대기
    pygame.time.delay(2000) # 게임 오버 메시지 출력 후 바로 pygame.quit()되면 안되니까
    
pygame.quit()

마무리하며

[나도코딩 활용편1 - 파이게임]를 들으면서

Pygame 라이브러리를 사용해보고, 간단한 게임들을 만들어보았다.

파이썬 기본 강의를 들을 때는 파이썬이 어떻게 쓰일 수 있을지 감이 안 와서

공부를 하는 느낌으로 들었다면 파이게임으로 게임을 만들어보면서

내가 프로그래밍한 것으로 결과물을 만들어 볼 수 있어서 좋은 경험이었다.

개발환경이 프로그램 설치가 안되서 구름IDE를 이용해서 사용해보았는데

pygame 템플릿이 있다보니 (공 쪼개기 전)까지는 문제 없이 게임을 실행해볼 수 있어서 좋았다.

공 튀기기부터 이후까지는 이해가 안되는 부분이 조금 있어서 다시 복습을 해볼 예정이고

부분적으로 이해가 안되는 부분을 한번 더 듣고, 전체적인 코드를 다시 보면서 흐름을 파악하는 것도 해보려고 한다.

유익-띠


 

Reference :

파이썬 코딩 무료 강의 (활용편1) - 추억의 오락실 게임을 만들어 보아요

https://www.youtube.com/watch?v=Dkx8Pl6QKW0 

https://nadocoding.tistory.com/8#google_vignette