python/python_pygame

pygame 기초

몽자비루 2023. 3. 22. 01:05
##1 환경설정 & 프레임

######################################################################
# 무조건 해야하는 부분
######################################################################
import pygame
#1 초기화 (반드시 필요.) 
pygame.init()

#1 화면 크기 설정
screen_width = 480 # 가로 크기
screen_height = 640 # 세로 크기
screen = pygame.display.set_mode((screen_width, screen_height))

#1 화면 타이틀 설정
pygame.display.set_caption("rusharp Game") # 게임 이름

######################################################################
# 사용자 게임 초개화 (배경화면, 게임이미지, 좌표, 속도, 폰트 등)
######################################################################

##2 배경 이미지 불러오기
background = pygame.image.load("경로\\background.png")

##3 캐릭터(스프라이트) 불러오기
character = pygame.image.load("경로\\character.png")
#3 캐릭터 사이즈를 가져옴 (가로/세로 크기)
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
#3 캐릭터가 움직일수 있는 가로/세로 범위
character_x_pos = (screen_width-character_width)/2
character_y_pos = screen_height-character_height

## 4 키보드 이벤트
#4 이동할 좌표
to_x = 0
to_y = 0

#5 이동속도
character_speed = 0.3

##5 FPS
# 프레임 수가 높을수록 부드럽다.
clock = pygame.time.Clock()

##6 충돌 처리
#6 적 (enemy) 캐릭터
enemy = pygame.image.load("경로\\enemy.png")
#6 캐릭터 사이즈를 가져옴 (가로/세로 크기)
enemy_size = enemy.get_rect().size
enemy_width = enemy_size[0]
enemy_height = enemy_size[1]
#6 캐릭터가 움직일수 있는 가로/세로 범위
enemy_x_pos = (screen_width-enemy_width)/2
enemy_y_pos = (screen_height-enemy_height)/2

##7 텍스트
#7 폰트 정의 : 폰트 객체 생성, (폰트, 크기)
game_fond = pygame.font.Font(None, 40)
total_time = 10
#7 시작 시간 정보를 받아옴.
start_ticks = pygame.time.get_ticks()

#1 이벤트 루프
#1 화면이 켜지자마자 꺼지지 않도록 함.
running = True # 게임이 진행중인가?
while running:
    #5 게임화면의 초당 프레임수를 설정함.
    dt = clock.tick(60)

    ######################################################################
    # 이벤트 처리 (키보드, 마우스 등)
    ######################################################################

    #1 사용자로부터 키보드/마우스 이벤트가 들어오는 지 체크함.
    #1 들어온다면 액션에 맞는 이벤트를 진행함. 
    for event in pygame.event.get():
        #1 여러 이벤트 중 들어온 이벤트가 QUIT이라면 runnig 은 False
        #1 창이 닫히는 이벤트가 발생하였는지 확인함.
        if event.type == pygame.QUIT:
            running = False
        
        #4 키보드가 눌렸는지 확인.
        if event.type == pygame.KEYDOWN:
            #4 캐릭터를 왼쪽으로
            if event.key == pygame.K_LEFT:
                to_x -=character_speed
            #4 캐릭터를 오른쪽으로
            elif event.key == pygame.K_RIGHT:
                to_x +=character_speed
            #4 캐릭터를 위쪽으로
            elif event.key == pygame.K_UP:
                to_y -=character_speed
            #4 캐릭터를 아래쪽으로
            elif event.key == pygame.K_DOWN:
                to_y +=character_speed
        #4 키보드에서 손을 떼면
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                to_y = 0
    
    #4 이 부분이 for문 안에 들어가있으면 키 입력마다 작동하고
    #4 이 부분이 for문 밖에 들어가있으면 연속 키누름에도 작동됨

    #5 캐릭터가 1초에 100만큼 이동해야할 떄,
    #5 10fps : 1초동안 10번 동작 > 1번에 10만큼 이동해야함
    #5 20fps : 1초동안 20번 동작 > 1번에 5만큼 이동해야함.
    #5 즉, 이동하는 곳에 dt를 곱하면 frame 관계없이 속도가 일정함.
    character_x_pos +=to_x*dt
    character_y_pos +=to_y*dt

    #4 가로 경계값 처리
    if character_x_pos < 0 : 
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width:
        character_x_pos = screen_width - character_width

    #4 세로 경계값 처리
    if character_y_pos < 0 : 
        character_y_pos = 0
    elif character_y_pos > screen_height - character_height:
        character_y_pos = screen_height - character_height

    #6 충돌 처리
    #6 실제로 캐릭터 자체의 rect 이미지는 처음 호출한 위치에 고정되어 있다.
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos

    enemy_rect = enemy.get_rect()
    #6 직접적으로 enemy_rect 에 반영된 것이 아니기 때문에 직접 업데이트해야함.
    enemy_rect.left = enemy_x_pos
    enemy_rect.top = enemy_y_pos

    #6 충돌 체크
    #6 colliderect : Rect와 자신에게 겹침이 있는지 없는지(충돌)를 반환
    if character_rect.colliderect(enemy_rect):
        print("충돌했어요")
        running = False

    #2 원하는 rgb색상으로 화면을 채움.
    #2 screen.fill((0,0,255))
    #2 원하는 이미지(background)가 0.0 좌표를 시작으로 배경을 그려줌.
    screen.blit(background, (0,0))
    
    #3 캐릭터를 그려줌.
    screen.blit(character, (character_x_pos, character_y_pos))
    
    #6 적을 그려줌.
    screen.blit(enemy, (enemy_x_pos, enemy_y_pos))

    #7 타이머 집어넣기
    #7 경과시간을 1000으로 나누어서 초단위로 표시
    elspsed_time = (pygame.time.get_ticks() - start_ticks)//1000
    # timer 에 GUI에서 열 수 있는 텍스트를 삽입함(character 처럼)
    timer = game_fond.render(str(total_time - elspsed_time),True, (0,0,0))

    #7 만약 시간이 0 이하이면 게임 종료
    if total_time - elspsed_time <=0:
        timer = game_fond.render("Time out",True, (0,0,0))
        running = False

    screen.blit(timer, (10,10))

    # #7 만약 시간이 0 이하이면 게임 종료
    # if total_time - elspsed_time <=0:
    #     print("타임아웃")
    #     running = False
    
    #2 게임 화면을 다시 그리기
    #2 아래 내용이 없는 경우, 화면이 한번 보여지고 바로 초기화(검정)됨.
    pygame.display.update()

#7 종료 직전 잠시 대기할 수 있는 코드
pygame.time.delay(2000)

#1 pygame 종료
pygame.quit()

 

  1. 환경설정 & 프레임
    1. pygame.init(): pygame의 초기화
    2. screen = pygame.display.set_mode((x, y)) : 창을 x y 크기로 바꿈.
      ㄴ screen.blit(객체, (x, y))로 x y 위치에 객체를 띄움.
    3. pygame.display.set_caption("게임이름") : 타이틀바의 텍스트를 설정한다.
    4. while running: 이벤트 루프를 통해 명시적으로 종료시킴.
    5. for event in pygame.event.get() : 입력받은 값을 event에 in하게됨.
    6. event.type == pygame.QUIT : 닫기 버튼을 누르면
    7. pygame.quit() : 게임을 종료함.
  2. 배경
    1. background = pygame.image.load(”경로”) :
      경로의 파일을 이미지로 불러와 background 변수에 삽입.
    2. 객체.blit(background, (x,y)) : 객체를 x,y좌표에 출력함.
    3. pygame.display.update() : 화면이 계속 업데이트 되도록 다시 그림
      ㄴ 추가로 display.flip()는 전체, display.update()는 특정부분만 업데이트.
  3. 캐릭터
    1. pygame의 전역 변수 중 size를 통해 객체의 크기를 가져올 수 있음.
      ㄴ size = 객체.get_rect().size 를 통해 객체의 가로, 세로를 tuple로 가져옴
  4. 키보드 이벤트
    1. event.type == pygame.KEYDOWN : 키보드를 눌렀을 때
      ㄴ event.type : 발생한 이벤트 종류를 나타내는 문자열.
    2. event.key == pygame.K_LEFT/K_RIGHT/K_UP/K_DOWN : 왼/오/위/아래
      ㄴ event.key : 키보드의 키릘 나타내는 값
    3. 객체가 화면 밖으로 넘어가지 않도록 가로/세로 경계값 설정
  5. FPS
    1. pygame.time.Clock : 시간 추적 개체 생성
    2. clock.tick(n) : 프레임 당 한번씩 호출해야 함
      ㄴ 이전 호출 이후 몇 밀리 초가 경과했는지 계산
      ㄴ 초당 틱보다 느리게 실행되도록 지연해 프레임이 n을 초과하지 않음
    3. frame관계없이 이동속도를 동일하게 하고싶은 경우,
      이동속도 x 초당 프레임수 (clock.tick(n)) 를 하면 된다.
  6. 충돌 처리
    1. 충돌처리를 위해서는 어떠한 객체의 실시간 위치를 받아와야 함
      ㄴ 객체의 rect 좌표는 처음 호출한 위치에 고정되어 있다.
      ㄴ 즉, 충돌처리를 위해선 객체.get_rect.left/top 을 주기적으로 갱신해야 함.
    2. 객채1.colliderect(객체2) : 객체2와 객체1의 겹침 여부를 반환함.
  7. 텍스트
    1. text = pygame.font.Font(폰트, 크기) : 폰트 객체를 생성.
    2. start_ticks = pygame.time.get_ticks() pygame.init() 가 호출 된 이후의 밀리 초 수를 반환 .
      파이 게임이 초기화되기 전에 항상 0이다
    3. pygame.time.get_ticks()-시작 시간으로 소요시간 계산(밀리초 단위)
    4. 폰트 객체.render(텍스트,antialias, color, background=None)
      ㄴ 텍스트를 blit하기 위해서 위를 통해 surface 객체로 변환해야 함.
      ㄴ 안티알리아싱 : 선을 부드럽게 만드는 그래픽 기법이다.
    5. pygame.time.delay(2000) : 대기할 수 있는 코드(밀리초 단위)