오늘은 pygame 모듈을 활용하여 슬라임 쪼개기 게임을 만들어 볼것 인데요. 이번 게임은 이전의 똥피하기 게임보다 좀더 어려우니 처음 pygame모듈을 다뤄 보시는 분은 똥피하기 게임을 먼저 만들어보시고 오는것을 추천드립니다. 그렇다면 먼저 어떤 게임을 만들지 구동 영상부터 보여드리겠습니다.

 

자 대충 어떤 형태로 게임이 구동되는지 아시겠죠? 방향키롤 캐릭터를 움직이고 스페이스 바로 무기를 발사하여 슬라임을 쪼갤 것 입니다.

원본 코드입니다. 직접 따라쓰면서 구동 원리를 공부하면 python 실력이 크게 늘 것입니다. 오늘은 여기까지 하겠습니다.

'python > 자료 구조' 카테고리의 다른 글

[Python] 똥 피하기 게임 만들기  (5) 2020.05.29
[Python] 파이썬 기초 | Python Foundation  (1) 2020.05.16

안녕하세요. 오늘은 수학과 프로그래밍을 결합한 주제를 한번 가지고 와 보았는데요. 제목에서도 보셨다시피 오늘은 파이를 구해보려고 합니다. 파이는 다른 말로 원주율이라고 하고 원둘레와 지름의 비를 나타내는 상수입니다. 이는 어떤 원을 그려도 같은 값을 나타내므로 우리는 이를 π라는 기호를 나타내 종종 표현합니다. 그래서 오늘은 이 파이를 직접 구해보려고 합니다. 사실 파이를 구하는 것은 여러가지 방법을 이용해 구할 수 있습니다. 그중에서 오늘은 도형과 확률의 개념을 이용한 구하기 코드를 구성해 보려고 합니다. 오늘 이 주제로 포스팅을 하게된 계기는 최근 제가 본 유튜브 영상 때문인데요. 작성일 기준 이틀전에 올라온 긱블의 영상을 보고 이러한 프로그램을 만들면 재밌겠다고 생각했습니다.

프로그램을 만들어보기 전에 영상을 보시는것을 추천드립니다.

 

다트 100개로 원주율(ㅠ)을 구하는 과학적인 내기-긱블(Geekble)

영상에서 보셨다시피 정사각형에 내접하는 원과 정사각형의 넓이의 비를 이용하여 파이를 구할 수 있다는 것을 알 수 있습니다.

영상을 보시지 않은 분들을 위해 간단히 설명드리자면 위의 그림처럼 정사각형이 있고 그에 내접하는 원이 있을 때, 원의 반지름의 길이를 r이라고 한다면 정사각형의 한변의 길이는 2r이고 정사각형의 넓이는 4r**2이고 원의 넓이는 r**2입니다. 이때 정사각형안에 랜덤하게 점을 무수히 찍는다고하면 (정사각형 안에 찍힌 점의 개수) : (원 안에 찍힌 점의 개수)는 (정사각형의 넓이) : (원의 넓이)가 됩니다. 이에 따라서 = 4*(원 안에 찍힌 점의 개수)/(정사각형 안에 찍힌 점의 개수)라는 식이 성립하게 되고 의 정확도는 수확적 확률과 통계적 확률의 관계에 따라 정사각형 안에 찍는 점의 개수가 늘어날수록 실제 에 수렴하게 됩니다.

지금까지 설명한 내용을 이용하여 코드를 구성하면 위와 같은 코드가 완성됩니다. 정사각형과 원을 그리고, 점을 찍을 좌표를 생성하고, 공식에 따라 파이를 구합니다. 위의 코드는 간단하므로 자세한 코드 설명은 생략하겠습니다. 마지막으로 프로그램 실행 영상을 보여주면서 마치겠습니다:D

 

 

오늘 만들어 볼 것은 python의 pygame모듈을 활용해서 간단한 똥 피하기 게임을 만들어 볼 것이다.

 

우리가 가장 먼저 해야 할 것은 pygame모듈을 import 하는 것이다. 

import pygame #

만약 pygame이 import되지 않거나 오류가 생긴다면 pygame모듈을 설치하지 않았거나 python interpreter가 pygame모듈이 설치되지 않은 경로로 선택되어 있을 가능성이 있다. 전자의 경우에는 pygame을 설치해주고, 후자의 경우에는 보통 anaconda와 같이 다른 python관련 프로그램이 설치되어 있는 경우가 많으니 확인해보자.

 

pygame모듈을 import한 후 우리는 pygame을 초기화해주어야 한다.

import pygame

pygame.init() #

위와 같이 pygame.init()함수를 이용하여 초기화해준다.

 

그 뒤 우리는 게임 실행 창의 크기를 설정해주어야 한다. 

import pygame

pygame.init()

background = pygame.image.load("background.png") #
pygame.display.set_caption("test pygame") #
screen_width = 480 #
screen_height = 640 #
screen = pygame.display.set_mode((screen_width,screen_height)) #

이 부분에서 screen_width와 screen_height를 사용하는 이유는 나중에 실행창의 크기를 바꿀 때 편리하게 하기 위해서이다. 필자는 480*640의 크기로 설정했지만 크기는 크게 상관이 없기 때문에 원하는 크기로 설정해 주면 된다. 그리고 게임의 제목도 임의로 설정해주었습니다. 그리고 background도 실행창과 알맞은 크기의 그림파일로 설정해줍니다.

 

이제 player를 생성해 주도록 하자. 이번에는 아주 단순한 게임을 만들 것이므로 70*70의 정사각형 모양으로 생성해 주도록 하겠다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

character = pygame.image.load("character.png") #
character_size = character.get_rect().size #
character_width = character_size[0] #
character_height = character_size[1] #
character_xpos = screen_width/2-character_width/2 #
character_ypos = screen_height - character_height #

그림판에서 70*70의 단색 이미지를 생성한 후 같은 폴더에 저장한다. 그리고 pygame.image.load("파일명")으로 player image를 불러온다. get_rect().size로 player의 크기를 구해준 후에 가로와 세로의 길이를 변수에 넣어준다. character_xpos, character_ypos는 캐릭터가 화면의 어느 지점에 위치할지 선언하는 변수로 사용되므로 그에 알맞게 지정하여 주면 되는데, 여기서 주의할 점이 pygame에서의 좌표체계는 우리가 수학에서 일반적으로 사용하는 좌표체계와는 달라 조심해야 한다. pygame에서는 왼쪽 위가 (0,0)이고 오른쪽이 x좌표의 +방향, 아래쪽이 y좌표의 +방향이다. 우리는 player를 아래쪽에서만 움직이도록 하고 싶으므로 x좌표는 화면의 가운데로 설정해 주고, y좌표는 바닥에 위치하도록 한다. 이때 x좌표와 y좌표의 기준은 각각 물체의 왼쪽과 위쪽이므로 적절히 고려하여 설정해준다.

 

그다음으로 필요한 것은 똥 피하기 게임의 똥을 생성해주는 것이다. 똥 또한 70*70의 정사각형 모양으로 생성하겠다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg") #
poo_size = poo.get_rect().size #
poo_width = poo_size[0] #
poo_height = poo_size[1] #
poo_xpos = 0 #
poo_ypos = poo_height #

똥을 생성하는 것은 player와 거의 같기 때문에 자세한 설명은 생략하도록 하겠다.

 

이제 기본적인 설정은 거의 끝 마쳤으므로 게임을 실행하기 위한 실행 구역을 생성해 주겠다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

running = True #
while running: #
  ~~~게임을 구동할 코드가 들어가게 될 부분~~~

이제 닫기 버튼을 클릭했을 때, 실행창을 종료하도록 해야 한다. 이 작업을 해주지 않으면 게임을 실행해도 실행창이 바로 닫히게 된다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

running = True
while running:
  for event in pygame.event.get(): #
    if event.type == pygame.QUIT: #
      running = False #

추가된 코드는 입력받은 이벤트 중 닫기 이벤트가 있으면 running변수를 False로 바꿔주어 실행 구역을 벗어나도록 해준다. 

 

다음으로 pygame에 내장되어 있는 기능을 사용하여 player를 조작할 수 있도록 하겠다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

clock = pygame.time.Clock() #
character_speed = 0.5 #
to_x = 0 #
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 #
      if 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 #
  character_xpos += to_x * dt #
      

to_x 변수는 x좌표가 얼마나 이동할지를 나타내는 변수이다. 이 값을 현재의 x좌표값에 더하여 player를 이동시키는 방식이다. KEYDOWN 이벤트는 키가 눌렸을 때를 말하고 반대로 KEYUP 이벤트는 키가 눌렸다가 다시 올라가는 것을 말한다. 여기서 새롭게 dt라는 변수와 character_speed라는 변수를 추가한 이유는 게임을 실행할 때의 프레임을 고정해주고, 캐릭터의 이동속도를 바꿀 때 좀 더 편하게 바꾸기 위해서이다. 캐릭터의 속도는 직접 플레이해보고 적당히 바꾸는 것을 추천한다. 

 

직접 따라 해 보셨다면 알아채셨을 테지만 이렇게 코딩을 하더라도 게임창에는 아무것도 보이지 않습니다. 그 이유는 화면을 업데이트해주지 않았기 때문인데요. 이제 그 작업을 해주도록 하겠습니다.

import pygame

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  screen.blit(background,(0,0)) #
  screen.blit(character,(character_xpos,character_ypos)) #
  pygame.display.update() #
   

화면을 업데이트할 때 주의해야 할 점이 blit명령어를 사용하는 순서이다. blit명령어는 네가 사용하는 순서대로 화면에 덧칠하는 방식이기 때문에 character를 먼저 blit 하고 background를 그 후에 blit 한다면 backround에 가려 character를 볼 수 없게 된다.

 

다음은 똥이 위에서부터 떨어지는 것을 구현해 보도록 하겠다. 먼저 똥은 x축의 좌표가 랜덤 하게 정해져야 하고, 한프레임마다 조금씩 떨어져야한다. x축의 좌표를 랜덤하게 설정하기 위해 random 라이브러리를 import 해줘야 한다. 그리고 random 함수를 사용하여 똥의 x좌표를 화면에서 벗어나지 않도록 설정해주고, y좌표도 초기 값을 설정해 줍니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  if poo_ypos >= screen_height + 70 or poo_ypos == 70: #
    poo_ypos =  poo_height #
    poo_xpos = random.uniform(0,screen_width - character_width) #
  
  screen.blit(background,(0,0)) 
  screen.blit(character,(character_xpos,character_ypos))
  pygame.display.update() 

이렇게 설정해 주면 똥의 x좌표는 화면 내에서 설정되지만, y좌표가 화면 밖으로 설정되어 보이지 않습니다. 이제 똥이 아래로 조금씩 떨어지도록 해주어야 합니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

poo_speed = 1 #
clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  if poo_ypos >= screen_height + 70 or poo_ypos == 70:
    poo_ypos =  poo_height
    poo_xpos = random.uniform(0,screen_width - character_width)
  
  poo_ypos += poo_speed #
  poo_speed += 0.01 #
  
  screen.blit(background,(0,0)) 
  screen.blit(character,(character_xpos,character_ypos))
  screen.blit(poo,(poo_xpos,poo_ypos)) #
  pygame.display.update() 

위와 같이 설정해주어 똥이 한 프레임마다 조금씩 떨어지도록 하고 시간이 지날수록 poo_speed가 빨라져 더 빨리 떨어지도록 해줍니다. 그리고 똥도 blit 해주어 화면에 나타나도록 합니다. 여기서 좌표를 설정하는 코드를 if 문안에 넣은 이유는 똥이 화면에서 아래쪽으로 벗어나거나 게임을 처음 시작한 상황에서만 새로 지정해 주어야하기 때문입니다. 그렇지 않으면 똥의 위치가 한 프레임마다 계속하여 지정될 것이기 때문에 정상적인 게임이 실행되지 않습니다.

 

이제 어느 정도 대략적인 기능들이 구현이 되었는데요. 하지만 아직도 중요 기능 중 구현되지 않은 것들이 있습니다. 첫째로 캐릭터가 화면 밖으로 이동할 수 있다는 것입니다. 그리고 똥과 충돌할 시 게임이 종료되는 기능을 구현해 주어야 합니다. 전자의 기능은 캐릭터의 x좌표를 고려하여 왼쪽으로 나가게 되면 x좌표를 0으로 설정해주어 그 자리를 유지하게 하고, 오른쪽으로 나가게되면 x좌표를 screen_width - character_width로 설정해주어 화면을 벗어나지 못하도록 해주겠습니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

poo_speed = 1
clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  if character_xpos < 0: #
    character_xpos = 0 #
  elif character_xpos > screen_width - character_width: #
    character_xpos = screen_width - character_width #
  if character_ypos < 0: #
    character_ypos = 0 #
  elif character_ypos > screen_height - character_height: #
    character_ypos = screen_height - character_height #
  if poo_ypos >= screen_height + 70 or poo_ypos == 70:
    poo_ypos =  poo_height
    poo_xpos = random.uniform(0,screen_width - character_width)
  
  poo_ypos += poo_speed
  poo_speed += 0.01
  
  screen.blit(background,(0,0)) 
  screen.blit(character,(character_xpos,character_ypos))
  screen.blit(poo,(poo_xpos,poo_ypos))
  pygame.display.update() 

 

이제 거의 다 왔습니다. 충돌 시 게임이 끝나는 기능을 구현할 차례인데요. 이 기능은 colliderect 함수를 사용하여 구현할 것인데요. 이 함수는 두 rect가 충돌하였는지 아닌지를 알려줍니다. 그래서 character와 poo를 get_rect함수를 사용하여 rect객체를 생성해 주고 이 두 rect가 충돌하였는지 아닌지에 따라 게임을 계속 실행할지의 여부를 결정해주도록 하겠습니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

poo_speed = 1
clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  if character_xpos < 0:
    character_xpos = 0
  elif character_xpos > screen_width - character_width:
    character_xpos = screen_width - character_width
  if character_ypos < 0:
    character_ypos = 0
  elif character_ypos > screen_height - character_height:
    character_ypos = screen_height - character_height
  if poo_ypos >= screen_height + 70 or poo_ypos == 70:
    poo_ypos =  poo_height
    poo_xpos = random.uniform(0,screen_width - character_width)
  
  poo_ypos += poo_speed
  poo_speed += 0.01
  
  character_rect = character.get_rect() #
  character_rect.left = character_xpos #
  character_rect.top = character_ypos #

  poo_rect = character.get_rect() #
  poo_rect.left = poo_xpos #
  poo_rect.top = poo_ypos #

  if character_rect.colliderect(poo_rect): #
    running = False #
  
  screen.blit(background,(0,0)) 
  screen.blit(character,(character_xpos,character_ypos))
  screen.blit(poo,(poo_xpos,poo_ypos))
  pygame.display.update() 

만약 두 rect가 충돌하면 running을 False로 설정하여 실행 구역을 벗어나 게임을 종료합니다. 

 

자, 여기까지 게임을 실행하기 위한 모든 기능을 구현해 보았습니다. 방향키로 character를 조종하고, 똥을 피해 게임을 지속할 수 있습니다. 하지만 모든 게임에는 score가 있어야죠. 마지막으로 score를 화면에 띄우는 것 까지 구현을 하고 마치도록 하겠습니다.

 

score는 게임의 지속시간으로 하겠습니다. 게임의 지속시간을 알기 위해서는 게임이 처음 실행된 시간과 게임이 실행되고 있는 현재의 시간을 알아야 합니다. 이는 get_ticks 함수를 사용하도록 하겠습니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

start_ticks = pygame.time.get_ticks() #

game_font = pygame.font.Font(None,40)

poo_speed = 1
clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
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
      if 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
  character_xpos += to_x * dt
  
  if character_xpos < 0:
    character_xpos = 0
  elif character_xpos > screen_width - character_width:
    character_xpos = screen_width - character_width
  if character_ypos < 0:
    character_ypos = 0
  elif character_ypos > screen_height - character_height:
    character_ypos = screen_height - character_height
  if poo_ypos >= screen_height + 70 or poo_ypos == 70:
    poo_ypos =  poo_height
    poo_xpos = random.uniform(0,screen_width - character_width)
  
  poo_ypos += poo_speed
  poo_speed += 0.01
  
  character_rect = character.get_rect()
  character_rect.left = character_xpos
  character_rect.top = character_ypos

  poo_rect = character.get_rect()
  poo_rect.left = poo_xpos
  poo_rect.top = poo_ypos

  if character_rect.colliderect(poo_rect):
    running = False
    
  current_time = pygame.time.get_ticks() #
  elapsed_time = ( current_time - start_ticks )/1000 # 
  timer = game_font.render(str(int(elapsed_time)),True,(255,255,255)) #
  
  screen.blit(background,(0,0)) 
  screen.blit(character,(character_xpos,character_ypos))
  screen.blit(poo,(poo_xpos,poo_ypos))
  screen.blit(timer,(10,10))
  pygame.display.update() 

pygame에서 화면에 글씨를 띄워주려면 render함수를 사용해야 하므로 game_font를 설정하여 적당한 위치에 띄워 주었습니다. 이렇게 하면 게임 중 왼쪽 위에 score가 뜨게 됩니다. 하지만 게임 종료 시에도 자신의 score를 확인할 수 있도록 하기 때문에 코드를 좀 더 추가하도록 해주겠습니다.

 

while running블록 전체를 while _running블록으로 감싸주고 _running을 True로 설정해 줍니다. 그리고 background를 검은색으로 설정하고 점수를 적절한 위치에 표시하였습니다. 마지막으로 닫기 버튼을 누르면 _running을 False로 설정해 주도록 하여 게임을 종료할 수 있도록 해주면 정말 끝입니다.

import pygame
import random

pygame.init()

background = pygame.image.load("background.png")
pygame.display.set_caption("test pygame")
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))

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

poo = pygame.image.load("poo.jpg")
poo_size = poo.get_rect().size
poo_width = poo_size[0]
poo_height = poo_size[1]
poo_xpos = 0
poo_ypos = poo_height

start_ticks = pygame.time.get_ticks()

game_font = pygame.font.Font(None,40)

poo_speed = 1
clock = pygame.time.Clock()
character_speed = 0.5
to_x = 0
running = True
_running = True #

while _running: #
  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
        if 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
    character_xpos += to_x * dt

    if character_xpos < 0:
      character_xpos = 0
    elif character_xpos > screen_width - character_width:
      character_xpos = screen_width - character_width
    if character_ypos < 0:
      character_ypos = 0
    elif character_ypos > screen_height - character_height:
      character_ypos = screen_height - character_height
    if poo_ypos >= screen_height + 70 or poo_ypos == 70:
      poo_ypos =  poo_height
      poo_xpos = random.uniform(0,screen_width - character_width)

    poo_ypos += poo_speed
    poo_speed += 0.01

    character_rect = character.get_rect()
    character_rect.left = character_xpos
    character_rect.top = character_ypos

    poo_rect = character.get_rect()
    poo_rect.left = poo_xpos
    poo_rect.top = poo_ypos

    if character_rect.colliderect(poo_rect):
      running = False

    current_time = pygame.time.get_ticks()
    elapsed_time = ( current_time - start_ticks )/1000 
    timer = game_font.render(str(int(elapsed_time)),True,(255,255,255))

    screen.blit(background,(0,0)) 
    screen.blit(character,(character_xpos,character_ypos))
    screen.blit(poo,(poo_xpos,poo_ypos))
    screen.blit(timer,(10,10))
    pygame.display.update()
  
  score_font = pygame.font.Font(None,50) #
  text = score_font.render("Your score is",True,(255,255,255)) #
  text_rect =text.get_rect() #
  timer_rect = timer.get_rect() #
  screen.fill((0,0,0)) #
  screen.blit(timer,(10,50)) #
  screen.blit(text,(10,10)) #
  pygame.display.update() #
  for event in pygame.event.get(): #
    if event.type == pygame.QUIT: #
      _running = False #

pygame.quit()

 

자, 정말로 간단한 똥 피하기 게임이 완성되었습니다. 그렇다면 어떻게 구동이 되는지 제 화면을 녹화하여 보여드리겠습니다.

 

이렇게 제 글을 따라오면서 똥피하기 게임을 완성하신 분들에게 먼저 감사하다는 말씀을 드리고요. 어떻게 보면 별거 아닐 수도 있지만 직접 무언가를 만들어 보면서 새로운 것을 배우는 것에 두려움을 느끼지 않으셨으면 좋겠습니다. 새로운 것을 배운다는 것은 지식의 새로운 대륙을 발견하는 것이라고 생각하기 때문입니다. 새로운 것을 배우면 배울수록 더욱 새로운 것이 나타나고 더욱 흥미로운 것들을 발견할 수 있습니다. 제 글을 끝까지 따라와 주신 분들께 감사하다는 말씀을 드리면서 다음에 더 유익하고 재밌는 글로 찾아뵙겠습니다. :D

 

github : https://github.com/kidkio/avoiding-poo

1. 변수란 무엇인가?

정보를 넣을 수 있는 공간이다.

a = "Hello Wolrd"
print(a) # 결과 : Hello World

위의 코드에서 a라는 변수에 "Hello World"라는 문자가 대입된 것을 볼 수 있다.

 

2. 자료형이란 무엇인가?

파이썬의 자료형은 여러 가지가 있는데 이번에는 integer, float, string, list, dictionary 정도만 보려고 한다.

 

1. integer(정수형)

정수를 나타내는 자료 형태이다. ex) 1,10,100 등

 

2. float(실수형)

소수점까지 표현할 수 있는 자료 형태이다. ex) 1.1, 3.14 등

 

3. string(문자열 자료형)

문자를 표현할 수 있는 자료 형태이다. ex) Hello World, apple 등

 

4. boolean(참/거짓)

참/거짓을 나타내는 자료형이다. ex) True, False

 

5. list

정보를  나열하여 저장할 수 있는 자료 형태이다. ex) ["apple", "pineapple"]

 

6. dictionary(사전)

정보를 key와 value를 짝지어 저장하는 자료 형태이다. ex) {"name":"kidkio", "age':18}
#integer
_integer = 1

#float
_float = 3.14

#string
_string = "apple"

#boolean
_boolean = True

#list
_list = [1, 2, "yellow", True]

#dictionary
_dictionary = {"name":"kidkio","age":18}​

 

3. 제어문이란 무엇인가?

 

1. if문

조건에 따라 실행/미실행 여부를 제어하는 문법이다.
a = 5
if (a==5):
  print("OK!")
# 결과 : OK!

 

2. for문

블록 내의 실행을 주어진 리스트나 횟수만큼 반복하는 문법이다.
a = [1,2,3,4,5]
for i in a:
  print(a)
# 결과 : 1 2 3 4 5

 

3. while문

주어진 조건을 충족시키는 동안 블록 내의 실행을 반복하는 문법이다.
a = 1
while(a<5):
  print(a)
  a += 1 # a = a + 1
# 결과 : 1 2 3 4

 

4. 함수란 무엇인가?

자주 사용하는 동작을 묶어 하나의 함수로 만드는 문법이다.
def hello(name):
  print(f"Hello {name}")
hello(kidkio) # 결과 : Hello kidkio

+ Recent posts