기본 콘텐츠로 건너뛰기

[pygame] Cannon 게임 프로젝트 4 - 스프라이트 기본

 제작로그 4 - 스프라이트 기본 

스프라이트는 화면에 움직이는 오브젝트들(캐릭터들?) 이라고 생각하면 됩니다. 제가 만드는 게임이라면 총알이라던가 적 캐릭터라던가 하는것들입니다. 

pygame 에는 스프라이트 클래스가 준비되어 있고 중요한 기능중 하나는 캐릭터 간의 충돌체크 입니다. 

충돌체크는 다음에 다루기로 하고 여기서는 간단히 스프라이트 이용의 기본 내용만 보겠습니다. 

import pygame
from robot import *
 
SCREEN_X = 800    #게임창 x 크기
SCREEN_Y = 600    #게임창 y 크기
 
screen = pygame.display.set_mode((SCREEN_X,SCREEN_Y)) #게임 윈도우 생성
background = pygame.Surface(screen.get_size())        #게임 화면을 그릴 surface
pygame.init() #pygame 초기화
robot_image = pygame.image.load('robot.png').convert_alpha() #이미지를 로드하고 변환
robot_image = pygame.transform.scale(robot_image,(40,40)) #이미지의 크기 변환
robot = Robot(robot_image,300,300)    #Robot 스프라이트 객체 생성
done=True
 
while done:        #이 루프를 벗어나면 게임이 종료됨
    ev = pygame.event.get()
    for event in ev:
        if event.type ==pygame.QUIT:     #창의 종료버튼이 눌렸을때 게임종료
            done = False     
        if event.type == pygame.MOUSEMOTION:    #마우스의 위치 얻음
            robot.rect.center = pygame.mouse.get_pos() #마우스 위치를 center 에 넣음
        break
 
    #적과 아군 캐릭터 표현. 점수 표현은 이곳에서
    background.fill((0,0,0))    #화면 지움
    background.blit(robot.image , robot.rect) #로봇캐릭터 표시
 
    screen.blit(background,(0,0)) #background 의 화면을 스크린에 복사
    pygame.display.flip()         #화면에 표시함

화면에 Robot 을 표시하고 마우스를 움직이면 마우스 포인터를 따라 Robot 이 그려지는 예제 입니다.

>

Robot 클래스는 다음과 같습니다. 

import pygame
class Robot(pygame.sprite.Sprite):
    def __init__(self,img,x,y):
        super().__init__()
        self.image = img    #스프라이트 이미지 surface
        self.rect = img.get_rect()  #이미지의 rect 구해서 저장
        self.rect.center = (x,y)    #캐릭터 위치 좌표
        self.mask = pygame.mask.from_surface(img) #충돌체크용 마스크 생성
        self.vecpos = pygame.math.Vector2(x,y)  #벡터 값 저장
        self.x = x
        self.y = y
        self.alive = 1  #로봇의 상태

Robot 클래스는 pygame 의 스프라이트 클래스를 상속받아 만듭니다. Vector2 클래스는 실제 이 게임의 robot 의 움직임에 쓰이지 않기는 하는데 만약에 쓰일 일이 있을까 싶어서 넣어둔 것입니다. 

다른건 보시면 대충 아실거고 중요한건 rect.center 와 pygame.mask.from_surface(img) 부분입니다. 

mask 생성은 스프라이트의 충돌체크에 쓰이기 때문에 꼭 넣어주어야 합니다. 이는 다음의 충돌체크부분에서 이야기 하도록 하겠습니다.

>

background.blit 함수 부분을 보면 robot 클래스의 image 와 rect 를 인자로 넣었는데 sprite 클래스의 rect 에는 center 라는 변수가 존재합니다. 만일 center 변수에 값이 없으면 rect의 x,y 값을 좌표로 사용합니다. 

일반적으론 게임에서는 center 변수를 이용하는게 좋은데 왜냐하면 center 의 좌표가 캐릭터의 중심이 되기 때문입니다. 


위는 center 변수를 사용하지 않았을때인데 캐릭터가 상단 왼쪽위치를 중심으로 그려지는걸 알 수 있습니다. 

 

center 변수에 값을 넣어주면 위와 같이 그려집니다. 마우스 포인터를 중심으로 하여 캐릭터를 그려주는 걸 확인 할 수 있습니다. 

소스에서는 "robot.rect.center = pygame.mouse.get_pos()" 의 방법으로 마우스를 움직였을때 마우스 포인터의 위치 값을 Robot 클래스의 rect.center 에 넣어줌으로서 마우스 포인터의 위치를 중심으로 캐릭터를 그리도록 하고 있습니다.  

>

"pygame.image.load('robot.png').convert_alpha()" 부분은 캐릭터인 Robot 의 이미지를 로드하는 부분인데요. convert_alpha() 로 변환을 해주는게 중요합니다. 이미지의 투명부분인 알파채널 때문일걸로 생각됩니다. 

이 부분도 충돌체크에서 중요한 부분입니다. 저 투명부분은 충돌로 판정되지 않고 캐릭터 부분만 충돌로 판정되어야 하기 때문입니다.

 

위의 이미지는 gimp 에서 캐릭터 이미지를 로드 한것 입니다. 캐릭터인 초록색 부분을 제외한 체크 격자 부분이 바로 이미지의 투명한 부분 입니다. 충돌 체크시 저 부분은 충돌 체크에서 제외됩니다. 따라서 정확한 충돌체크를 할 수가 있습니다.

>

다음에 간단히 충돌체크를 적어 보겠습니다. 충돌체크 방법은 사각형, 원 등의 방법이 있지만 알파채널을 이용한 mask 방법만 적어 볼 생각입니다. 

 

댓글

이 블로그의 인기 게시물

pygame 에서 이미지 회전하는 방법

 pygame 에서 transform.rotate 를 사용해서 이미지를 회전시켜 보면 생각과는 달리 요상하게 회전합니다.    따라서 이를 해결해 보고자 검색해 보다 다음 링크를 찾았습니다. https://stackoverflow.com/questions/4183208/how-do-i-rotate-an-image-around-its-center-using-pygame/54714144 위 링크를 보면 파이게임의 이미지 회전이 왜 그렇게 이상한지 알 수 있고 답변하신 분이 blitRotate 라는 함수를 만들어 놓아서 이용할 수 있습니다.  제 소스에 가져와서 테스트를 해 봤는데 제 생각대로 회전 하더군요.  def blitRotate(image, pos, originPos, angle):       #calcaulate the axis aligned bounding box of the rotated image     w, h       = image.get_size()     box        = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]     box_rotate = [p.rotate(angle) for p in box]     min_box    = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])     max_box    = (max(box_rotate, key=lambda p: p[0])[0], max...

모닝 JA 엔진오일 교환. 보쉬필터 구입

요즘은 주행거리가 1만km 가 안되다보니 1년에 한번씩 엔진오일을 교환하고 있습니다.  1년에 한번이라 그냥 오토큐에서 교환을 했었지만 오토큐의 오일교환 가격이 너무 오른데다가 이젠 보증도 끝났기 때문에 오일과 필터를 구입해서 공임나라로 갔습니다.  > 오일은 kixx g1 fe 1L x 3 을 구입하고 필터는 보쉬제품으로 구입했습니다.   A3003 이 에어필터이고 O0356 이 오일필터 입니다. 기아의 순정부품보단 조금 가격이 저렴합니다.  > 오랜만에 공임나라 갔는데 교환공임이 17000원 이네요. 물가가 오른만큼 오일교환 비용도 예전보다 좀 올랐네요.  필터 품번도 기록해 둘겸 올려 봅니다. ^^;

antix linux 업데이트시 GPG Error

 최근에 가장 가벼운 리눅스를 검색해서 antix 리눅스를 설치해서 테스트 해 보고 있습니다. 역시 가볍긴 가볍더군요. 생각보단 패키지 구성도 괜찮아 보였고요.    설치후 좀 써보고 업데이트를 하는데 GPG Error 가 발생했습니다. GPG 키 관련 문제인것 같아서 검색해 보니 antixforum에 답이 있었습니다.  https://www.antixforum.com/forums/topic/how-to-fix-expired-gpg-key-error/   간단히 적어보자면... http://repo.antixlinux.com/bookworm/pool/main/a/antix-archive-keyring/antix-archive-keyring_20019.5.0_all.deb 위 파일을 받은 다음에 터미널에서... sudo dpkg -i antix-archive-keyring_20019.5.0_all.deb 을 실행해서 설치해 주면 됩니다.    그런다음 업데이트를 시도해 보면 잘 됩니다.