import pygame as pg
import random
# 이미지 초기화
def 스프라이트_생성(이미지):
스프라이트 = pg.sprite.Sprite()
스프라이트.image = 이미지
스프라이트.rect = 스프라이트.image.get_rect()
return 스프라이트
pg.init()
# 게임 기본 설정
실행여부 = True
화면가로길이, 화면세로길이 = 800, 450
화면 = pg.display.set_mode([화면가로길이, 화면세로길이])
pg.display.set_caption('동족을 노역장에서 구출하라!')
배경이미지 = pg.image.load('img/배경.png')
배경이미지 = pg.transform.scale(배경이미지, (화면가로길이, 화면세로길이))
개리점프이미지 = pg.image.load('img/개리-뛰는-모습5(점프).png')
개리점프이미지 = pg.transform.scale(개리점프이미지, (100, 100))
개리착지이미지 = pg.image.load('img/개리-뛰는-모습6(착지).png')
개리착지이미지 = pg.transform.scale(개리착지이미지, (100, 100))
개리뛰기이미지리스트 = [pg.image.load(f'img/개리-뛰는-모습{인덱스}.png') for 인덱스 in range(1, 5)]
for 인덱스 in range(len(개리뛰기이미지리스트)):
개리뛰기이미지리스트[인덱스] = pg.transform.scale(개리뛰기이미지리스트[인덱스], (100, 100))
개리스프라이트 = 스프라이트_생성(개리뛰기이미지리스트[0])
돌이미지 = pg.image.load('img/돌.png')
돌이미지 = pg.transform.scale(돌이미지, (100, 100))
# 게임 요소 초기화
게임여부 = True
개리시작높이 = 255
개리뛰기상태 = 0
개리뛰는흐름 = 1
개리동작업데이트시간 = 0
점프기본속도 = 0.1
점프속도 = 점프기본속도
점프상태 = False
개리위치 = [70, 개리시작높이]
요소들속도 = 300
돌멩이생성시간 = 1
돌멩이시작높이 = 280
돌멩이위치리스트 = [[500, 돌멩이시작높이]]
돌멩이스프라이트리스트 = [스프라이트_생성(돌이미지) for _ in 돌멩이위치리스트]
시계 = pg.time.Clock()
while 실행여부:
if 게임여부:
화면.blit(배경이미지, (0, 0))
# 게임 시간 계산
경과시간 = 시계.tick(60) / 1000
개리스프라이트.rect.x, 개리스프라이트.rect.y = 개리위치[0], 개리위치[1]
화면.blit(개리스프라이트.image, 개리스프라이트.rect)
for 돌멩이위치, 돌멩이스프라이트 in zip(돌멩이위치리스트, 돌멩이스프라이트리스트):
돌멩이스프라이트.rect.x, 돌멩이스프라이트.rect.y = 돌멩이위치[0], 돌멩이위치[1]
화면.blit(돌멩이스프라이트.image, 돌멩이스프라이트.rect)
if pg.sprite.collide_mask(개리스프라이트, 돌멩이스프라이트) != None:
게임여부 = False
돌멩이위치[0] -= 요소들속도 * 경과시간
if 돌멩이위치[0] < -100:
돌멩이스프라이트리스트.remove(돌멩이스프라이트)
돌멩이위치리스트.remove(돌멩이위치)
# 개리 점프
if 점프상태:
개리스프라이트.image = 점프속도 > 0 and 개리점프이미지 or 개리착지이미지
개리위치[1] -= 점프속도 * 경과시간 * 1000
점프속도 -= 점프기본속도 * 경과시간 * 2
if 개리위치[1] >= 개리시작높이:
개리위치[1] = 개리시작높이
점프상태 = False
점프속도 = 점프기본속도
else:
개리동작업데이트시간 += 경과시간
if 개리동작업데이트시간 > 0.2:
개리동작업데이트시간 = 0
개리스프라이트.image = 개리뛰기이미지리스트[개리뛰기상태]
개리뛰기상태 += 개리뛰는흐름
if 개리뛰기상태 == len(개리뛰기이미지리스트) - 1 or 개리뛰기상태 == 0:
개리뛰는흐름 *= -1
돌멩이생성시간 -= 경과시간
if 돌멩이생성시간 <= 0:
돌멩이스프라이트리스트.append(스프라이트_생성(돌이미지))
돌멩이위치리스트.append([900, 돌멩이시작높이])
돌멩이생성시간 = random.random() * 2 + 1
for 이벤트 in pg.event.get():
if 이벤트.type == pg.QUIT:
실행여부 = False
elif 이벤트.type == pg.KEYDOWN:
if 게임여부 and 이벤트.key == pg.K_SPACE and not 점프상태:
점프상태 = True
pg.display.update()
pg.display.quit()
2. 상세 설명
2-1. 구현 방식(정리)
충돌 구현 이전에 충돌하면 게임을 멈추가 위해서 게임여부 만들고 게임여부에 따라 게임이 진행되도록 합니다.
돌멩이 위치를 업데이트 하는 로직에 충돌 로직을 추가합니다.
점프를 담당하는 이벤트 쪽도 게임여부에 따라 점프할 수 있도록 변경합니다.
2-2. 구현
if 게임여부:
게임여부 : 게임여부 변수가 False상태가 되면 그리는 작업과 위치 업데이트 작업을 멈춥니다.
if pg.sprite.collide_mask(개리스프라이트, 돌멩이스프라이트) != None:
게임여부 = False
pg.sprite.collide_mask(스프라이트, 스프라이트) 함수를 통해 두 개의 객체들의 충돌을 체크합니다.
충돌 체크 함수는 collide_rect, collide_circle, collide_mask의 3가지 함수가 있습니다.(ratio가 들어간 비율 체크도 있지만 사용하지 않으므로 생략합니다.)
collide_rect : 스프라이트의 rect 객체에 저장된 좌표와 크기를 통하여 충돌을 체크합니다.(이걸 사용할 시에는 캐릭터와 시각적으로는 충돌되지 않아도 충돌이 일어날 수 있습니다.)
collide_circle : 스프라이트의 center 좌표와 width를 통하여 충돌 체크를 합니다.
collide_mask : 그림의 실제 색체를 가지고 충돌을 체크합니다.(그림의 빈 부분은 충돌 체크에서 제외됩니다.) 위의 2개의 함수(결과값이 논리값)와 달리 충돌지점이 존재하면 좌표(튜플)를 반환하고 없으면 None입니다. 그리고 연산량이 많으므로 속도가 좀 느립니다.