[๐Ÿ•น๏ธPython for Game Programming] ๊ทธ๋ž˜ํ”ฝ์„ ์ด์šฉํ•œ ํŒŒ์ด์ฌ ๊ฒŒ์ž„ ๋งŒ๋“ค๊ธฐ

์Œ์•…๋‹ค๋žŒ์ฅยท2025๋…„ 2์›” 11์ผ
0

โŒจ๏ธ: 2025๋…„ 2์›” 10์ผ โ†’ 2025๋…„ 2์›” 11์ผ

โœ๏ธ : 2025๋…„ 2์›” 11์ผ

Pygame

  • Python์œผ๋กœ 2D ๊ฒŒ์ž„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์‚ฌ์šฉ
  • ๋„ํ˜•, ์ด๋ฏธ์ง€, ๊ทธ๋ž˜ํ”ฝ, ์‚ฌ์šด๋“œ, ์ถฉ๋Œ ์ฒ˜๋ฆฌ ๋“ฑ์˜ ๊ธฐ๋Šฅ ์ œ๊ณต

๐Ÿ•น๏ธ Pygame ์ฃผ์š” ๊ธฐ๋Šฅ ์ •๋ฆฌ

1๏ธโƒฃ ํ™”๋ฉด ์ƒ์„ฑ

screen = pygame.display.set_mode((๊ฐ€๋กœ, ์„ธ๋กœ))
  • ๊ฒŒ์ž„ ์ฐฝ์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜

2๏ธโƒฃ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ฐฝ์„ ๋‹ซ๋Š” ๋“ฑ์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐ˜์‘

3๏ธโƒฃ ์ƒ‰์ƒ ์ •์˜

WHITE = (255, 255, 255)  # RGB ๊ฐ’
  • ์ƒ‰์ƒ์€ (R, G, B) ํŠœํ”Œ๋กœ ํ‘œํ˜„

4๏ธโƒฃ ํ™”๋ฉด ์ฑ„์šฐ๊ธฐ

screen.fill(WHITE)
  • ๋ฐฐ๊ฒฝ ์ƒ‰์„ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ

5๏ธโƒฃ ํ™”๋ฉด ์—…๋ฐ์ดํŠธ

pygame.display.update()
  • ํ™”๋ฉด์„ ์ƒˆ๋กœ๊ณ ์นจํ•ด์„œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ฐ˜์˜

๐Ÿ”น ์ถ”๊ฐ€ ๊ธฐ๋Šฅ

๐Ÿƒโ€โ™‚๏ธ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ๋ฐ›๊ธฐ

for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:  # ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ
        if event.key == pygame.K_LEFT:
            print("์™ผ์ชฝ ํ™”์‚ดํ‘œ ํ‚ค ๋ˆŒ๋ฆผ")
  • KEYDOWN โ†’ ํ‚ค๊ฐ€ ๋ˆŒ๋ ธ์„ ๋•Œ
  • KEYUP โ†’ ํ‚ค์—์„œ ์†์„ ๋—„ ๋•Œ

๐Ÿ–ฑ๏ธ ๋งˆ์šฐ์Šค ์ž…๋ ฅ ๋ฐ›๊ธฐ

for event in pygame.event.get():
    if event.type == pygame.MOUSEBUTTONDOWN:
        print("๋งˆ์šฐ์Šค ํด๋ฆญ๋จ!", event.pos)  # ํด๋ฆญ ์œ„์น˜ ์ถœ๋ ฅ

๐ŸŽจ ๋„ํ˜• ๊ทธ๋ฆฌ๊ธฐ

pygame.draw.rect(screen, (255, 0, 0), (50, 50, 100, 100))  # ๋นจ๊ฐ„์ƒ‰ ์‚ฌ๊ฐํ˜•
pygame.draw.circle(screen, (0, 0, 255), (250, 200), 50)  # ํŒŒ๋ž€์ƒ‰ ์›
  • draw.rect(ํ™”๋ฉด, ์ƒ‰์ƒ, (x, y, ๋„ˆ๋น„, ๋†’์ด))
  • draw.circle(ํ™”๋ฉด, ์ƒ‰์ƒ, (x, y), ๋ฐ˜์ง€๋ฆ„)

๐ŸŽญ ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

image = pygame.image.load("character.png")
screen.blit(image, (100, 100))  # (100, 100) ์œ„์น˜์— ์ด๋ฏธ์ง€ ์ถœ๋ ฅ

๐Ÿ”Š ์‚ฌ์šด๋“œ ์žฌ์ƒ

sound = pygame.mixer.Sound("jump.wav")
sound.play()  # ์‚ฌ์šด๋“œ ์žฌ์ƒ

๐Ÿ“š Pygame Library

๐Ÿ”น ์ฃผ์š” ์ด๋ฒคํŠธ ํƒ€์ž… ์ƒ์ˆ˜๋“ค

pygame.event ๋ชจ๋“ˆ์—์„œ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ด๋ฒคํŠธ ํƒ€์ž… ์ƒ์ˆ˜๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ƒ์ˆ˜๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. pygame.QUIT

    • ์œˆ๋„์šฐ ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ. ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์ž„ ์ฐฝ์˜ "X" ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ๋ฐœ์ƒ.
    
    if event.type == pygame.QUIT:
        running = False
    
  2. pygame.KEYDOWN / pygame.KEYUP

    • ํ‚ค๋ณด๋“œ ํ‚ค๊ฐ€ ๋ˆŒ๋ ธ์„ ๋•Œ(KEYDOWN)์™€ ๋–ผ์—ˆ์„ ๋•Œ(KEYUP) ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ.
    
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            print("์™ผ์ชฝ ํ™”์‚ดํ‘œ ํ‚ค ๋ˆŒ๋ฆผ")
    
  3. pygame.MOUSEBUTTONDOWN / pygame.MOUSEBUTTONUP

    • ๋งˆ์šฐ์Šค ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ(MOUSEBUTTONDOWN)์™€ ๋–ผ์—ˆ์„ ๋•Œ(MOUSEBUTTONUP) ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ.
    
    if event.type == pygame.MOUSEBUTTONDOWN:
        print("๋งˆ์šฐ์Šค ๋ฒ„ํŠผ ํด๋ฆญ๋จ", event.pos)  # ํด๋ฆญ๋œ ์œ„์น˜
    
  4. pygame.MOUSEMOTION

    • ๋งˆ์šฐ์Šค๊ฐ€ ์›€์ง์ผ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ.
    
    if event.type == pygame.MOUSEMOTION:
        print("๋งˆ์šฐ์Šค ์œ„์น˜:", event.pos)
    
  5. pygame.ACTIVEEVENT

    • ์œˆ๋„์šฐ๊ฐ€ ํ™œ์„ฑํ™”๋˜์—ˆ์„ ๋•Œ ๋˜๋Š” ๋น„ํ™œ์„ฑํ™”๋  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ.
    
    if event.type == pygame.ACTIVEEVENT:
        if event.state == pygame.APPINPUTFOCUS:
            print("์•ฑ ํ™œ์„ฑํ™”๋จ")
        elif event.state == pygame.APPINPUTFOCUSLOSS:
            print("์•ฑ ๋น„ํ™œ์„ฑํ™”๋จ")
    
  6. pygame.VIDEORESIZE

    • ์œˆ๋„์šฐ ํฌ๊ธฐ ์กฐ์ ˆ ์ด๋ฒคํŠธ.
    
    if event.type == pygame.VIDEORESIZE:
        screen = pygame.display.set_mode(event.size, pygame.RESIZABLE)
    
  7. pygame.USEREVENT

    • ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ๋กœ, pygame.event.post()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    
    pygame.event.post(pygame.event.Event(pygame.USEREVENT, {"data": "example"}))
    

โŒจ๏ธ๊ฒŒ์ž„ ๊ตฌํ˜„ํ•˜๊ธฐ

1. ๐ŸŒ‰ ์ดˆ๊ธฐํ™”๋ถ€ํ„ฐ ๋ฐฐ๊ฒฝ ์„ค์ •๊นŒ์ง€

- ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ , ๊ฒŒ์ž„ ์ƒ‰์ƒ ์ •์˜: RGB Tuple

import pygame
import sys
from pygame.locals import * #pygame ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์•ˆ ๋ชจ๋“  ์ง€์—ญ ๋ณ€์ˆ˜ ํ˜ธ์ถœ

BLACK  = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)

- ๊ฒŒ์ž„ ์‹œ์ž‘, ํŒŒ์ด๊ฒŒ์ž„ ์ดˆ๊ธฐํ™”: init()

pygame.init()

- FPS ์„ค์ •: pygame.time.Clock().tick(์ˆซ์ž)

clock = pygame.time.Clock()
clock.tick(60)
  • tick()์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด CPU ์‚ฌ์šฉ๋Ÿ‰์ด ๊ณผ๋„ํ•˜๊ฒŒ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

- ์ œ๋ชฉ ํ‘œ์‹œ์ค„ ์„ค์ •: pygame.display.set_caption("์ œ๋ชฉํ‘œ์‹œ์ค„๋ช…")

pygame.display.set_caption("Crazy Driver")
  • display ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: ํ™”๋ฉด ํ‘œ์‹œ ๊ด€๋ฆฌ

- ๊ฒŒ์ž„ ํ™”๋ฉด ์ดˆ๊ธฐํ™”: pygame.display.set_mode(( , ))

screen = pygame.display.set_mode((500,800))

- ํ™”๋ฉด ์ถœ๋ ฅ: screen.fill(WHITE)

screen.fill(WHITE)

- ํ™”๋ฉด ์—…๋ฐ์ดํŠธ: pygame.display.update()

pygame.display.update()

- ๋ฉ”์ธ ๊ฒŒ์ž„ ๋ฃจํ”„: While True ํ™œ์šฉ

#๋ฉ”์ธ ๊ฒŒ์ž„ ๋ฃจํ”„
while True:
    #๋ฐฐ๊ฒฝ ๋‘๊ธฐ
    screen.blit(IMG_ROAD,(0,0))
    
    #ํ”Œ๋ ˆ์ด์–ด ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(player.image, player.rect)
    
    #์  ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(enemy.image, enemy.rect)
    #์ด๋ฒคํŠธ ํ™•์ธํ•˜๊ธฐ
    for event in pygame.event.get():
        #ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๊ฒŒ์ž„์„ ๊ทธ๋งŒ๋‘๋Š”์ง€?
        if event.type == QUIT:#pygame.QUIT
            #๊ฒŒ์ž„ ๋๋‚ด๊ธฐ
            pygame.quit()
            sys.exit()
    #ํ™”๋ฉด ์—…๋ฐ์ดํŠธํ•˜๊ธฐ
    pygame.display.update()

- ๊ฒŒ์ž„ ๊ฒฝ๋กœ ์„ค์ •, ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ: os.path.dirname(**file**)ํ™œ์šฉ

import os
GAME_ROOT_FOLDER = os.path.dirname(__file__) #๊ฒŒ์ž„๋ฃจํŠธ
IMAGE_FOLDER = os.path.join(GAME_ROOT_FOLDER,"Images") 
#๊ฒŒ์ž„๋ฃจํŠธ์— Images ์ถ”๊ฐ€ํ•ด์„œ ์ด๋ฏธ์ง€ ๋ฃจํŠธ ์ €์žฅ
  • ๊ฒŒ์ž„๋ฃจํŠธ์— Images joinํ•ด์„œ ์ด๋ฏธ์ง€ ๋ฃจํŠธ ์ €์žฅ

- ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ: pygame.image.load(์ด๋ฏธ์ง€๋ช…)

IMG_ROAD = pygame.image.load(os.path.join(IMAGE_FOLDER,"Road.png")
  • ์ด๋ฏธ์ง€ ๋ฃจํŠธ์— png๋ช… joinํ•ด์„œ ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋‚ด ํ•ด๋‹น ์ด๋ฏธ์ง€ ํ˜ธ์ถœ

- ๋ณต์‚ฌํ•  ์ด๋ฏธ์ง€์™€ ๋ณต์‚ฌํ•  ๊ณณ x,y์ขŒํ‘œ ๋ฐ›๊ธฐ: blit(๋ณต์‚ฌํ• ๊ณณ์ด๋ฆ„,(x,y))

screen.blit(IMG_ROAD, (0,0))

2. ๐Ÿš— ์ž๋™์ฐจ ํ‘œ์‹œํ•˜๊ธฐ

**Sprite

  • ํฐ ์ด๋ฏธ์ง€ ์œ„์— ๋†“์ธ 2์ฐจ์› ์ด๋ฏธ์ง€ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„ ํ™”๋ฉด์—์„œ ์›€์ง์ž„ ๋“ฑ์„ ํ‘œํ˜„ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

- ํ”Œ๋ ˆ์ด์–ด ์ดˆ๊ธฐ ์œ„์น˜ ๊ณ„์‚ฐํ•˜๊ธฐ

h = IMG_ROAD.get_width()//2
v = IMG_ROAD.get_height() - (IMG_PLAYER.get_height()//2)

์•„๋ž˜์ชฝ ๊ฐ€์šด๋ฐ์— ํ”Œ๋ ˆ์ด์–ด ์ž๋™์ฐจ๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ€๋กœ ์œ„์น˜๋Š” ๊ฐ€๋กœ ๋„๋กœ ๊ธธ์ด์˜ ์ ˆ๋ฐ˜
  • ๋„๋กœ ๋†’์ด๋ฅผ ์„ธ๋กœ ์œ„์น˜๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํ™”๋ฉด์˜ ๊ฐ€์žฅ ์•„๋ž˜์— ์ค‘์‹ฌ์ด ์˜ค๋ฏ€๋กœ ์ž๋™์ฐจ์˜ ์ ˆ๋ฐ˜๋งŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์„ธ๋กœ ์œ„์น˜๋Š” (๋„๋กœ ๋†’์ด - ํ”Œ๋ ˆ์ด์–ด ์ž๋™์ฐจ ๋†’์ด์˜ ์ ˆ๋ฐ˜) ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

- ํ”Œ๋ ˆ์ด์–ด ์Šคํ”„๋ผ์ดํŠธ ๋งŒ๋“ค๊ธฐ

player = pygame.sprite.Sprite()
player.image = IMG_PLAYER
player.surf = pygame.Surface(IMG_PLAYER.get_size())
player.rect = player.surf.get_rect(center = (h,v)) 
#์Šคํ”„๋ผ์ดํŠธ๋ฅผ ๋‹ด์„ ์ง์‚ฌ๊ฐํ˜• ์ •์˜

- ์  ์Šคํ”„๋ผ์ดํŠธ ๋งŒ๋“ค๊ธฐ

# ์ 
# ์  ์ดˆ๊ธฐ ์œ„์น˜ ๊ณ„์‚ฐํ•˜๊ธฐ
hl = IMG_ENEMY.get_width()//2 #๊ฐ€์žฅ์™ผ์ชฝ
hr = IMG_ROAD.get_width() - (IMG_ENEMY.get_width()//2) #๊ฐ€์žฅ์˜ค๋ฅธ์ชฝ
h = random.randrange(hl, hr) #๋žœ๋ค
v = 0 #์„ธ๋กœ
# enemy ์Šคํ”„๋ผ์ดํŠธ ๋งŒ๋“ค๊ธฐ
enemy = pygame.sprite.Sprite()
enemy.image = IMG_ENEMY
enemy.surf = pygame.Surface(IMG_ENEMY.get_size())
enemy.rect = enemy.surf.get_rect(center = (h, v))
  • hl = IMG_ENEMY.get_width()//2 #๊ฐ€์žฅ์™ผ์ชฝ hr = IMG_ROAD.get_width() - (IMG_ENEMY.get_width()//2) #๊ฐ€์žฅ์˜ค๋ฅธ์ชฝ h = random.randrange(hl, hr) #๋žœ๋ค

cf. Surface() vs get_rect()

์†์„ฑ์„ค๋ช…์šฉ๋„์ฃผ์š” ํŠน์ง•
surfSurface ๊ฐ์ฒด๋กœ, ๊ฒŒ์ž„ ๊ฐ์ฒด์˜ ์ด๋ฏธ์ง€๋‚˜ ๋„ํ˜•์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.์Šคํ”„๋ผ์ดํŠธ์˜ ๋น„์ฃผ์–ผ์„ ์ •์˜ํ•˜๊ณ  ํ™”๋ฉด์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.- ์‹ค์ œ ๊ฒŒ์ž„ ํ™”๋ฉด์— ๊ทธ๋ ค์งˆ ์ด๋ฏธ์ง€๋‚˜ ๋„ํ˜•์„ ๋‹ด๊ณ  ์žˆ์Œ.
- surf๋Š” ์Šคํ”„๋ผ์ดํŠธ์˜ ๋‚ด์šฉ์„ ๋‹ด๋‹น.
rect์‚ฌ๊ฐํ˜• ์˜์—ญ์„ ๋‚˜ํƒ€๋‚ด๋Š” pygame.Rect ๊ฐ์ฒด๋กœ, ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.์Šคํ”„๋ผ์ดํŠธ์˜ ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์ถฉ๋Œ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.- ์Šคํ”„๋ผ์ดํŠธ์˜ ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ์ •์˜.
- ์ถฉ๋Œ ๊ฐ์ง€๋‚˜ ์Šคํ”„๋ผ์ดํŠธ ๋ฐฐ์น˜๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋จ

- ๋ฉ”์ธ ๊ฒŒ์ž„ ๋ฃจํ”„ ์ˆ˜์ •: screen.blit(player.image, player.rect)

#๋ฉ”์ธ ๊ฒŒ์ž„ ๋ฃจํ”„
while True:
    #๋ฐฐ๊ฒฝ ๋‘๊ธฐ
    screen.blit(IMG_ROAD,(0,0))
    
    #ํ”Œ๋ ˆ์ด์–ด ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(player.image, player.rect)
    
    #์  ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(enemy.image, enemy.rect)
    #์ด๋ฒคํŠธ ํ™•์ธํ•˜๊ธฐ
    for event in pygame.event.get():
        #ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๊ฒŒ์ž„์„ ๊ทธ๋งŒ๋‘๋Š”์ง€?
        if event.type == QUIT:#pygame.QUIT
            #๊ฒŒ์ž„ ๋๋‚ด๊ธฐ
            pygame.quit()
            sys.exit()
    #ํ™”๋ฉด ์—…๋ฐ์ดํŠธํ•˜๊ธฐ
    pygame.display.update()

3. ๐Ÿš˜ ์  ์›€์ง์ด๊ธฐ

- ์Šคํ”ผ๋“œ ์ดˆ๊ธฐํ™”

#๊ฒŒ์ž„ ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”
moveSpeed =  5

- ์ ์„ ์•„๋ž˜์ชฝ์œผ๋กœ ์›€์ง์ด๊ธฐ

#์  ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(enemy.image, enemy.rect)
    
    #์ ์„ ์•„๋ž˜์ชฝ์œผ๋กœ ์›€์ง์ด๊ธฐ
    enemy.rect.move_ip(0, moveSpeed)
    
    #ํ™”๋ฉด ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ”๋Š”์ง€ ์ฒดํฌ, ๋‚˜๊ฐ”์œผ๋ฉด ์œ„์ชฝ ๋žœ๋ค์œผ๋กœ ๋˜๋Œ๋ฆผ
    if (enemy.rect.bottom) > IMG_ROAD.get_height():
        hl = IMG_ENEMY.get_width()//2
        hr = IMG_ROAD.get_width() - (IMG_ENEMY.get_width()//2)
        h = random.randrange(hl, hr)
        v = 0
        
        #ํ™”๋ฉด์— ๋‘๊ธฐ
        enemy.rect.center = (h,v)
    

4. ๐Ÿš– ํ”Œ๋ ˆ์ด์–ด ์›€์ง์ด๊ธฐ

- ํ‚ค๋ณด๋“œ ์ œ์–ด: keys[K_LEFT] keys[K_RIGHT]

#ํ”Œ๋ ˆ์ด์–ด ํ™”๋ฉด์— ๋‘๊ธฐ
    screen.blit(player.image, player.rect)
    #ํ‚ค๋ณด๋“œ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ
    keys = pygame.key.get_pressed()
    if keys[K_LEFT] and player.rect.left > 0:
        player.rect.move_ip(-moveSpeed, 0)
        if player.rect.left < 0:
            player.rect.left = 0
    if keys[K_RIGHT] and player.rect.right < IMG_ROAD.get_width():
        player.rect.move_ip(moveSpeed,0)
        if player.rect.right > IMG_ROAD.get_width():
            player.rect.right = IMG_ROAD.get_width()
  • cf. ip๋Š” in place์˜ ์•ฝ์ž์ž…๋‹ˆ๋‹ค.

5. โฉ ์ ์  ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ธฐ

- ์กฐ๊ฑด๋ฌธ ํ™œ์šฉํ•ด์„œ ์†๋„ ๋†’์ด๊ธฐ

moveSpeed = 5
maxSpeed = 12
#์†๋„ ์—…๋ฐ์ดํŠธ
        if score % 3 == 0 and moveSpeed <= maxSpeed:
             moveSpeed += 0.5
  • ์ง€๋‚˜๊ฐ„ ์ž๋™์ฐจ(์ )์˜ ์ˆ˜๋ฅผ score๋ผ๊ณ  ํ•  ๋•Œ, ์ž๋™์ฐจ(์ ) 3๊ฐœ ์ง€๋‚˜๊ฐˆ ๋•Œ ์†๋„๊ฐ€ 0.5์”ฉ ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค.

6. โœ‹๐Ÿป ๊ฒŒ์ž„ ์˜ค๋ฒ„

- ๊ฒŒ์ž„ ์˜ค๋ฒ„ ํ•จ์ˆ˜ ์ƒ์„ฑ

#ํฐํŠธ ์„ค์ •
textFonts = ['minecraftia']
textSize = 48

#๊ฒŒ์ž„์˜ค๋ฒ„ ํ•จ์ˆ˜
def GameOver():
    # ๊ฒŒ์ž„ ๋๋‚ด๊ธฐ ๋ฌธ์ž์—ด ๋งŒ๋“ค๊ธฐ
    fontGameOver = pygame.font.SysFont(textFonts, textSize)
    textGameOver = fontGameOver.render("Game Over!", True, RED)
    rectGameOver = textGameOver.get_rect()
    rectGameOver.center = (IMG_ROAD.get_width()//2,
                           IMG_ROAD.get_height()//2)
    # ๊ฒ€์€์ƒ‰ ๋ฐฐ๊ฒฝ์— ๊ฒŒ์ž„ ์˜ค๋ฒ„ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅํ•˜๊ธฐ
    screen.fill(BLACK)
    screen.blit(textGameOver, rectGameOver)
    # ์ถœ๋ ฅ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ
    pygame.display.update()
    # ๊ฐ์ฒด ์—†์• ๊ธฐ
    player.kill()
    enemy.kill()
    # ์ผ์‹œ ์ •์ง€ํ•˜๊ธฐ
    time.sleep(2)
    # ๊ฒŒ์ž„ ๋๋‚ด๊ธฐ 
    pygame.quit()
    sys.exit()

- ์ž๋™์ฐจ ์ถฉ๋Œ ์‹œ ๊ฒŒ์ž„ ์˜ค๋ฒ„

#์ถฉ๋Œ ํ™•์ธํ•˜๊ธฐ
    if pygame.sprite.collide_rect(player,enemy):
        GameOver()

โŒจ๏ธํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์‚ฌ์šฉํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ํ•จ์ˆ˜

1. pygame.init()

  • ์„ค๋ช…: Pygame์˜ ๋ชจ๋“  ๋ชจ๋“ˆ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๊ฒŒ์ž„์„ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋ฉฐ, Pygame์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

2. pygame.time.Clock()

  • ์„ค๋ช…: ๊ฒŒ์ž„์˜ ํ”„๋ ˆ์ž„ ์†๋„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์—ญํ• : clock.tick(60)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๋‹น 60ํ”„๋ ˆ์ž„์œผ๋กœ ์ œํ•œํ•˜๋Š” ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

3. pygame.display.set_caption("Crazy Driver")

  • ์„ค๋ช…: ๊ฒŒ์ž„ ์ฐฝ์˜ ์ œ๋ชฉ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์—ญํ• : ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•œ ๊ฒŒ์ž„ ์ฐฝ์˜ ์ƒ๋‹จ ๋ฐ”์— "Crazy Driver"๋ผ๋Š” ์ด๋ฆ„์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

4. pygame.image.load(os.path.join(IMAGE_FOLDER, "ํŒŒ์ผ๋ช…"))

  • ์„ค๋ช…: ์ง€์ •๋œ ๊ฒฝ๋กœ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
  • ์—ญํ• : ๊ฒŒ์ž„์—์„œ ์‚ฌ์šฉํ•  ๋ฐฐ๊ฒฝ, ํ”Œ๋ ˆ์ด์–ด, ์  ๋“ฑ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

5. pygame.display.set_mode(IMG_ROAD.get_size())

  • ์„ค๋ช…: ๊ฒŒ์ž„ ํ™”๋ฉด์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๊ฒŒ์ž„์˜ ์ฐฝ ํฌ๊ธฐ๋ฅผ IMG_ROAD ์ด๋ฏธ์ง€ ํฌ๊ธฐ์™€ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

6. pygame.sprite.Sprite()

  • ์„ค๋ช…: Pygame์˜ ์Šคํ”„๋ผ์ดํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๊ฒŒ์ž„์—์„œ ํ”Œ๋ ˆ์ด์–ด๋‚˜ ์ ๊ณผ ๊ฐ™์€ ๊ฐœ์ฒด๋ฅผ ์Šคํ”„๋ผ์ดํŠธ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

7. pygame.Surface(IMG_PLAYER.get_size())

  • ์„ค๋ช…: ์ง€์ •๋œ ํฌ๊ธฐ์˜ Surface(ํ‘œ๋ฉด)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์—ญํ• : ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž๋Š” Surface๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ฒŒ์ž„ ๊ฐ์ฒด์˜ ์‹œ๊ฐ์  ์š”์†Œ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

8. player.rect = player.surf.get_rect(center = (h, v))

  • ์„ค๋ช…: Surface ๊ฐ์ฒด์˜ ์‚ฌ๊ฐํ˜•(Rect) ์†์„ฑ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์—ญํ• : ์Šคํ”„๋ผ์ดํŠธ์˜ ์œ„์น˜์™€ ์ถฉ๋Œ ๊ฐ์ง€๋ฅผ ์œ„ํ•œ ์ขŒํ‘œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

9. pygame.display.update()

  • ์„ค๋ช…: ํ™”๋ฉด์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๋ฐฐ๊ฒฝ๊ณผ ์Šคํ”„๋ผ์ดํŠธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

10. pygame.key.get_pressed()

  • ์„ค๋ช…: ํ˜„์žฌ ๋ˆŒ๋ฆฐ ํ‚ค๋“ค์˜ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์—ญํ• : ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์™ผ์ชฝ ๋˜๋Š” ์˜ค๋ฅธ์ชฝ ํ™”์‚ดํ‘œ ํ‚ค๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ํ™•์ธํ•˜์—ฌ, ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.

11. player.rect.move_ip(-moveSpeed, 0)

  • ์„ค๋ช…: ํ”Œ๋ ˆ์ด์–ด์˜ ์œ„์น˜๋ฅผ ์™ผ์ชฝ(-) ๋˜๋Š” ์˜ค๋ฅธ์ชฝ(+)์œผ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.
  • ์—ญํ• : ํ‚ค ์ž…๋ ฅ์— ๋”ฐ๋ผ ํ”Œ๋ ˆ์ด์–ด์˜ rect ์ขŒํ‘œ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์ด๋™์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

12. pygame.QUIT

  • ์„ค๋ช…: ๊ฒŒ์ž„ ์ฐฝ์„ ๋‹ซ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•˜๋ฉด pygame.quit()์„ ํ˜ธ์ถœํ•˜์—ฌ Pygame์„ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

13. pygame.quit()

  • ์„ค๋ช…: Pygame์„ ์ข…๋ฃŒํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋  ๋•Œ ํ˜ธ์ถœ๋˜๋ฉฐ, Pygame ๊ด€๋ จ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

14. sys.exit()

  • ์„ค๋ช…: ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : Pygame ์ข…๋ฃŒ ํ›„ ์‹œ์Šคํ…œ์ ์œผ๋กœ ๊ฒŒ์ž„์„ ์™„์ „ํžˆ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

15. pygame.event.get()

  • ์„ค๋ช…: Pygame์—์„œ ๋ฐœ์ƒํ•œ ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ์—ญํ• : ํ‚ค ์ž…๋ ฅ, ๋งˆ์šฐ์Šค ํด๋ฆญ, ์ฐฝ ๋‹ซ๊ธฐ ๋“ฑ์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

16. screen.blit(IMG_ROAD, (0,0))

  • ์„ค๋ช…: ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ๋ฐฐ์น˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ๋ฐฐ๊ฒฝ์„ ํ™”๋ฉด์— ๋‹ค์‹œ ๊ทธ๋ ค์ค๋‹ˆ๋‹ค.

17. enemy.rect.move_ip(0, moveSpeed)

  • ์„ค๋ช…: ์ ์„ ์•„๋ž˜์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ์ ์ด ์ง€์†์ ์œผ๋กœ ํ™”๋ฉด ์•„๋ž˜์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

18. time.sleep(2)

  • ์„ค๋ช…: ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ํ”„๋กœ๊ทธ๋žจ์„ ๋ฉˆ์ถ”๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • ์—ญํ• : ๊ฒŒ์ž„ ์˜ค๋ฒ„ ํ™”๋ฉด์„ 2์ดˆ๊ฐ„ ์œ ์ง€ํ•œ ํ›„ ์ข…๋ฃŒํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€