TIL_220426
- -
κ°μΈ νλ‘μ νΈ μ£Όκ°
무μμ λκΌλκ°.
κ°μΈ νλ‘μ νΈλ₯Ό μ§ννλ©΄μ, λ°°μ΄ κ²λ³΄λ€ μ½λ μ€λ₯λ‘ ν΄κ²°νλ μκ°μ μμκ° κ°μ₯ ν¬λ€.
λμκ²λ μ€λ ₯μ΄ λκ² μ§λ§, μ무리 μκ°ν΄λ λ무 μμ½κ³ , λ무 μκΉλ€.
λ¨μκ°μ μ°Ύμ μ μμλ μ€λ₯μλ€.
νμ§λ§ μ΄λ° μ€λ₯μ λν΄μ μ΄λ λΆλΆμ μ€μ μΌλ‘ λκ³ νμΈν΄μΌ νλμ§, μ¬μ μ§μμ΄ μμΌλ μ²μλΆν° λκΉμ§ λ€μ 보λ λ―Έλ ¨ν νλμ 보μλ€.
μ΄μ 보λ μ€λ₯λ κ°μ₯ 맨 λ§μ§λ§μ μ€νμλ‘ λ°κ²¬λμ΄ λ§λ¬΄λ¦¬ λμλ€.
κ·Έ μΈμλ μ€λ₯λ μλμ§λ§, μ½λ νμ©μ μμ΄μ μ΄λ λΆλΆμ μ μ©μμΌ κ²μμ΄ λμλλμ§ νλ νλλ₯Ό λ£μ΄λ³΄λ©° νμΈν΄μΌλ§ νλ€.
μ΄λ κ² λ³΄λΈ μκ°μ΄ λ²μ¨ 2μΌμ΄ λλκ³ λΉμ₯ λ°νμΌμ΄ λμλ€.
νμ§λ§ λλ 무μμ λκΌλκ°.
κ·Έλ κ² λ§€λ¬λ¦¬κ³ , μ«κ³ , νν€μ³€λ κ·Έ κ³Όμ μ κ±°μ³ ν΄κ²°λ‘ λλ¬νμ λμ μ±μ·¨κ°.
λ΄ λ¨Έλ¦¬μμΌλ‘ κ·Έλ € λμκ°λ©°, μ€μ λ‘ μ½λμ μ μ©ν΄ λμλλ κ²μ λ³΄κ³ λλΌλ ν¬μ΄κ°.
κ·Έλ¦¬κ³ λ΄κ° λ°°μ°κ³ μ±μ₯νκ³ μλ€λ κ²μ λλΌκ² ν΄μ£Όλ μ§κΈμ κ²°κ³Ό.
μ€ν¨λ‘ λλ¬λ€κ° μλλΌ ν κ±Έμ λ λμκ° λ°νμ΄ λμμμ λ§μμμ νκ³ ,
λΆλ ν¬κΈ°λ§κ³ ,
κ³μ λμκ°μ.
κ°μΈ νλ‘μ νΈ κΈ°ν [22. 04. 27. μμ ]
1. μ°½ νλ©΄
- 640 * 640 ν¬κΈ°
2. κ²μ μ΄λ―Έμ§
- λ°°κ²½ μ΄λ―Έμ§, μ μ νλ©΄ μ΄λ―Έμ§ 640 * 640
- κ²μ λ©λ΄ νλ©΄ μ΄λ―Έμ§ 640 * 640
- μ°μ£Όμ μ΄λ―Έμ§ 42 * 40
- νλ° μ΄λ―Έμ§ 70 * 55
- λ―Έμ¬μΌ μ΄λ―Έμ§ 20 * 20
- μ΄μ μ΄λ―Έμ§ (75 * 37, 75 * 55, , 75 * 25, 75 * 52, , 75 * 61)
3. μ’ν
- μ°μ£Όμ κ³ μ μμΉ : μ°½ νλ©΄μ μ€μ
- λ―Έμ¬μΌ μ΄λ μμΉ(μ°μ£Όμ μ€μ¬μΌλ‘) : λ€ λ°©ν₯ μ§μ§
- μ΄μ μ΄λ μμΉ(λ€ λ°©ν₯ μ°½ μ€μ¬μΌλ‘ μ°μ£Όμ μ ν₯ν΄) : λ€ λ°©ν₯ μμͺ½ μ΄λ
- λ°°κ²½ μ΄λ―Έμ§ μμΉ : (0, 0)
- κ²μ λ©λ΄ νλ©΄ μ΄λ―Έμ§ μμΉ : (0, 0)
- νλ° μ΄λ―Έμ§ μμΉ
- μ΅κ³ μ μ κΈ°λ‘ μμΉ : (150, 20)
- κ²μ μ λͺ© ν μ€νΈ μμΉ : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ μ€μ¬)
- μν° ν€ μλ΄ ν μ€νΈ μμΉ : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ μ€μ¬ + 200)
- κ²μ μμ ν μ€νΈ μμΉ : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ μ€μ¬ + 250)
- μ μ νμΈ μλ΄ ν μ€νΈ μμΉ : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ μ€μ¬ + 350)
- μ μ ν μ€νΈ μμΉ 1 : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ / 4 + 100)
- μ μ ν μ€νΈ μμΉ 2 : (μ°½ λλΉ μ€μ¬, μ°½ λμ΄ / 4 + 200)
4. FPS
- μ΄λΉ 60
5. μμ
- BLACK = (0, 0, 0)
- WHITE = (255, 255, 255)
- YELLOW = (250, 250, 50)
- RED = (250, 50, 50)
6. μμΉ μ μ
- μ°μ£Όμ μ νλ©΄ μμΉ κ³ μ
- μ΄λ²€νΈ ν€ μ λ ₯μ λ°λ₯Έ λ€ λ°©ν₯ λ―Έμ¬μΌ μ¬μΆ μμΉ μ μ
-- λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ° κ²½μ° λ―Έμ¬μΌ μ κ±°
- μ°½μ μ€μ¬ λ€ λ°©ν₯μΌλ‘ μ°μ£Όμ μ ν₯νκ² μ΄μμ μ΄λ μμΉ μ μ
7. μΆ©λ μ²λ¦¬
- μ°μ£Όμ κ³Ό μ΄μμ μΆ©λ μ²λ¦¬
- λ―Έμ¬μΌκ³Ό μ΄μμ μΆ©λ μ²λ¦¬
8. κ·μΉ μ μ
- μ°μ£Όμ μΌλ‘ ν₯νλ μ΄μμ μΆ©λμ λ§μμΌ ν¨.
- μ°μ£Όμ μ λ€ λ°©ν₯μΌλ‘ λ―Έμ¬μΌμ λ°μ¬
- μ΄μμ λ€ λ°©ν₯μμ λλ€μ νλ₯ λ‘ 5κ°μ§μ μ΄μ μ’ λ₯ μΆν
- 100/ 200/ 300 μ μ΄μ 격μΆμ λ°λ₯Έ λμ΄λ μ¦κ°
κΈ°λ°μ΄ λλ μμ€ λ°λΌμ°λ©° μ΄ν΄νκΈ°
import random
from time import sleep
import pygame as pg
from pygame.locals import *
# μ°½ μ¬μ΄μ¦ μ μλ³μ
WINDOW_WIDTH = 480
WINDOW_HEIGHT = 640
# μμ μ μ
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (250, 250, 50)
RED = (250, 50, 50)
# μ΄λΉ νλ μ
FPS = 60
# μ°μ£Όμ ν΄λμ€
# κ²μμμ λνλ΄λ λͺ¨λ μΊλ¦ν°, μ₯μ λ¬Όλ±μ ννν λ μ¬μ©νλ Surface μμμ λ°μμ¨λ€.
class Fighter(pg.sprite.Sprite):
# λ€λ₯Έ κ°μ²΄μ§ν₯ μΈμ΄μμλ μμ±μ(constructor)λΌκ³ λΆλ₯Έλ΅λλ€
# μ΄κΈ°ν λ©μλ, μ΄λ€ ν΄λμ€μ κ°μ²΄κ° λ§λ€μ΄μ§ λ μλμΌλ‘ νΈμΆλμ΄μ κ·Έ κ°μ²΄κ° κ°κ² λ μ¬λ¬ κ°μ§ μ±μ§μ μ ν΄μ£Όλ μΌ
def __init__(self): # λ¨μΌ
super(Fighter, self).__init__() # μμ ν΄λμ€ __init__ νΈμΆ
self.image = pg.image.load('fighter.png') # self(Fighterμ μ΄κΈ°ν κ°) μ μ
ν μ΄λ―Έμ§λ₯Ό κ°μ Έμ¨λ€.
self.rect = self.image.get_rect() # μ΄λ―Έμ§ ν¬κΈ° μ‘°μ .get_rect(none)[ν¬κΈ° μ 보 + μ’ν μ 보]
self.rect.x = int(WINDOW_WIDTH / 2) # μ²μ μ°μ£Όμ μ λ±μ₯ μμΉ (WINDOW_WIDTH / 2 = μ°½μ λλΉμ μ€μ)
self.rect.y = WINDOW_HEIGHT - self.rect.height # μ°μ£Όμ μ λμ΄ λ§νΌ λΉΌμ y κ°μ μ§μ
self.dx = 0 # x λ°©ν₯
self.dy = 0 # y λ°©ν₯
# νλ©΄ λ°μΌλ‘ λκ°μ κ²½μ°λ₯Ό λλΉν 루νΈ
def update(self):
self.rect.x += self.dx # μ°μ£Όμ .rect.x μμΉκ° μ°μ£Όμ .dx μ΄λν μμΉ λ§νΌ λν΄μ§λ€.
self.rect.y += self.dy # μμ§μ νμμ μΈ λΆλΆ
# μ°μ£Όμ .rect.x μ’νκ° 0 λ³΄λ€ μμ κ²½μ°λ = νλ©΄ λ°μΌλ‘ λκ°λ κ²½μ°
# λ§μ½ X μμΉκ° μ°μ£Όμ μ λλΉλ₯Ό ν¬ν¨ν μ’νκ° μ°½μ λλΉλ³΄λ€ ν΄ κ²½μ°
if self.rect.x < 0 or self.rect.x + self.rect.width > WINDOW_WIDTH: # μ°½μ λ°μΌλ‘ λκ°μ κ²½μ°λ₯Ό λλΉ
self.rect.x -= self.dx # λκ°λ©΄ μμ§μμ λ©μΆ€
# μ°μ£Όμ .rect.y μ’νκ° 0 λ³΄λ€ μμ κ²½μ°λ = νλ©΄ λ°μΌλ‘ λκ°λ κ²½μ°
# λ§μ½ Y μμΉκ° μ°μ£Όμ μ λμ΄λ₯Ό ν¬ν¨ν μ’νκ° μ°½μ λμ΄λ³΄λ€ ν΄ κ²½μ°
if self.rect.y < 0 or self.rect.y + self.rect.height > WINDOW_HEIGHT:
self.rect.y -= self.dy
# κ·Έλ €μ£Όλ λΆλΆ
def draw(self, screen): # self μμ μ€ν¬λ¦° κ°μ λ°μμ¨λ€.
screen.blit(self.image, self.rect) # νλ©΄μ κ·Έλ €μ€ μ°μ£Όμ (self) μ μ΄λ―Έμ§μ μ°μ£Όμ (self) μ μ¬μ΄μ¦
def collide(self, sprites):
for sprite in sprites: # κ°μ²΄ κ΄λ¦¬λ₯Ό νΈνκ² νκΈ° μν λ°©λ²
if pg.sprite.collide_rect(self, sprite): # κ²μ¬ μ€ μ°μ£Όμ κ³Ό sprite μ μΆ©λνμ κ²½μ° / .collide_rect = μΆ©λ 체ν¬
return sprite # μΆ©λ λ sprite return
# λ―Έμ¬μΌ ν΄λμ€
class Missile(pg.sprite.Sprite):
def __init__(self, xpos, ypos, speed): # μ΄κΈ°ν λ©μλ, λΆλ¬μ¬ κ° μ§μ
super(Missile, self).__init__()
self.image = pg.image.load('missile.png')
self.rect = self.image.get_rect() # λ―Έμ¬μΌ μ¬μ΄μ¦
self.rect.x = xpos # λ―Έμ¬μΌ νΈμΆνλ μμΉ κ° μ§μ / μ°μ£Όμ μμ λ°μ¬ν μ μκ² λ§λ€κΈ° μν
self.rect.y = ypos
self.speed = speed
self.sound = pg.mixer.Sound('missile.wav')
def launch(self): # λ°μ¬μ λν μ리
self.sound.play() # μ리 μ¬μ
# λ―Έμ¬μΌμ μμΉ
def update(self):
self.rect.y -= self.speed # μλμμ μλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.y + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
# λ―Έμ¬μΌ μΆ©λ 체ν¬
def collide(self, sprites):
for sprite in sprites:
if pg.sprite.collide_rect(self, sprite):
return sprite
# μ΄μ ν΄λμ€
class Rock(pg.sprite.Sprite):
def __init__(self, xpos, ypos, speed): # μ΄κΈ°ν λ©μλ, μ΄μμ μ’ν λ° μ€νΌλ
super(Rock, self).__init__()
rock_images = ('rock01.png', 'rock02.png', 'rock03.png', 'rock04.png', 'rock05.png', \
'rock06.png', 'rock07.png', 'rock08.png', 'rock09.png', 'rock10.png', \
'rock11.png', 'rock12.png', 'rock13.png', 'rock14.png', 'rock15.png', \
'rock16.png', 'rock17.png', 'rock18.png', 'rock19.png', 'rock20.png', \
'rock21.png', 'rock22.png', 'rock23.png', 'rock24.png', 'rock25.png', \
'rock26.png', 'rock27.png', 'rock28.png', 'rock29.png', 'rock30.png') # μ΄μ 1 ~ 30 μ μ / νν μ μ©
self.image = pg.image.load(random.choice(rock_images)) # rock_images μμ λλ€μΌλ‘ μ΄λ―Έμ§λ₯Ό 골λΌμ€
self.rect = self.image.get_rect()
self.rect.x = xpos
self.rect.y = ypos
self.speed = speed
# μ΄μ μ
λ°μ΄νΈ
def update(self):
self.rect.y += self.speed # μμμ λ°μΌλ‘ λ΄λ €μ€λ κ° +
# μ΄μμ΄ νλ©΄ λ°μΌλ‘ λκ°μ κ²½μ°
def out_of_screen(self):
if self.rect.y > WINDOW_HEIGHT: # μ΄μμ y κ°μ΄ λ§μ½μ νλ©΄μ λμ΄λ³΄λ€ 컀μ§λ©΄ = μ΄μμ΄ μλ νλ©΄ λκΉμ§ λκ°μ λ
return True # λκ°μ κ²½μ°μ μν©μ νΈμΆνκΈ° μν True
# κ²μ νλ©΄ μμ νμ λλ ν
μ€νΈ μΆλ ₯
def draw_text(text, font, surface, x, y, main_color):
text_obj = font.render(text, True, main_color) # font.render λ‘ ν°νΈ μ μ / μνλ ν
μ€νΈ μμ μ§μ
text_rect = text_obj.get_rect() # ν
μ€νΈμ μμΉ μ§μ
text_rect.centerx = x
text_rect.centery = y
surface.blit(text_obj, text_rect) # .blit(νλ©΄ μΆλ ₯ν κ°μ²΄, μΆλ ₯ν μμΉ)
# νλ° ν¨κ³Ό
def occur_explosion(surface, x, y):
explosion_image = pg.image.load('explosion.png')
explosion_rect = explosion_image.get_rect()
explosion_rect.x = x
explosion_rect.y = y
surface.blit(explosion_image, explosion_rect)
explosion_sounds = ('explosion01.wav', 'explosion02.wav', 'explosion03.wav')
explosion_sound = pg.mixer.Sound(random.choice(explosion_sounds))
explosion_sound.play()
# λ©μΈ κ²μμ 루ν
def game_loop():
default_font = pg.font.Font('NanumGothic.ttf', 28) # κ²μ ν°νΈ
background_image = pg.image.load('background.png') # κ²μ λ°°κ²½ μ΄λ―Έμ§
gameover_sound = pg.mixer.Sound('gameover.wav') # κ²μ μ’
λ£
pg.mixer.music.load('music.wav') # κ²μ μμ
pg.mixer.music.play(-1) # λͺ λ² μ¬μν κ²μΈκ° (-1 = 무ν)
fps_clock = pg.time.Clock() # νλ μ
fighter = Fighter() # λ§λ€μλ ν΄λμ€λ₯Ό μΈμ€ν΄μ€λ‘ μ§μ
missiles = pg.sprite.Group() # μ¬λ¬ κ°μ λ―Έμ¬μΌμ .Group() μΌλ‘ λ¬Άμ
rocks = pg.sprite.Group() # μ¬λ¬ κ°μ μ΄μμ λ¬Άμ
occur_prob = 40 # νλ₯ μ μΌλ‘ μΌλ§νΌ λμ€κ² νλκ°
shot_count = 0 # λ§μΆ κ°μ
count_missed = 0 # λμΉ κ°μ
# κ²μμ λ°λ³΅
done = False
while not done: # done μ΄ λ§μ½μ True κ° λλ€λ©΄ λ°λ³΅λ¬Έ μ’
λ£
for event in pg.event.get(): # event μ pg.event.get() λ₯Ό κ°μ Έμ€κ³
if event.type == pg.KEYDOWN: # event.type μ΄ ν€ λ€μ΄ μνμΌ λ = μ
λ ₯ μνμΌ λ
if event.key == pg.K_LEFT: # κ·Όλ° λ§μ½μ event.key κ° μΌμͺ½μ΄ λλ Έλ€λ©΄
fighter.dx -= 5 # μΌμͺ½(-xμ΄λ) μΌλ‘ 5 λ§νΌ μ΄λ
elif event.key == pg.K_RIGHT:
fighter.dx += 5 # μ€λ₯Έμͺ½(+xμ΄λ) μΌλ‘ 5 λ§νΌ μ΄λ
elif event.key == pg.K_UP:
fighter.dy -= 5 # μ(-yμ΄λ) λ‘ 5 λ§νΌ μ΄λ
elif event.key == pg.K_DOWN:
fighter.dy += 5 # μλ(+yμ΄λ) λ‘ 5 λ§νΌ μ΄λ
elif event.key == pg.K_SPACE:
missile = Missile(fighter.rect.centerx, fighter.rect.y, 10) # Missle class > (xpos, ypos, speed)
missile.launch()
missiles.add(missile) # μ λ£μ΄μ£Όλλ°?
if event.type == pg.KEYUP: # ν€μ
μΈ μνμμ
if event.key == pg.K_LEFT or event.key == pg.K_RIGHT: # μΌμͺ½ or μ€λ₯Έμͺ½ ν€λ₯Ό λ λ€λ©΄
fighter.dx = 0 # x μ΄λμ λ©μΆλ€
elif event.key == pg.K_UP or event.key == pg.K_DOWN: # μ or μλ ν€λ₯Ό λ λ€λ©΄
fighter.dy = 0 # y μ΄λμ λ©μΆλ€
screen.blit(background_image, background_image.get_rect()) # νλ©΄ μΆλ ₯(λ°±κ·ΈλΌμ΄λ μ΄λ―Έμ§, λ°±κ·ΈλΌμ΄λ μμΉ μ’ν)
# λ§μ½μ μ΄μμ 100κ° νκ΄΄ νλ€λ©΄, μ€νΌλμ μ΄μ μλ₯Ό μ¦κ°μν¨λ€ = λμ΄λ μμΉ
occur_of_rocks = 1 + int(shot_count / 300) # shot_count = μΌλ§νΌ μ΄μμ λ§μ·λκ°
min_rock_speed = 1 + int(shot_count / 200)
max_rock_speed = 1 + int(shot_count / 100)
if random.randint(1, occur_prob) == 1: # 1 λΆν° occur_prob(40) μ¬μ΄μ 1μ΄ λ±μ₯ν νλ₯ = 1/40
for i in range(occur_of_rocks):
speed = random.randint(min_rock_speed, max_rock_speed) # μ€νΌλλ₯Ό λλ€μΌλ‘ μ ν
rock = Rock(random.randint(0, WINDOW_WIDTH - 30), 0, speed) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
rocks.add(rock)
# ('νμν ν
μ€νΈ', μ¬μ©ν ν°νΈ, νμν νλ©΄, xμ’ν, yμ’ν, μμ)
draw_text('νκ΄΄ν μ΄μ : {}'.format(shot_count), default_font, screen, 100, 20, YELLOW) # νκ΄΄ν μ΄μ νμ
draw_text('λμΉ μ΄μ : {}'.format(count_missed), default_font, screen, 400, 20, RED) # λμΉ μ΄μ νμ
# λ―Έμ¬μΌμ΄ μ¬λ¬κ° λ°μ¬ λμ λ
for missile in missiles:
rock = missile.collide(rocks) # λ―Έμ¬μΌμ΄ μ΄μκ³Όμ μΆ©λ 체ν¬
if rock: # μΆ©λμ΄ λ¬λ€λ©΄
missile.kill() # λ―Έμ¬μΌ ν°μ§
rock.kill() # μ΄μ ν°μ§
occur_explosion(screen, rock.rect.x, rock.rect.y) # μ΄μμ΄ ν°μ§λ ν¨κ³Ό(μΆλ ₯ν νλ©΄, x μμΉ, y μμΉ)
shot_count += 1 # μ΄μμ νκ΄΄νμ λ μ μ μ΅λ
# μ 체 μ΄μλ€ μ€μμ
for rock in rocks:
if rock.out_of_screen(): # λ§μ½ μ΄μμ΄ νλ©΄ λ°μΌλ‘ λκ°λ€λ©΄
rock.kill() # μ΄μ μλ©Έ
count_missed += 1 # λμΉ μ μ¦κ°
rocks.update()
rocks.draw(screen)
missiles.update()
missiles.draw(screen)
fighter.update()
fighter.draw(screen)
pg.display.flip()
# κ²μμ΄ λλλ 쑰건
if fighter.collide(rocks) or count_missed >= 3: # μ°μ£Όμ μ΄ μΆ©λμ΄ λ¬μ λ or μ΄μ λμΉ κ°μκ° 3κ° μ΄μμΌ λ
pg.mixer_music.stop() # κ²μ μμ
μ΄ κΊΌμ§
occur_explosion(screen, fighter.rect.x, fighter.rect.y) # μ°μ£Όμ μ΄ μμΉν κ³³μμ ν°μ§λ ν¨κ³Ό
pg.display.update()
gameover_sound.play() # κ²μμ΄ μ’
λ£λλ μμ
sleep(1) # μ μ λκΈ° 1μ΄
done = True # done μ΄ True κ° λ κ²½μ° κ²μμ μ’
λ£λλ€. 153μ΄ μ°Έμ‘°
fps_clock.tick(FPS) # νλ μ μ§μ
return 'game_menu' # κ²μ λ©λ΄λ‘ λμκ°
# κ²μ λ©λ΄
def game_menu():
start_image = pg.image.load('background.png')
screen.blit(start_image, [0, 0])
draw_x = int(WINDOW_WIDTH / 2)
draw_y = int(WINDOW_HEIGHT / 4)
font_70 = pg.font.Font('NanumGothic.ttf', 70)
font_40 = pg.font.Font('NanumGothic.ttf', 40)
draw_text('μ§κ΅¬λ₯Ό μ§μΌλΌ!', font_70, screen, draw_x, draw_y, YELLOW)
draw_text('μν° ν€λ₯Ό λλ₯΄λ©΄', font_40, screen, draw_x, draw_y + 200, WHITE)
draw_text('κ²μμ΄ μμλ©λλ€.', font_40, screen, draw_x, draw_y + 250, WHITE)
pg.display.update()
# μ΄ νλ©΄ λ΄μμ λ°μμ€λ ν€ κ°μ μ΄λ²€νΈ μ²λ¦¬
for event in pg.event.get():
if event.type == pg.KEYDOWN:
if event.key == pg.K_RETURN: # K_RETURN = μν° κ°
return 'play'
if event.type == QUIT: # κ²μ μ’
λ£
return 'quit'
return 'game_menu'
# κ²μ μ
ν
def main():
global screen
pg.init() # μ΄κΈ°ν
screen = pg.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # νλ©΄ μ
ν
.set_mode
pg.display.set_caption('PyShooting') # νλ©΄ μ΄λ¦
action = 'game_menu'
while action != 'quit': # λ§μ½μ action μ΄ quit μ΄ μλλ©΄
if action == 'game_menu': # λ§μ½μ action μ΄ κ²μ λ©λ΄μ΄λ©΄
action = game_menu()
elif action == 'play': # μλλΌλ©΄ action μ΄ νλ μ΄ λΌλ©΄
action = game_loop() # κ²μ μν
pg.quit()
# main μ μ€νμν€κΈ° μν΄ __name__ μ΄ __main__ μΌ κ²½μ°μ
if __name__ == "__main__":
main() # main() μ μ€ν μμΌλΌ > κ²μ μ
ν
μ μν
μΆμ² : https://youtu.be/W92RjjptAsM
λμ μ€νμΌ arrange
- κΈ°μ‘΄μ μμ±μ κΉ¨κ³ μμ λ§μ μ½λλ‘ λ°κΎΈμ΄ μ€λ ₯ ν€μ°κΈ°
- ν΄λμ€μ μ¬μ©λ°©λ²κ³Ό λΆλΆ ν¨μμ νμ© μ΄ν΄
- μ½λμ νλ¦ μ΄ν΄
κ²μ λͺ©ν : λ€ λ°©ν₯ μ΄μ λ§κΈ°
κΈ°λ₯ μ μ
- μ°μ£Όμ μμΉ κ³ μ
- μ°μ£Όμ λ°μ¬ λ°©ν₯ μ ν
- μ°μ£Όμ λ―Έμ¬μΌ μ¬μΆ λ°©ν₯
- μ°μ£Όμ λ―Έμ¬μΌ μ΄λ―Έμ§ λ°©ν₯
- μ΄μ μΆ©λ λ°©ν₯
- κ²½λ‘ : Route
- λ€μν΄μ§ νμΌλ€μ ν΄λν ν΄μ μ 리νκ³ , os λ₯Ό μν¬νΈ ν΄μ ν΄λμ κ²½λ‘ μ€μ κ³Ό μ§μ ν΄λμ νμΌ νΈμΆμ κ°νΈνκ² μ¬μ©
import os
# μ΄λ―Έμ§ ν΄λ κ²½λ‘ μ€μ / νμΌλͺ
μ§μ
current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "image")
sound_path = os.path.join(current_path, "sound")
font_path = os.path.join(current_path, "font")
user_image = pg.image.load(os.path.join(image_path, "fighter.png"))
- λ―Έμ¬μΌ μ΄λ―Έμ§ λ°©ν₯
- μ°μ£Όμ μ μΌκ΄μ μΈ λ―Έμ¬μΌ μ΄λ―Έμ§λ₯Ό νμ μμΌ λμκ°λ λ°©ν₯μΌλ‘ μ μ
- Missile λ©μλμμ rotate ν¨μλ₯Ό μ μνκ³ λ°©ν₯ μ λ ₯κ°μ λ°λ₯Έ μ΄λ―Έμ§λ₯Ό μ ν
def rotate(self, direction): # μ΄λ―Έμ§ νμ
self.direction = direction
if self.direction == 2:
self.image = pg.transform.rotate(self.image, 180)
elif self.direction == 3:
self.image = pg.transform.rotate(self.image, 90)
elif self.direction == 4:
self.image = pg.transform.rotate(self.image, 270)
- λ―Έμ¬μΌ μ¬μΆ λ°©ν₯
- μ°μ£Όμ μ ν λ°©ν₯μΌλ‘λ§ μ¬μΆλλ λ―Έμ¬μΌμ λ€ λ°©ν₯μΌλ‘ μ μ
- νμ κ³Ό λ§μ°¬κ°μ§λ‘ μ μλ λ°©ν₯κ°μ λ°λΌ Missile ν΄λμ€μ μ΄λ μ’ν λ°©ν₯μ μ μ
- νλ©΄ λ°μΌλ‘ λκ° μ λ―Έμ¬μΌ μ κ±°
# λ―Έμ¬μΌ μ¬μΆ λ°©ν₯
# μ°μ£Όμ κΈ°μ€ μνμ’μ° λ°©ν₯μΌλ‘ λ°μ¬
def update(self):
if self.direction == 1:
self.rect.y -= self.speed # μ°μ£Όμ μμ μλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.y + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 2:
self.rect.y += self.speed # μ°μ£Όμ μμ μλλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.y + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 3:
self.rect.x -= self.speed # μ°μ£Όμ μμ μΌμͺ½μΌλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.x + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 4:
self.rect.x += self.speed # μ°μ£Όμ μμ μ€λ₯Έμͺ½μΌλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.x + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
- μ°μ£Όμ ν€ μ΄λ²€νΈ μ€μ
- κ³ μ μ’νμ μ°μ£Όμ μμ ν€ μ΄λ²€νΈλ₯Ό ν΅ν΄ λ€ λ°©ν₯μΌλ‘ ν€ μ΄λ²€νΈ μ μ
- missile μ ν€ μ΄λ²€νΈμ λ°λ₯Έ μ¬μΆ μ§μ κ³Ό μλ λ°©ν₯μ μ μν Missile ν΄λμ€λ₯Ό λ΄λλ€. λ€μ μ¬μ μ μλ missilesμ sprite.Group() μΌλ‘ λ΄λλ€.
missiles = pg.sprite.Group() # μ¬λ¬ κ°μ λ―Έμ¬μΌμ .Group() μΌλ‘ λ¬Άμ
# κ²μμ λ°λ³΅
done = False
while not done: # done μ΄ λ§μ½μ True κ° λλ€λ©΄ λ°λ³΅λ¬Έ μ’
λ£
for event in pg.event.get(): # event μ pg.event.get() λ₯Ό κ°μ Έμ€κ³
if event.type == pg.KEYDOWN: # event.type μ΄ ν€ λ€μ΄ μνμΌ λ = μ
λ ₯ μνμΌ λ
if event.key == pg.K_UP:
missile = Missile(fighter.rect.centerx - 9, fighter.rect.centery - 5, 10, 1) # Missle class > (xpos, ypos, speed)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_DOWN:
missile = Missile(fighter.rect.centerx - 9, fighter.rect.centery - 5, 10, 2) # Missle class > (xpos, ypos, speed)
missile.rotate(2)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_LEFT: # κ·Όλ° λ§μ½μ event.key κ° μΌμͺ½μ΄ λλ Έλ€λ©΄
missile = Missile(fighter.rect.centerx - 5, fighter.rect.centery - 5, 10, 3) # Missle class > (xpos, ypos, speed)
missile.rotate(3)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_RIGHT:
missile = Missile(fighter.rect.centerx - 5, fighter.rect.centery - 5, 10, 4) # Missle class > (xpos, ypos, speed)
missile.rotate(4)
# missile.launch()
missiles.add(missile)
# λ―Έμ¬μΌμ΄ μ¬λ¬κ° λ°μ¬ λμ λ
for missile in missiles:
rock = missile.collide(rocks) # λ―Έμ¬μΌμ΄ μ΄μκ³Όμ μΆ©λ 체ν¬
if rock: # μΆ©λμ΄ λ¬λ€λ©΄
missile.kill() # λ―Έμ¬μΌ ν°μ§
rock.kill() # μ΄μ ν°μ§
occur_explosion(screen, rock.rect.x, rock.rect.y) # μ΄μμ΄ ν°μ§λ ν¨κ³Ό(μΆλ ₯ν νλ©΄, x μμΉ, y μμΉ)
shot_count += 1 # μ΄μμ νκ΄΄νμ λ μ μ μ΅λ
- μ΄μ μΆ©λ λ°©ν₯
- κ²μμ μ°½ WIDTH μ HEIGHT μ κ°μΌλ‘ μ€κ° μ§μ μ’νλ₯Ό κ³μ°
# μ΄μ μΆ©λ λ°©ν₯ & λ±μ₯ νλ₯
if random.randint(1, occur_prob) == 1: # 1 λΆν° occur_prob(40) μ¬μ΄μ 1μ΄ λ±μ₯ν νλ₯ = 1/40
for i in range(occur_of_rocks):
speed = random.randint(min_rock_speed, max_rock_speed) # μ€νΌλλ₯Ό λλ€μΌλ‘ μ ν
rock_direction = random.randint(1, 4)
if rock_direction == 1:
rock = Rock(WINDOW_WIDTH / 2 - 40, 640, speed, 1) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 2:
rock = Rock(WINDOW_WIDTH / 2 - 40, 0, speed, 2) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 3:
rock = Rock(640, WINDOW_HEIGHT / 2 - 20, speed, 3) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 4:
rock = Rock(0, WINDOW_HEIGHT / 2 - 20, speed, 4) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
rocks.add(rock)
- 미ꡬν κΈ°λ₯
- μ΄μκ°μ μ€μ²© λ°©μ§
- μ΅κ³ μ μ€μ½μ΄ κΈ°λ‘ κΈ°λ₯
- λμ΄λ μμΉ μ κ΅¬λΆ νμ κΈ°λ₯
- 1μ°¨ μμ±
import random
from time import sleep
import os
import pygame as pg
from pygame.locals import *
# μ°½ μ¬μ΄μ¦ μ μλ³μ
WINDOW_WIDTH = 640
WINDOW_HEIGHT = 640
# μμ μ μ
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (250, 250, 50)
RED = (250, 50, 50)
# μ΄λ―Έμ§ κ²½λ‘ μ€μ
current_path = os.path.dirname(__file__)
image_path = os.path.join(current_path, "../image")
sound_path = os.path.join(current_path, "../sound")
font_path = os.path.join(current_path, "../font")
# μ΄λΉ νλ μ
FPS = 60
# μ°μ£Όμ ν΄λμ€
# κ²μμμ λνλ΄λ λͺ¨λ μΊλ¦ν°, μ₯μ λ¬Όλ±μ ννν λ μ¬μ©νλ Surface μμμ λ°μμ¨λ€.
class Fighter(pg.sprite.Sprite):
# λ€λ₯Έ κ°μ²΄μ§ν₯ μΈμ΄μμλ μμ±μ(constructor)λΌκ³ λΆλ₯Έλ΅λλ€
# μ΄κΈ°ν λ©μλ, μ΄λ€ ν΄λμ€μ κ°μ²΄κ° λ§λ€μ΄μ§ λ μλμΌλ‘ νΈμΆλμ΄μ κ·Έ κ°μ²΄κ° κ°κ² λ μ¬λ¬ κ°μ§ μ±μ§μ μ ν΄μ£Όλ μΌ
def __init__(self): # λ¨μΌ
super(Fighter, self).__init__() # μμ ν΄λμ€ __init__ νΈμΆ
self.image = pg.image.load(os.path.join(image_path, "fighter3.svg")) # self(Fighterμ μ΄κΈ°ν κ°) μ μ
ν μ΄λ―Έμ§λ₯Ό κ°μ Έμ¨λ€.
self.rect = self.image.get_rect() # μ΄λ―Έμ§ ν¬κΈ° μ‘°μ .get_rect(none)[ν¬κΈ° μ 보 + μ’ν μ 보]
self.rect.x = int(WINDOW_WIDTH / 2 - self.rect.width / 2) # μ²μ μ°μ£Όμ μ λ±μ₯ μμΉ (WINDOW_WIDTH / 2 = μ°½μ λλΉμ μ€μ)
self.rect.y = int(WINDOW_HEIGHT / 2 - self.rect.height / 2) # μ°μ£Όμ μ λμ΄ λ§νΌ λΉΌμ y κ°μ μ§μ
self.dx = 0 # x λ°©ν₯
self.dy = 0 # y λ°©ν₯
# νλ©΄ λ°μΌλ‘ λκ°μ κ²½μ°λ₯Ό λλΉν 루νΈ
def update(self):
self.rect.x += self.dx # μ°μ£Όμ .rect.x μμΉκ° μ°μ£Όμ .dx μ΄λν μμΉ λ§νΌ λν΄μ§λ€.
self.rect.y += self.dy # μμ§μ νμμ μΈ λΆλΆ
# μ°μ£Όμ .rect.x μ’νκ° 0 λ³΄λ€ μμ κ²½μ°λ = νλ©΄ λ°μΌλ‘ λκ°λ κ²½μ°
# λ§μ½ X μμΉκ° μ°μ£Όμ μ λλΉλ₯Ό ν¬ν¨ν μ’νκ° μ°½μ λλΉλ³΄λ€ ν΄ κ²½μ°
if self.rect.x < 0 or self.rect.x + self.rect.width > WINDOW_WIDTH: # μ°½μ λ°μΌλ‘ λκ°μ κ²½μ°λ₯Ό λλΉ
self.rect.x -= self.dx # λκ°λ©΄ μμ§μμ λ©μΆ€
# μ°μ£Όμ .rect.y μ’νκ° 0 λ³΄λ€ μμ κ²½μ°λ = νλ©΄ λ°μΌλ‘ λκ°λ κ²½μ°
# λ§μ½ Y μμΉκ° μ°μ£Όμ μ λμ΄λ₯Ό ν¬ν¨ν μ’νκ° μ°½μ λμ΄λ³΄λ€ ν΄ κ²½μ°
if self.rect.y < 0 or self.rect.y + self.rect.height > WINDOW_HEIGHT:
self.rect.y -= self.dy
# κ·Έλ €μ£Όλ λΆλΆ
def draw(self, screen): # self μμ μ€ν¬λ¦° κ°μ λ°μμ¨λ€.
screen.blit(self.image, self.rect) # νλ©΄μ κ·Έλ €μ€ μ°μ£Όμ (self) μ μ΄λ―Έμ§μ μ°μ£Όμ (self) μ μ¬μ΄μ¦
def collide(self, sprites):
for sprite in sprites: # κ°μ²΄ κ΄λ¦¬λ₯Ό νΈνκ² νκΈ° μν λ°©λ²
if pg.sprite.collide_rect(self, sprite): # κ²μ¬ μ€ μ°μ£Όμ κ³Ό sprite μ μΆ©λνμ κ²½μ° / .collide_rect = μΆ©λ 체ν¬
return sprite # μΆ©λ λ sprite return
# λ―Έμ¬μΌ ν΄λμ€
class Missile(pg.sprite.Sprite):
def __init__(self, xpos, ypos, speed, direction): # μ΄κΈ°ν λ©μλ, λΆλ¬μ¬ κ° μ§μ
super(Missile, self).__init__()
self.image = pg.image.load(os.path.join(image_path, "firetrail.png"))
self.rect = self.image.get_rect() # λ―Έμ¬μΌ μ¬μ΄μ¦
self.rect.x = xpos # λ―Έμ¬μΌ νΈμΆνλ μμΉ κ° μ§μ / μ°μ£Όμ μμ λ°μ¬ν μ μκ² λ§λ€κΈ° μν
self.rect.y = ypos
self.speed = speed
self.direction = direction
self.sound = pg.mixer.Sound(os.path.join(sound_path, "missile.wav"))
def launch(self): # λ°μ¬μ λν μ리
self.sound.play() # μ리 μ¬μ
def rotate(self, direction): # μ΄λ―Έμ§ νμ
self.direction = direction
if self.direction == 2:
self.image = pg.transform.rotate(self.image, 180)
elif self.direction == 3:
self.image = pg.transform.rotate(self.image, 90)
elif self.direction == 4:
self.image = pg.transform.rotate(self.image, 270)
# λ―Έμ¬μΌ μ¬μΆ λ°©ν₯
# μ°μ£Όμ κΈ°μ€ μνμ’μ° λ°©ν₯μΌλ‘ λ°μ¬
def update(self):
if self.direction == 1:
self.rect.y -= self.speed # μ°μ£Όμ μμ μλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.y + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 2:
self.rect.y += self.speed # μ°μ£Όμ μμ μλλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.y + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 3:
self.rect.x -= self.speed # μ°μ£Όμ μμ μΌμͺ½μΌλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.x + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
elif self.direction == 4:
self.rect.x += self.speed # μ°μ£Όμ μμ μ€λ₯Έμͺ½μΌλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
if self.rect.x + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
# self.rect.x -= self.speed # μλμμ μλ‘ λ°μ¬λλ μ’ν - / ν΄λΉνλ μλ λ§νΌ
# if self.rect.x + self.rect.height < 0: # λ§μ½μ y κ°μ λμ΄κ° λν΄μ§ κ°μΌλ‘ 0 λ³΄λ€ μμΌλ©΄ = λ―Έμ¬μΌμ΄ νλ©΄ λ°μΌλ‘ λκ°
# self.kill() # νλ©΄ λ°μΌλ‘ λκ° λ―Έμ¬μΌμ μμ μ€
# λ―Έμ¬μΌ μΆ©λ 체ν¬
def collide(self, sprites):
for sprite in sprites:
if pg.sprite.collide_rect(self, sprite):
return sprite
# μ΄μ ν΄λμ€
class Rock(pg.sprite.Sprite):
def __init__(self, xpos, ypos, speed, direction): # μ΄κΈ°ν λ©μλ, μ΄μμ μ’ν λ° μ€νΌλ
super(Rock, self).__init__()
rock_images = (os.path.join(image_path, "rock01.png"), os.path.join(image_path, "rock02.png"), os.path.join(image_path, "rock03.png"), os.path.join(image_path, "rock04.png"), os.path.join(image_path, "rock05.png")) # μ΄μ 1 ~ 5 μ μ / νν μ μ©
self.image = pg.image.load(random.choice(rock_images)) # rock_images μμ λλ€μΌλ‘ μ΄λ―Έμ§λ₯Ό 골λΌμ€
self.rect = self.image.get_rect()
self.rect.x = xpos
self.rect.y = ypos
self.speed = speed
self.direction = direction
# μ΄μ μ
λ°μ΄νΈ
def update(self):
# self.rect.y += self.speed # μμμ λ°μΌλ‘ λ΄λ €μ€λ κ° +
if self.direction == 1: # μλμμ μλ‘
self.rect.y -= self.speed
elif self.direction == 2: # μμμ μλλ‘
self.rect.y += self.speed
elif self.direction == 3: # μ€λ₯Έμͺ½μμ μΌμͺ½μΌλ‘
self.rect.x -= self.speed
elif self.direction == 4: # μΌμͺ½μμ μ€λ₯Έμͺ½μΌλ‘
self.rect.x += self.speed
# μ΄μμ΄ νλ©΄ λ°μΌλ‘ λκ°μ κ²½μ°
def out_of_screen(self):
if self.rect.y > WINDOW_HEIGHT: # μ΄μμ y κ°μ΄ λ§μ½μ νλ©΄μ λμ΄λ³΄λ€ 컀μ§λ©΄ = μ΄μμ΄ μλ νλ©΄ λκΉμ§ λκ°μ λ
return True # λκ°μ κ²½μ°μ μν©μ νΈμΆνκΈ° μν True
# κ²μ νλ©΄ μμ νμ λλ ν
μ€νΈ μΆλ ₯
def draw_text(text, font, surface, x, y, main_color):
text_obj = font.render(text, True, main_color) # font.render λ‘ ν°νΈ μ μ / μνλ ν
μ€νΈ μμ μ§μ
text_rect = text_obj.get_rect() # ν
μ€νΈμ μμΉ μ§μ
text_rect.centerx = x
text_rect.centery = y
surface.blit(text_obj, text_rect) # .blit(νλ©΄ μΆλ ₯ν κ°μ²΄, μΆλ ₯ν μμΉ)
# νλ° ν¨κ³Ό
def occur_explosion(surface, x, y):
explosion_image = pg.image.load(os.path.join(image_path, "explosion.png"))
explosion_rect = explosion_image.get_rect()
explosion_rect.x = x
explosion_rect.y = y
surface.blit(explosion_image, explosion_rect)
explosion_sounds = (os.path.join(sound_path, "explosion01.wav"), os.path.join(sound_path, "explosion02.wav"), os.path.join(sound_path, "explosion03.wav"))
explosion_sound = pg.mixer.Sound(random.choice(explosion_sounds))
explosion_sound.play()
# λ©μΈ κ²μμ 루ν
def game_loop():
default_font = pg.font.Font(os.path.join(font_path, "NanumGothic.ttf"), 28) # κ²μ ν°νΈ
background_image = pg.image.load(os.path.join(image_path, "background3.jpg")) # κ²μ λ°°κ²½ μ΄λ―Έμ§
gameover_sound = pg.mixer.Sound(os.path.join(sound_path, "gameover.wav")) # κ²μ μ’
λ£
pg.mixer.music.load(os.path.join(sound_path, "music.wav")) # κ²μ μμ
pg.mixer.music.play(-1) # λͺ λ² μ¬μν κ²μΈκ° (-1 = 무ν)
fps_clock = pg.time.Clock() # νλ μ
fighter = Fighter() # λ§λ€μλ ν΄λμ€λ₯Ό μΈμ€ν΄μ€λ‘ μ§μ
missiles = pg.sprite.Group() # μ¬λ¬ κ°μ λ―Έμ¬μΌμ .Group() μΌλ‘ λ¬Άμ
rocks = pg.sprite.Group() # μ¬λ¬ κ°μ μ΄μμ λ¬Άμ
occur_prob = 30 # νλ₯ μ μΌλ‘ μΌλ§νΌ λμ€κ² νλκ°
shot_count = 0 # λ§μΆ κ°μ
# count_missed = 0 # λμΉ κ°μ
# κ²μμ λ°λ³΅
done = False
while not done: # done μ΄ λ§μ½μ True κ° λλ€λ©΄ λ°λ³΅λ¬Έ μ’
λ£
for event in pg.event.get(): # event μ pg.event.get() λ₯Ό κ°μ Έμ€κ³
if event.type == pg.KEYDOWN: # event.type μ΄ ν€ λ€μ΄ μνμΌ λ = μ
λ ₯ μνμΌ λ
if event.key == pg.K_UP:
missile = Missile(fighter.rect.centerx - 9, fighter.rect.centery - 5, 10, 1) # Missle class > (xpos, ypos, speed)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_DOWN:
missile = Missile(fighter.rect.centerx - 9, fighter.rect.centery - 5, 10, 2) # Missle class > (xpos, ypos, speed)
missile.rotate(2)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_LEFT: # κ·Όλ° λ§μ½μ event.key κ° μΌμͺ½μ΄ λλ Έλ€λ©΄
missile = Missile(fighter.rect.centerx - 5, fighter.rect.centery - 5, 10, 3) # Missle class > (xpos, ypos, speed)
missile.rotate(3)
# missile.launch()
missiles.add(missile)
elif event.key == pg.K_RIGHT:
missile = Missile(fighter.rect.centerx - 5, fighter.rect.centery - 5, 10, 4) # Missle class > (xpos, ypos, speed)
missile.rotate(4)
# missile.launch()
missiles.add(missile)
# if event.type == pg.KEYUP: # ν€μ
μΈ μνμμ
# if event.key == pg.K_LEFT or event.key == pg.K_RIGHT: # μΌμͺ½ or μ€λ₯Έμͺ½ ν€λ₯Ό λ λ€λ©΄
# fighter.dx = 0 # x μ΄λμ λ©μΆλ€
# elif event.key == pg.K_UP or event.key == pg.K_DOWN: # μ or μλ ν€λ₯Ό λ λ€λ©΄
# fighter.dy = 0 # y μ΄λμ λ©μΆλ€
screen.blit(background_image, background_image.get_rect()) # νλ©΄ μΆλ ₯(λ°±κ·ΈλΌμ΄λ μ΄λ―Έμ§, λ°±κ·ΈλΌμ΄λ μμΉ μ’ν)
# λ§μ½μ μ΄μμ 100κ° νκ΄΄ νλ€λ©΄, μ€νΌλμ μ΄μ μλ₯Ό μ¦κ°μν¨λ€ = λμ΄λ μμΉ
occur_of_rocks = 1 + int(shot_count / 300) # shot_count = μΌλ§νΌ μ΄μμ λ§μ·λκ°
min_rock_speed = 1 + int(shot_count / 200)
max_rock_speed = 1 + int(shot_count / 100)
# μ΄μ λ±μ₯ νλ₯
if random.randint(1, occur_prob) == 1: # 1 λΆν° occur_prob(40) μ¬μ΄μ 1μ΄ λ±μ₯ν νλ₯ = 1/40
for i in range(occur_of_rocks):
speed = random.randint(min_rock_speed, max_rock_speed) # μ€νΌλλ₯Ό λλ€μΌλ‘ μ ν
rock_direction = random.randint(1, 4)
if rock_direction == 1:
rock = Rock(WINDOW_WIDTH / 2 - 40, 640, speed, 1) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 2:
rock = Rock(WINDOW_WIDTH / 2 - 40, 0, speed, 2) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 3:
rock = Rock(640, WINDOW_HEIGHT / 2 - 20, speed, 3) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
elif rock_direction == 4:
rock = Rock(0, WINDOW_HEIGHT / 2 - 20, speed, 4) # 0 λΆν° X μ’ν(λλΉ μ’νμμ 30μ λ λΊ κ°)κΉμ§
rocks.add(rock)
# ('νμν ν
μ€νΈ', μ¬μ©ν ν°νΈ, νμν νλ©΄, xμ’ν, yμ’ν, μμ)
draw_text('νκ΄΄ν μ΄μ : {}'.format(shot_count), default_font, screen, 100, 20, YELLOW) # νκ΄΄ν μ΄μ νμ
# draw_text('λμΉ μ΄μ : {}'.format(count_missed), default_font, screen, 400, 20, RED) # λμΉ μ΄μ νμ
# λ―Έμ¬μΌμ΄ μ¬λ¬κ° λ°μ¬ λμ λ
for missile in missiles:
rock = missile.collide(rocks) # λ―Έμ¬μΌμ΄ μ΄μκ³Όμ μΆ©λ 체ν¬
if rock: # μΆ©λμ΄ λ¬λ€λ©΄
missile.kill() # λ―Έμ¬μΌ ν°μ§
rock.kill() # μ΄μ ν°μ§
occur_explosion(screen, rock.rect.x, rock.rect.y) # μ΄μμ΄ ν°μ§λ ν¨κ³Ό(μΆλ ₯ν νλ©΄, x μμΉ, y μμΉ)
shot_count += 1 # μ΄μμ νκ΄΄νμ λ μ μ μ΅λ
rocks.update()
rocks.draw(screen)
missiles.update()
missiles.draw(screen)
fighter.update()
fighter.draw(screen)
pg.display.flip()
# κ²μμ΄ λλλ 쑰건
# if fighter.collide(rocks) or count_missed >= 3: # μ°μ£Όμ μ΄ μΆ©λμ΄ λ¬μ λ or μ΄μ λμΉ κ°μκ° 3κ° μ΄μμΌ λ
if fighter.collide(rocks): # μ°μ£Όμ μ΄ μΆ©λμ΄ λ¬μ λ or μ΄μ λμΉ κ°μκ° 3κ° μ΄μμΌ λ
pg.mixer_music.stop() # κ²μ μμ
μ΄ κΊΌμ§
occur_explosion(screen, fighter.rect.x, fighter.rect.y) # μ°μ£Όμ μ΄ μμΉν κ³³μμ ν°μ§λ ν¨κ³Ό
pg.display.update()
gameover_sound.play() # κ²μμ΄ μ’
λ£λλ μμ
sleep(1) # μ μ λκΈ° 1μ΄
done = True # done μ΄ True κ° λ κ²½μ° κ²μμ μ’
λ£λλ€. 153μ΄ μ°Έμ‘°
fps_clock.tick(FPS) # νλ μ μ§μ
return 'game_menu' # κ²μ λ©λ΄λ‘ λμκ°
#
# κ²μ λ©λ΄
def game_menu():
start_image = pg.image.load(os.path.join(image_path, "background_menu.png"))
screen.blit(start_image, [0, 0])
draw_x = int(WINDOW_WIDTH / 2)
draw_y = int(WINDOW_HEIGHT / 4)
font_70 = pg.font.Font(os.path.join(font_path, "NanumGothic.ttf"), 70)
font_40 = pg.font.Font(os.path.join(font_path, "NanumGothic.ttf"), 40)
draw_text('μ§κ΅¬λ₯Ό μ§μΌλΌ!', font_70, screen, draw_x, draw_y, YELLOW)
draw_text('μν° ν€λ₯Ό λλ₯΄λ©΄', font_40, screen, draw_x, draw_y + 200, WHITE)
draw_text('κ²μμ΄ μμλ©λλ€.', font_40, screen, draw_x, draw_y + 250, WHITE)
# draw_text('νκ΄΄ν μ΄μ : {}'.format(shot_count), default_font, screen, 100, 20, YELLOW) # νκ΄΄ν μ΄μ νμ
pg.display.update()
# κ²μ μ΅κ³ μ
# μ΄ νλ©΄ λ΄μμ λ°μμ€λ ν€ κ°μ μ΄λ²€νΈ μ²λ¦¬
for event in pg.event.get():
if event.type == pg.KEYDOWN:
if event.key == pg.K_RETURN: # K_RETURN = μν° κ°
return 'play'
if event.type == QUIT: # κ²μ μ’
λ£
return 'quit'
return 'game_menu'
# κ²μ μ
ν
def main():
global screen
pg.init() # μ΄κΈ°ν
screen = pg.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # νλ©΄ μ
ν
.set_mode
pg.display.set_caption('PyShooting') # νλ©΄ μ΄λ¦
action = 'game_menu'
while action != 'quit': # λ§μ½μ action μ΄ quit μ΄ μλλ©΄
if action == 'game_menu': # λ§μ½μ action μ΄ κ²μ λ©λ΄μ΄λ©΄
action = game_menu()
elif action == 'play': # μλλΌλ©΄ action μ΄ νλ μ΄ λΌλ©΄
action = game_loop() # κ²μ μν
pg.quit()
# main μ μ€νμν€κΈ° μν΄ __name__ μ΄ __main__ μΌ κ²½μ°μ
if __name__ == "__main__":
main() # main() μ μ€ν μμΌλΌ > κ²μ μ
ν
μ μν
'π¦ λ΄μΌλ°°μμΊ ν > TIL(Today I Learned)' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
TIL_220428_μΈμ€ν λ°μ€ν¬ν UI ν΄λ‘ (0) | 2023.01.01 |
---|---|
TIL_220427 (0) | 2023.01.01 |
TIL_220425 (0) | 2023.01.01 |
TIL_220422_λ―Έλ ν νλ‘μ νΈ (0) | 2023.01.01 |
TIL_220421_λ―Έλ ν νλ‘μ νΈ (1) | 2023.01.01 |
λΉμ μ΄ μ’μν λ§ν μ½ν μΈ
μμ€ν κ³΅κ° κ°μ¬ν©λλ€