오늘은 pygame을 가지고 간단한 게임들을 만들어 보는 개인 프로젝트가 시작되었다.
필수 구현 사항으로
- 파이썬 GUI 프로그램 개발 라이브러리인 Pygame을 활용
- 이미지 리소스 삽입해보기
- (중요) 게임의 이기고 지는 규칙 설계/구현
- 현재 게임의 진행 상태 표시
- Stage별로 난이도 설정(1,2,3 / Easy, Normal, Hard)
- (선택) 제한시간 기능
- 마우스, 키보드 이벤트 처리(사용자 입력, 멈춤 기능)
- 이벤트 처리 꼭 해보기
우선 어느정도까지 만들 수 있는지 감이 전혀 잡히질 않아 pygame 튜토리얼을 따라서 전체적으로 사용되는 내장함수와 그에 따른 사용방법들을 익혀나갔다.
우선 두가지의 게임을 튜토리얼과 완전히 동일하게 따라해서 클론코딩을 한번 해보니 약간 감이 잡히는 듯 하다.
다른 것 보다도 위의 필수사항들을 다 넣어서 만들 수 있을 만한 게임을 기획해야하는데 아직 정확히 뭘 할지는 모르겠다.
일단 이어서 있는 RPG 튜토리얼까지 진행해보고 만들어본 소스를 적당히 가져와서 원하는 게임을 만들어보도록해야겠다.
pygame 튜토리얼 사이트
https://coderslegacy.com/python/pygame-platformer-game-development/
Pygame Platformer - Game Development - CodersLegacy
Welcome to the Pygame Platformer Game development! In this section, we'll be building a 2D Platformer game using the Python game library, Pygame. First...
coderslegacy.com
음향 다운로드 사이트
뮤팟 홈 | 프리미엄 배경음악 뮤팟
유튜버와 음원 저작권자를 연결하는 음악단지 뮤팟(Mewpot) 메인 페이지 입니다. 뮤팟에서 유튜브 영상에 들어갈 다양한 음악을 찾아보세요.
www.mewpot.com
오늘 클론 코딩한 게임 두가지
1. 장애물 피하기 게임(똥피하기)
# pygame 필수 import
import pygame, sys
from pygame.locals import *
# random, time 클래스 사용을 위한 import
import random
import time
# pygame 시작을 위한 초기화
pygame.init()
# 프레임 수 설정 너무 과할 경우 과부하 올 수 있기때문에 반드시 설정
FPS = 60
FramePerSec = pygame.time.Clock()
# 색깔들을 전역 변수로 선언하여 추후 사용
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
# 화면 구성 가로, 세로 길이
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
#추가 게임 설정
SPEED = 5 # 난이도 증가를 위한 변수
SCORE = 0 # 점수 측정을 위한 변수
# 출력할 글자의 폰트 설정
font = pygame.font.SysFont("Verdana", 60) # 큰 폰트 설정
font_small = pygame.font.SysFont("Verdana", 20) # 작은 폰트 설정
game_over = font.render("Game Over", True, BLACK) # 게임오버 문구 설정
# 이후에 font 와 font_small은 해당 폰트를 적용하여 출력할 때 .render("출력할 문구", True, 글자색)함수 호출하여 사용함
# 배경에 넣을 이미지 설정
background = pygame.image.load("AnimatedStreet.png")
# 화면 설정
DISPLAYSURF = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) #화면 출력 및 크기 설정
DISPLAYSURF.fill(WHITE) # 화면 배경 색 지정
pygame.display.set_caption("Game") # 타이틀 제목 설정
# 적 클래스 정의 (클래스 정의 시 주는 파라매터는 고정)
class Enemy(pygame.sprite.Sprite):
# 적 이미지 로드 및 등장 위치 설정 함수
def __init__(self):
super().__init__()
# 적 이미지 로드
self.image = pygame.image.load("Enemy.png")
# 이미지 크기의 직사각형 불러오기 즉 이미지랑 실제위치랑 동기화
self.rect = self.image.get_rect()
# 이미지 시작 위치 설정 (가로 픽셀 위치만 random클래스 이용하여 무작위 위치 선정, 세로는 0으로 설정하여 맨위에 위치)
self.rect.center = (random.randint(40, SCREEN_WIDTH - 40), 0)
# 적 움직임 설정
def move(self):
global SCORE
# 적을 10픽셀-> SPEED만큼 아래로 떨어지게 설정 SPPED 변수로 난이도 변경가능
self.rect.move_ip(0, SPEED)
# 적이 맨아래에 도달했을때 사각형의 아래쪽의 위치가 600픽셀보다 더 아래로 내려갔을때
if (self.rect.bottom > 600):
# 스코어 1점 올리기
SCORE += 1
# 사각형의 위쪽의 위치를 0으로 (맨위로) 설정
self.rect.top = 0
# 사각형의 중심 즉 사각형의 위치를 랜덤으로 설정
self.rect.center = (random.randint(30, 370), 0)
# 화면에 출력하는 함수 (스프라이트들을 그룹화하게 되면서 쓸모없어짐)
# def draw(self, surface):
# surface.blit(self.image, self.rect)
# 플레이어 클래스 정의
class Player(pygame.sprite.Sprite):
# 플레이어 이미지로드 및 등장 위치 설정
def __init__(self):
super().__init__()
# 플레이어 이미지 로드
self.image = pygame.image.load("Player.png")
# 플레이어 이미지에 맞게 사각형 생성
self.rect = self.image.get_rect()
# 플레이어 위치 설정
self.rect.center = (160, 520)
# 플레이어 움직임 설정
def move(self):
# 키를 눌렀을때
pressed_keys = pygame.key.get_pressed()
# 위로 움직임
# if pressed_keys[K_UP]:
# self.rect.move_ip(0, -5)
# 아래로 움직임
# if pressed_keys[K_DOWN]:
# self.rect.move_ip(0,5)
# 왼쪽으로 움직임
if self.rect.left > 0: # 사각형의 왼쪽 좌표가 0 보다 클때 즉 왼쪽 끝인지 아닌지 판별
# 눌러진 키가 왼쪽버튼일 때
if pressed_keys[K_LEFT]:
# 사각형을 왼쪽으로 5픽셀만큼 움직인다.
self.rect.move_ip(-5, 0)
# 오른쪽으로 움직임
if self.rect.right < SCREEN_WIDTH: # 사각형의 오른쪽 좌표가 설정한 화면의 가로 크기보다 작을때 즉 오른쪽 끝인지 아닌지 판별
# 눌러진 키가 오른쪽버튼일 때
if pressed_keys[K_RIGHT]:
# 사각형을 오른쪽으로 5픽셀만큼 움직인다.
self.rect.move_ip(5, 0)
# 화면에 출력하는 함수 (스프라이트들을 그룹화하게 되면서 쓸모없어짐)
# def draw(self, surface):
# surface.blit(self.image, self.rect)
# 플레이어와 적 인스턴스 생성
P1 = Player()
E1 = Enemy()
# 충돌 판정 생성을 위한 스프라이트 그룹화
# enemies 스프라이트 그룹 선언
enemies = pygame.sprite.Group()
# enemies 그룹안에 적 인스턴스를 추가하여 적으로 지정
enemies.add(E1)
# 모든 스프라이트 그룹 선언
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
all_sprites.add(E1)
# 이벤트 생성
# pygame.USEREVENT 의 값은 24이며 기본적으로 1~23까지는 pygame에서 사전정의된 이벤트가 이미 있다. 추가로 생성을 위해서 +1을 달아주는 거고
# 최대 32까지 9개의 이벤트만 생성이 가능하다.
INC_SPEED = pygame.USEREVENT + 1
# 타이머 기능을 이용하여 1000밀리초, 즉 1초마다 INC_SPEED를 호출하도록 함
pygame.time.set_timer(INC_SPEED, 1000)
while True:
for event in pygame.event.get():
# 생성한 이벤트 활성화 (1초마다 속도가 2픽셀씩 증가)
if event.type == INC_SPEED:
SPEED += 0.5
if event.type == QUIT:
pygame.quit()
sys.exit()
# P1.update()
# E1.move()
DISPLAYSURF.fill(WHITE)
# 스프라이트 그룹화를 하여서 출력하기때문에 따로 별도로 그려줄 필요없다
# P1.draw(DISPLAYSURF)
# E1.draw(DISPLAYSURF)
# 게임중인 화면 설정
# background 변수에 저장한 이미지 파일 불러와서 배경화면으로 변경
DISPLAYSURF.blit(background, (0, 0))
# 스코어를 화면에 출력하기 위해서 앞서 선언한 SCORE 변수를 가져와 font_small로 render함
scores = font_small.render(str(SCORE), True, BLACK)
# 스코어 점수를 화면 좌표 10,10에 출력함 (왼쪽 맨위)
DISPLAYSURF.blit(scores, (10, 10))
# 모든 스프라이트들의 움직임과 재생성
for entity in all_sprites:
DISPLAYSURF.blit(entity.image, entity.rect) # 모든 스프라이트들의 이미지와 사각형 생성
entity.move() # 오버라이딩 된 move() 함수를 각각의 스프라이트들이 공통적으로 호출함
# 플레이어와 적과의 충돌 판정
# spritecollideany(일반객체,스프라이트그룹)함수가 P1객체와, enemies 스프라이트 그룹과 겹치는지를 판별해줌
# 이 기능으로 각 객체별로 충돌판정을 달아줄 필요없이 충돌판정이 필요한 아이들을 그룹으로 묶어주기만하면된다.
if pygame.sprite.spritecollideany(P1, enemies):
# 충돌 시 사운드 출력
pygame.mixer.Sound('crash.mp3').play()
# 0.5초간 정지 후
time.sleep(0.5)
# 화면이 회색으로 바뀐다.
DISPLAYSURF.fill(GRAY)
# game_over 변수에 저장된 GAME OVER 문구를 해당 위치에 출력
DISPLAYSURF.blit(game_over, (30, 250))
pygame.display.update()
# all_sprites에 포함된 모든 스프라이트들을 없앤다.
for entity in all_sprites:
entity.kill()
# 2초 동안 정지 후
time.sleep(2)
# 프로그램 종료
pygame.quit()
sys.exit()
pygame.display.update()
FramePerSec.tick(FPS)
이 게임은 이미지를 뭘 넣느냐에 따라 그냥 단순하게 제목을 지을 수 가 있기때문에 장애물 피하는 게임인지라 딱히 바꿀건 없고 추가할 거는 음향을 넣는다던지 재시작, 멈춤, 메뉴같은 걸 만들면 되겠다
2. 플랫포머 게임(무한의 계단)
#pygame 필수 import
import pygame
from pygame.locals import *
import sys
import random
import time
# pygame 초기화
pygame.init()
#벡터 사용을 위한 함수 호출하여 변수 선언
vec = pygame.math.Vector2 # 2 for two dimensional
#화면 크기 지정 상수
HEIGHT = 450
WIDTH = 400
# ACC상수 와 FRIC 라는 변수 를 보셨을 것 vec입니다.
# 이것들은 뒷부분에서 사실적인 움직임을 만들고 중력을 구현하는 데 사용할 것입니다.
ACC = 0.5 # 가속도 올릴수록 빨라짐
FRIC = -0.12 # 음수 값이 커질 수록 느려짐 = 마찰이 심해짐 0에 가까워질수록 잘 미끄러짐
FPS = 60
#시계 설정
FramePerSec = pygame.time.Clock()
# 화면 설정
displaysurface = pygame.display.set_mode((WIDTH, HEIGHT))
# 게임 타이틀 설정
pygame.display.set_caption("Game")
# 플레이어 클래스 생성
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 플레이어 캐릭터 모양 생성
# self.surf = pygame.Surface((30, 30))
# 플레이어 이미지 로드
self.surf = pygame.image.load("player.png")
self.surf = pygame.transform.scale(self.surf,(30, 30))
# 플레이어 캐릭터의 색상 지정
self.surf.fill((255, 255, 0))
# 플레이어 캐릭터의 시작 위치 지정
self.rect = self.surf.get_rect(center=(WIDTH / 2, HEIGHT - 10))
#첫 번째 매개변수는 가속도/속도를 나타내고
# 두 번째 매개변수 X axis는 Y axis. center 매개변수를 제거했습니다.
# 이는 플레이어의 위치 제어를 self.pos변수로 이동했기 때문입니다.
# 다음은 move()플레이어를 제어할 수 있는 기능입니다.
self.pos = vec((10, 360))
self.vel = vec(0,0)
self.acc = vec(0,0)
# 플레이어가 점프 위치에 있는지 여부를 결정
self.jumping = False
# 스코어 점수 최초 값 생성 및 초기화
self.score = 0
def move(self):
# 첫번째 파라미터는 수평 가속도를 나타내고 두번재 파라미터는 수직 가속도를 나타낸다.
# 여기서 우리가 하고 있는 것은 플레이어에게 0.5의 영구적인 수직 가속도를 제공하는 것입니다.
# 다시 말해서, 우리는 일정한 중력을 만들었습니다. 0.5의 값은 변경이 가능하다.
self.acc = vec(0, 0.5)
# 가속도 0으로 설정
# self.acc = vec(0, 0)
# 키눌림 확인
pressed_keys = pygame.key.get_pressed()
# 왼쪽이 눌려졌을 경우 가속도가 음수으로 설정됨
if pressed_keys[K_LEFT]:
self.acc.x = -ACC
# 오른쪽이 눌려졌을 경우 가속도가 양수로 설정됨
if pressed_keys[K_RIGHT]:
self.acc.x = ACC
# 가속도 설정 변수의 값 FRIC을 조정하여 미끄러짐 마찰의 정도를 조정할 수 있다.
self.acc.x += self.vel.x * FRIC
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
# 화면 양끝으로 갈 경우 반대쪽으로 나오게하는 코드
# 물론 이 기능을 원하지 않는 경우 두 개의 if 문을 다른 용도로 사용하고 전체 코드를 둘러싸서 화면에서 벗어나지 않도록 할 수 있습니다.
# 아래 코드가 아예 없을 경우 객체가 그냥 화면 밖으로 나가버림
# 못나가게 막으려면 if문 하나에 두개 똑같이 WIDTH WIDTH 넣거나 0 0 넣으면 됨
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
# 이동 후 새 위치로 Player 객체 업데이트 하는 코드
self.rect.midbottom = self.pos
# 플랫폼에 착지 할 수 있도록 하는 메서드
def update(self):
# P1(플레이어)와, platforms 그룹에 포함된 스프라이트가 부딪혔을때 충돌 여부 return (마지막 파라매터는 삭제여부 이기때문에 False)
hits = pygame.sprite.spritecollide(self, platforms, False)
# 무한 점프 방지 코드 가속도가 1이라도 있으면 안되게
if self.vel.y > 0:
if hits:
# 플레이어의 y 포지션이 플랫폼 바닥위로 올라가지않을 때까지 착륙이 등록되지 않도록함
if self.pos.y < hits[0].rect.bottom:
# 스코어 증가 코드
# 방금 착지한 플랫폼의 포인트 속성을 확인한다.
# 플랫폼이 생성될 때 기본 point값이 True로 설정되어있으므로 속성을 확인하여 True일 경우
# 점수를 상승 시키고 point의 값을 False로 바꿔주는 것
# 이렇게 하면 플레이어가 같은 플랫폼으로 계속해서 점프하여 점수를 얻는 것을 방지할 수 있습니다.
if hits[0].point == True: ##
hits[0].point = False ##
self.score += 100
# 첫번째 코드를 사용하여 Player의 속도를 0으로 설정해야 합니다 self.vel.y = 0. 수직 속도만 0으로 설정했습니다.
# 그렇지 않으면 플랫폼에서 수평으로 이동할 수 없습니다
self.vel.y = 0
# 두번째, 플랫폼의 상단 y 좌표 self.pos.y 로 변수를 업데이트하여 플랫폼 상단에 플레이어를 재배치합니다 .
self.pos.y = hits[0].rect.top + 1
# 수직방향 가속도가 있는 상태면 점프 불가능
self.jumping = False
# 점프 하는 메서드 위로 올라가기때문에 플레이어 객체에 수직속도 값을 음수 값을 줘야함
# 그리고 버튼을 눌렀을 때 해당 메서드를 호출
def jump(self):
# 무한 점프 방지 코드 바닥과 붙어 있는지 확인
hits = pygame.sprite.spritecollide(self, platforms, False)
if hits and not self.jumping:
self.jumping = True
self.vel.y = -15
# 점프 메커니즘을 수정하기 위한 메서드 정의
# 소점프 기능(스페이스바를 떼면은 실행되는 메서드 플레이어의 속도를 줄이는 목적의 메서드)
def cancel_jump(self):
if self.jumping:
if self.vel.y < -3:
self.vel.y = -3
class platform(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# # 플랫폼의 모양 생성
# self.surf = pygame.Surface((WIDTH, 20))
# # 플랫폼의 색상 지정
# self.surf.fill((255, 0, 0))
# # 플랫폼의 시작 위치 지정
# self.rect = self.surf.get_rect(center=(WIDTH / 2, HEIGHT - 10))
# 가로 길이가 50 ~ 100 픽셀의 플랫폼을 랜덤 생성
self.surf = pygame.Surface((random.randint(50, 100), 12))
# 플랫폼의 색상 지정
self.surf.fill((0, 255, 0))
# 플랫폼의 생성 위치 지정
self.rect = self.surf.get_rect(center=(random.randint(0, WIDTH - 10),
random.randint(0, HEIGHT - 30)))
# 플랫폼 움직임 무작위 방향(왼쪽,오른쪽,가만히) 설정 및 활성화
self.speed = random.randint(-1, 1)
self.moving = True
# 플랫폼에 대한 "포인트" 속성을 생성하여 플레이어가 플레이어에게 착지할 경우
# 플랫폼에서 포인트를 줄 것인지 여부를 결정합니다. 참이면 예, 거짓이면 아니요.
self.point = True
#플랫폼 움직임 메서드 정의
def move(self):
# 플레이어와 플랫폼의 충돌확인
hits = self.rect.colliderect(P1.rect)
# 플랫폼이 움직임이 활성화되어있을때 (Base 플랫폼때문에 활성화여부 구분)
if self.moving == True:
# self.speed의 방향대로 이동하는데
self.rect.move_ip(self.speed, 0)
# 충돌이 있을 경우 플레이어의 속도도 플랫폼이 움직이고 있는 속도와 같아지도록 설정
if hits:
P1.pos += (self.speed, 0)
# 각각의 플랫폼이 화면끝으로 갈 경우 반대편으로 나오도록하는 것
if self.speed > 0 and self.rect.left > WIDTH:
self.rect.right = 0
if self.speed < 0 and self.rect.right < 0:
self.rect.left = WIDTH
# 코인 생성 메서드 정의
# 멈춰있는 플랫폼 위에 코인을 생성하고 이를 코인 그룹에 추가하는 역할을 합니다.
def generateCoin(self):
if (self.speed == 0):
coins.add(Coin((self.rect.centerx, self.rect.centery - 50)))
# 코인 클래스 정의
class Coin(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
# 코인 이미지 불러오기
self.image = pygame.image.load("Coin.png")
self.image = pygame.transform.scale(self.image, (20, 20))
# 코인에 사각형 판정 만들기
self.rect = self.image.get_rect()
self.rect.topleft = pos
def update(self):
if self.rect.colliderect(P1.rect):
P1.score += 5
self.kill()
# 플랫폼들이 서로 모여 있지 않도록 하는 check() 메서드 정의
# 이 함수는 새로 생성된 플랫폼을 입력으로 사용하고
# 모든 플랫폼이 저장되는 "groupies"라는 Sprite 그룹을 사용합니다.
# 현재 이 새로 생성된 플랫폼은 Sprite 그룹에 그려지거나 추가되지 않았습니다.
# 이 검사를 통과한 경우에만 추가됩니다.
def check(platform, groupies):
# 충돌 판정 확인 충돌나면 True 리턴
if pygame.sprite.spritecollideany(platform,groupies):
return True
# 충돌은 아니지만 근처에 있을 경우 파악
else:
for entity in groupies:
# 새로 생성될 groupies에서 나온 entity 객체들 중
# 각각의 플랫폼의 간격을 50px 을 보장하기 위한 코드
if entity == platform:
continue
# 절대값을 이용하여 이미 생성되있는 플랫폼(platform)의 위쪽좌표와 생성될 플랫폼(entity)의 아래쪽 좌표의 차이 그리고
# 생성된 플랫폼(platform)의 아래쪽 좌표와 생성될 플랫폼(entity)의 위쪽 좌표 차이를 50으로 설정
if (abs(platform.rect.top - entity.rect.bottom) < 40) and (
abs(platform.rect.bottom - entity.rect.top) < 40):
return True
C = False
# 플랫폼 리젠 함수 정의
def plat_gen():
# 이 값은 초기 플랫폼 생성(5 – 6)에 대해 제공한 값보다 커야 합니다.
# 이 값이 초기 플랫폼 수보다 크지 않으면 플레이어가 HEIGHT / 3화면에 도달할 때까지 새 플랫폼이 생성되지 않습니다.
# 그 결과 플레이어와 다음 플랫폼 사이에는 한 번의 점프로 커버할 수 없는 큰 간격이 생깁니다.
while len(platforms) < 6:
# 새 플랫폼을 만드는 데 임의의 너비 할당 플랫폼의 다양성을 위해
width = random.randrange(50, 100)
p = None
C = True
# C 가 False를 반환하면 루프가 종료 되고 플랫폼이 그룹에 추가됨
while C:
p = platform()
# 화면의 보이는 부분 바로 위에 플랫폼을 만들고 배치합니다. 위치는 무작위 라이브러리 를 사용하여 무작위로 생성됩니다 .
p.rect.center = (random.randrange(0, WIDTH - width),
random.randrange(-50, 0))
C = check(p, platforms)
# 생성된 플랫폼 스프라이트 그룹에 추가
p.generateCoin() # <----------------
platforms.add(p)
all_sprites.add(p)
# 정의한 클래스의 객체 생성
PT1 = platform()
P1 = Player()
# Base 플랫폼 움직임 비활성화
PT1.moving = False
# Base 플랫폼에서 포인트 기능을 비활성화합니다.
PT1.point = False
# platform()함수를 재정의하여서 바닥플랫폼이 없기때문에 따로 정의해준 것
PT1.surf = pygame.Surface((WIDTH, 20))
PT1.surf.fill((255, 0, 0))
PT1.rect = PT1.surf.get_rect(center=(WIDTH / 2, HEIGHT - 10))
# 생성한 모든 객체들을 스프라이트 그룹에 포함
all_sprites = pygame.sprite.Group()
all_sprites.add(PT1)
all_sprites.add(P1)
# platforms 스프라이트 그룹 생성 및 플랫폼 객체들 해당 그룹에 추가
platforms = pygame.sprite.Group()
platforms.add(PT1)
# coins 스프라이트 그룹 생성
coins = pygame.sprite.Group()
# 게임 초기 레벨 생성
for x in range(random.randint(5, 6)):
C = True
pl = platform()
while C:
pl = platform()
C = check(pl, platforms)
# 생성된 플랫폼 스프라이트 그룹에 추가
pl.generateCoin() # <----------------
platforms.add(pl)
all_sprites.add(pl)
while True:
# P1.move() move()함수 platform 클래스에도 만들어 준다음 그룹화한 스프라이트 한번에 불러오기에 코드추가하고 지우기
P1.update()
# 모든 이벤트 처리 코드
for event in pygame.event.get():
# 윈도우창 종료 버튼 클릭 시 정상종료 되도록하는 코드
if event.type == QUIT:
pygame.quit()
sys.exit()
# 스페이스바 눌렸을 때 확인해서 jump()함수 호출
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
P1.jump()
# 스페이스바 키를 뗐을 때 확인해서 cancel_jump() 함수 호출
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
P1.cancel_jump()
# # 키눌림 확인
# pressed_keys = pygame.key.get_pressed()
# if pressed_keys[K_w]:
# P1.jump()
# 화면 무한 스크롤
# 화면에 대한 플레이어의 위치 확인
# 언제 화면을 이동 시킬지에 대해서 결정하는 지점
# 화면크기, 플레이어 속도 등을 고려하여 적절한 위치로 선정해야함
# 플레이어가 해당 위치에 도달할 때마다 안의 코드가 실행됨
if P1.rect.top <= HEIGHT / 3:
# 화면은 더이상 동적개체가 아니므로 화면이 이동함에 따라 플레이어의 위치도 업데이트 해줘야함
# abs()함수를 사용하여 속도 값에서 음수 부호 제거 (abs()함수는 파라미터로 받은 수의 절대값을 반환하는 함수)
P1.pos.y += abs(P1.vel.y)
# 다른 플랫폼들도 위치를 업데이트 하기 위해서 abs()함수 이용하여 음수 부호 제거
for plat in platforms:
plat.rect.y += abs(P1.vel.y)
# 플랫폼의 위치가 바닥에서 화면을 벗어나는 모든 플랫폼들을 파괴하는 코드
# 이 줄이 없으면 플랫폼들이 계속 메모리에 쌓여 게임속도가 느려짐!
if plat.rect.top >= HEIGHT:
plat.kill()
# 마찬가지로 코인들도 위치를 업데이트 하기 위해서 abs() 함수 이용하여 음수 부호 제거
for coin in coins:
coin.rect.y += abs(P1.vel.y)
if coin.rect.top >= HEIGHT:
coin.kill()
# 루프 내 플랫폼 리젠 함수 실행
plat_gen()
# 배경화면 검은색으로 0, 0, 0 대신에 미리 상수로 선언했을경우 BLACK 으로 적어도됨
displaysurface.fill((0, 0, 0))
# 스코어 화면 출력
# 파이게임에서 High Score 디스플레이용 글꼴을 만든 다음 렌더링합니다.
f = pygame.font.SysFont("Verdana", 20) ##
g = f.render(str(P1.score), True, (123, 255, 0)) ##
displaysurface.blit(g, (WIDTH / 2, 10)) ##
# 코인 그룹을 반복하고 렌더링 및 업데이트를 위해 매 프레임마다 메서드 호출
for coin in coins:
displaysurface.blit(coin.image, coin.rect)
coin.update()
# 게임 오버 화면 구현
if P1.rect.top > HEIGHT:
for entity in all_sprites:
entity.kill()
time.sleep(1)
displaysurface.fill((128, 128, 128))
pygame.display.update()
time.sleep(1)
pygame.quit()
sys.exit()
#그룹화한 모든 스프라이트를 한번에 불러오기
for entity in all_sprites:
displaysurface.blit(entity.surf, entity.rect)
entity.move()
pygame.display.update()
FramePerSec.tick(FPS)
플랫폼 게임을 완전히 코드를 따라해서 작성하였는데도 불구하고 한번씩 플랫폼이 새로 생성될때 게임자체가 뻑이나는 버그가있다. 완전히 뻑나버려서 플랫폼 생성 시에 뭔가 문제가 있다는 것은 알겠지만 정확한 디버깅이 어려워 해결은 못하더라도 일단 레퍼런스로 사용해야 할 것 같다.
'회고록(TIL&WIL)' 카테고리의 다른 글
TIL & WIL 2022.04.29 인스타그램 클론코딩 - 2 (0) | 2022.04.29 |
---|---|
TIL 2022.04.28 인스타그램 클론코딩 - 1 (0) | 2022.04.28 |
TIL 2022.04.27 - pygame을 이용한 게임만들기 - 3 & git 특강 (0) | 2022.04.27 |
TIL 2022.04.26 pygame을 이용한 게임만들기 - 2 (2) | 2022.04.26 |
WIL_2022.04.22~2022.4.24 (0) | 2022.04.23 |