프로젝트 개요
- pygame을 사용하여 Pixel Runner 제작
- Youtube Clear Code의 The ultimate introduction to Pygame을 따라하며 진행
- 주요 과제: python과 pygame의 사용에 익숙해지는 것
프로젝트 내용
Default Setting
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800, 400))
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
pygame.display.update()
clock.tick(60)
Pixel Runner
- pygame 내의 sprite class를 사용해 게임 완성
import pygame
from sys import exit
from random import randint, choice
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
player_walk1 = pygame.image.load('graphics/Player/player_walk_1.png').convert_alpha()
player_walk2 = pygame.image.load('graphics/Player/player_walk_2.png').convert_alpha()
self.player_walk = [player_walk1, player_walk2]
self.player_index = 0
self.player_jump = pygame.image.load('graphics/player/jump.png').convert_alpha()
self.image = self.player_walk[self.player_index]
self.rect = self.image.get_rect(midbottom = (80, 300))
self.gravity = 0
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.1)
def player_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
self.gravity = -20
self.jump_sound.play()
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300: self.rect.bottom = 300
def animation_state(self):
if self.rect.bottom < 300: self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk): self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
def update(self):
self.player_input()
self.apply_gravity()
self.animation_state()
class Obstacle(pygame.sprite.Sprite):
def __init__(self, type):
super().__init__()
if type == 'fly':
fly_1 = pygame.image.load('graphics/Fly/Fly1.png').convert_alpha()
fly_2 = pygame.image.load('graphics/Fly/Fly2.png').convert_alpha()
self.frames = [fly_1, fly_2]
y_pos = 210
else:
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1, snail_2]
y_pos = 300
self.animation_index = 0
self.image = self.frames[self.animation_index]
self.rect = self.image.get_rect(midbottom = (randint(900, 1100), y_pos))
def animation_state(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames): self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
def destroy(self):
if self.rect.x <= -100: self.kill()
def update(self):
self.animation_state()
self.rect.x -= 5
self.destroy()
def display_score():
current_time = int(pygame.time.get_ticks() / 500) - start_time
score_surf = game_font.render(f'SCORE: {current_time}', False, (64, 64, 64))
score_rect = score_surf.get_rect(center = (400, 50))
screen.blit(score_surf, score_rect)
return current_time
def collide_sprite():
if pygame.sprite.spritecollide(player.sprite, obstacle_group, False):
obstacle_group.empty()
return False
else: return True
pygame.init()
screen = pygame.display.set_mode((800, 400))
pygame.display.set_caption('Pixel Runner')
clock = pygame.time.Clock()
game_active = False
score = 0
start_time = 0
player = pygame.sprite.GroupSingle()
player.add(Player())
obstacle_group = pygame.sprite.Group()
sky_surf = pygame.image.load('graphics/Sky.png').convert()
ground_surf = pygame.image.load('graphics/ground.png').convert()
game_font = pygame.font.Font('font/Pixeltype.ttf', 50)
game_name = game_font.render('Pixel Runner', False, (64, 64, 64))
game_name_rect = game_name.get_rect(center = (400, 50))
game_message = game_font.render('Press space to run', False, (111, 196, 169))
game_message_rect = game_message.get_rect(center = (400, 330))
player_walk1 = pygame.image.load('graphics/Player/player_walk_1.png').convert_alpha()
player_walk2 = pygame.image.load('graphics/Player/player_walk_2.png').convert_alpha()
player_walk = [player_walk1, player_walk2]
player_index = 0
player_jump = pygame.image.load('graphics/player/jump.png')
player_surf = player_walk[player_index]
player_rect = player_surf.get_rect(midbottom = (80, 300))
player_gravity = 0
player_stand_surf = pygame.image.load('graphics/Player/player_stand.png').convert_alpha()
player_stand_surf = pygame.transform.rotozoom(player_stand_surf, 0, 2)
player_stand_rect = player_stand_surf.get_rect(center = (400, 200))
snail_frame1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_frame2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
snail_frames = [snail_frame1, snail_frame2]
snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
fly_frame1 = pygame.image.load('graphics/Fly/Fly1.png').convert_alpha()
fly_frame2 = pygame.image.load('graphics/Fly/Fly2.png').convert_alpha()
fly_frames = [fly_frame1, fly_frame2]
fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, 1500)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
if event.type == obstacle_timer:
obstacle_group.add(Obstacle(choice(['fly', 'snail', 'snail', 'snail'])))
else:
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
start_time = int(pygame.time.get_ticks() / 500)
if game_active:
screen.blit(sky_surf, (0, 0))
screen.blit(ground_surf, (0, 300))
player.draw(screen)
player.update()
obstacle_group.draw(screen)
obstacle_group.update()
game_active = collide_sprite()
score = display_score()
else:
screen.fill((94, 129, 162))
screen.blit(player_stand_surf, player_stand_rect)
screen.blit(game_name, game_name_rect)
score_message = game_font.render(f'YOUR SCORE: {score}', False, (111, 196, 169))
score_message_rect = score_message.get_rect(center = (400, 330))
if score == 0: screen.blit(game_message, game_message_rect)
else: screen.blit(score_message, score_message_rect)
pygame.display.update()
clock.tick(60)
![](https://velog.velcdn.com/images/sh97818/post/10c4fdb3-9296-4d35-88ed-af154a3ab8f5/image.gif)
KEEP
- 게임을 제작하는 동시에 파이썬의 기본 문법에 많이 익숙해지면서 코드를 작성하고 구현하는 시간이 줄어들고 전체적인 구조를 파악하는 능력이 향상됨을 느낌
- pygame을 사용해 게임을 만들 경우, default setting과 sprite class를 사용함에 있어 그 사용법과 예시를 잘 기억해야함을 느낌
PROBLEM
- 아무리 간단한 게임이어도 직접 기획하고 디자인한 게임이 아니다보니 게임 내에서 물리적 요소를 구현하기 위해 정의한 함수들을 이해하는데에 시간이 많이 소요됨
- 게임의 몇가지 이벤트들을 구성하는 것에 있어서 다소 복잡하다고 느낌
TRY
- Clear Code에서 업로드한 영상들을 보며 다른 게임 제작과정과 python을 활용한 간단한 툴 개발 등을 계속해서 시도
- 물리적 요소를 구현하기 위한 함수작성 시 미리 생각해보고 진행
-알고리즘 작성 능력 향상을 위해 문제들 풀어보기