기본 콘텐츠로 건너뛰기

라벨이 pygame인 게시물 표시

[pygame] Cannon 게임프로젝트 7 - 사운드

 게임에서 사운드는 배경음악과 효과음 2가지가 있습니다. 이를 위해 pygame 에선 mixer 라이브러리를 제공합니다. > 사운드 기능을 사용하기 전에 해야 할 일은 초기화 입니다.  pygame.mixer.init 라는 함수가 있어 설정값을 주고 초기화 할 수있지만, 보통은 pygame.init() 를 사용하여 한번에 여러 라이브러리를 초기화 하는게 간단하고 편하기 때문에 보통 초기화는 다음과 같은 방법을 씁니다. pygame.mixer.pre_init(44100,-16,2,512)   pygame.init()    pygame.init() 전에 pre_init 로 초기화시 사용할 초기값을 미리 설정해 주는 것 입니다. 맨 마지막 인수가 buffer 값인데 예전에는 512 로 해 주지 않으면 효과음에 지연이 생겨서 넣어 줬던 것인데 최근 pygame 문서를 보면 기본값이 512 로 바뀌었더군요. 따라서 pre_init 를 해주지 않아도 될지도 모르겠지만 pygame 버전에 따른 차이가 생길 수 있으니 저는 그냥 명시적으로 넣어줍니다.    1. 배경음악 pygame.mixer.music 의 사용법은 간단합니다. pygame.mixer.music.load('bg.ogg') pygame.mixer.music.play() 하면 됩니다. load 함수에 리턴값 없이 그냥 저렇게 쓰면 됩니다. play 함수는 play(3) 처럼 반복 재생회수를 넣어줄 수 있으며 -1 이면 계속 반복 재생합니다. https://www.pygame.org/docs/ref/music.html  그 외에 다른 함수들은 위의 링크를 보면 됩니다. 영어 단어만 봐도 대충 무슨 함수인지 알 수 있습니다. rewind, stop, pause 같은 함수들입니다. 다만 몇가지만 설명해 드리자면....  > pygame.mixer.queue('xxx.ogg')  위의 queue 함수는 지금 재생...

gimp 로 이미지 배경 투명하게 만들기

gimp 는 free 그래픽툴로 윈도우에서도 사용가능하고, 리눅스에서는 왠만한 배포판에는 기본으로 설치되어 있습니다. 그래서 제 경우는 gimp 를 애용하는 편입니다.  >    예로 사용하기 위해 간단히 위의 이미지를 만들어 봤습니다. 배경이 흰색이면 사실 간단하지만...이런저런 이유로 일단 배경을 핑크하게 칠했습니다. 가운데가 게임 캐릭터라고 치고요. 그럼 저 핑크를 투명하게 설정해 보도록 하겠습니다.  >      위 스크린샷을 참고하여 "Color to Alpha" 메뉴를 선택합니다.    이 경우는 png 이미지라 이미 알파채널이 추가되어 있지만(따라서 메뉴에서 비활성화 되어 있습니다) 만일 알파채널이 없다면 그 위의 "알파채널 추가" 를 선택해서 알파채널을 추가 하고 진행을 해야 합니다. > 녹색 사각형으로 표시된 부분의 색이 투명색으로 바뀌게 됩니다. 기본적으로 흰색이 설정되어 있습니다. 하지만 우리가 투명으로 만들 부분은 핑크색입니다. 그 옆에 빨간 사각형으로 표시해 놓은 아이콘을 클릭후에 배경인 핑크색 부분을 클릭하세요.     >    핑크색이 설정되었고 이미지에서 핑크색 부분이 사라졌습니다. 설정이 끝났습니다. 그 아래에 두개의 슬라이드는 직접 조정해 보시면 뭔지 쉽게 아실 수 있습니다. 이 설정은 "OK" 를 눌러야 실제로 적용됩니다.    마지막으로 저장하실때는 반드시 알파채널을 저장 할 수 있는 png 로 저장하셔야 합니다.     >    그렇게 실제 만들어진 이미지가 바로 위의 이미지 입니다.  제대로 된 캐릭터를 그리실 수 있는 분 이라면 이 정도를 모를리가 없지만 pygame 을 연습삼아 써보려는 분들은 간단한 이미지라도 만들 수 있어야 하기 때문에 간단히 설명해 봤습니다. 

[pygame] Cannon 게임 프로젝트 6 - 총알 발사

 제작로그 6 - 총알 발사, Vector2 클래스의 이용 위 스크린샷은 게임에서 쓰이는 대포의 모습입니다.  대포는 빨간색으로 표시해 놓은곳을 중심으로 좌우로 90도씩 회전하도록 되어 있습니다. 이를 위해서는 2가지를 해결해야 합니다. 첫째는 대포를 중심을 기준으로 회전시켜야 했습니다. 이에 대해선 제 블로그에 pygame 의 회전을 다룬 다른 포스팅이 있는데 그걸 참고 하시면 됩니다. 링크 둘째는 총알을 발사했을때 특정 각도로 총알을 움직여야 하는 것이었습니다. 보통은 이런 경우 삼각함수를 이용해야 할테지만 pygame 에는 Vector2 라는 클래스가 있어서 이걸 이용할 수 있습니다.  다만 저도 아직 Vector2 클래스를 완전히 다 이해한 것은 아닙니다. 대충 보고 제가 필요한 부분만 이용한 것이라 더 간단한 방법이 있을 수 있음을 미리 알려드립니다. > 우선 Vector2 클래스에 대해 간단히 설명하겠습니다. Vector2 클래스는 죄표를 쉽게 다룰 수 있는 클래스 입니다.  예를 들어 (1,1) 에서 (1,100) 으로 공을 계속 1 만큼 이동시키는 건 매우 간단합니다. y 좌표에 계속 1 을 더하면 됩니다.  그런데 (10,10) 에서 (100,200) 으로 공을 1만큼 이동 시키려면 어떻게 해야 할까요? x,y 값에 각각 얼마씩을 더해줘야 할까요? 이걸 Vector2 클래스를 이용하면 별다른 수학적 계산 없이 할 수 있습니다. >>> a = pygame.math.Vector2(10,10) >>> b = pygame.math.Vector2(100,200) >>> c = b - a >>> c <Vector2(90, 190)> >>> d = c.normalize() >>> d <Vector2(0.428086, 0.903738)> 위에 보시면 아시겠지만 Vector 끼리 연산이 가능합니...

[pygame] Cannon 게임 프로젝트 5 - 스프라이트 충돌 체크

 제작로그 5 - 스프라이트 충돌 체크 기본 스프라이트의 충돌체크 방법은 몇가지가 있는데요. 여기서는 mask 방식의 충돌체크만 설명하겠습니다.  사각형과 원 방식의 충돌체크는 충돌을 판단하는 기준만 다를뿐 기본적으로 비슷한 함수를 사용하기 때문에 뒤에 아주 간단히 설명 하겠습니다. > mask 충돌체크를 하기 위해선 기본적으로 이미지를 로딩할때 convert_alpha() 를 사용해야 합니다. robot_image = pygame.image.load('images/robot.png').convert_alpha() 위의 문장과 같이 이미지를 로드해야 합니다.  > 또 한가지 조건은 sprite 클래스에 mask 란 변수를 만들고 mask 데이터를 넣어 줘야 합니다.  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.x = x         self.y = y         self.mask = pyga...

[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:         ...

[pygame] Cannon 게임 프로젝트 3 - 텍스트 표시

 제작 로그 3 - 화면에 텍스트 표시  pygame에서 모든 이미지는 surface 에 그려집니다. surface 는 이미지를 그리는 도화지 같은 것이라고 생각하시면 됩니다.  게임이 표시되는 화면도 surface 이고 화면에 표시되는 이미지도 읽어들이면 surface 객체로 생성됩니다.  따라서 텍스트도 surface 로 만들어져서 화면에 표시됩니다. 화면에 텍스트를 표시하기 위해서는... 1. font = pygame.font.SysFont("notosanscjkkr",30) 2. text_start = font.render("게임을 시작하려면 's' 키를 누르세요.",True,(0,255,0)) 3. background.blit(text_start,(150,300)) 위의 3 과정을 거칩니다.  1번은 폰트 객체를 생성하는 것 입니다.  2번은 텍스트가 표시된 Surface 를 만드는 것이고요. 3번은 화면에 표시되는 Surface 에 텍스트 이미지가 들어간 Surface 를 복사해 넣는 것입니다. 이 3번은 이전에 이야기 했던 while 문(게임의 메인루프)에 작성해야 합니다.  각 순서에 대한 자세한 설명은 아래에서 하나씩 하겠습니다. > 1번 폰트객체의 생성방법은 2가지가 있습니다.  첫째는 위와 같이 system 폰트를 이용하는 방법이고요.  두번째는 직접 폰트 파일을 읽어들여서 사용하는 방법입니다.   *시스템 폰트란 OS 에 등록되어 있는 폰트를 말합니다. 이 경우는 등록된 이름만 알면 위의 예처럼 바로 사용할 수 있습니다. 시스템이 등록된 폰트는 pygame 의 font 객체의 get_fonts() 함수로 구할 수 있습니다.  *폰트파일을 직접 읽어들이는 방법은 외부에서 다운받은 ".ttf " 파일을 직접 읽어들여 사용합니다. 이 경우는 게임을 배포한다면 폰트의 라이센스에 주의 해야 합니다.  파일을 실행파일과 같은 디렉토...

[pygame] Cannon 게임 프로젝트 2 - 기본 구조와 키보드, 마우스 처리

 제작로그 2 - pygame 의 기본구조  import pygame   SCREEN_X = 800    #게임창 x 크기 SCREEN_Y = 600    #게임창 y 크기   screen = pygame.display.set_mode((SCREEN_X,SCREEN_Y)) #게임 윈도우 생성 background = pygame.Surface(screen.get_size())        #게임 화면을 그릴 surface   done=True   while done:        #이 루프를 벗어나면 게임이 종료됨     ev = pygame.event.get()     for event in ev:         if event.type ==pygame.QUIT:     #창의 종료버튼이 눌렸을때 게임종료             done = False              if event.type == pygame.MOUSEBUTTONUP:             pass         if event.type == pygame.MOUSEMOTION:    #마우스를 움직이고 있음   ...

[pygame] Cannon 게임 프로젝트 1 - 프롤로그

제작로그 1 - 프롤로그  예전 부터 pygame 을 한번 사용해 보고 싶었습니다만...여러 이유로 진행이 안됐었는데 이번에 천천히 진행해 보고 있습니다.     현재 대략 진행중인 상태입니다.  이 게임은 예전에 제가 8비트 Apple 컴퓨터를 구입했을때 받은 디스켓에 들어있던 게임 중 하나였는데 오래되서 정확히 기억은 안나지만 대충 기억을 되살려 비슷하게 만들어 보았습니다. 게임의 규칙은 매우 간단해서 낙하산을 타고 내려오는 적들(제 경우는 로봇군단으로 설정)을 아래의 무기(대포)로 땅에 내려오기 전에 맞추면 되는 게임입니다.  모두 4기의 로봇이 땅에 착지하면 대포는 폭파되어 게임이 끝나고요. 대포가 있는 저 사각형 위는 한대라도 착지 하면 게임은 끝납니다. 대략적인 구현은 끝난 상태인데요. 제가 pygame 을 처음 다뤄보고, 원래 pygame 을 완전히 파악하고 진행하는게 아니라 공부 겸 해서 진행하는 프로젝트였고 그러다 보니 처음부터 치밀하게 구상해서 코딩을 하지 않았기 때문에 소스가 전혀 정리가 안되는 상태고 맘에 안듭니다만 기록을 남겨두지 않으면 또 까맣게 잊어버릴게 분명하기에 간단히 정리해 기록해 둘 생각입니다.  다음에는 조금 나아 지겠죠. 아마도요....ㅎㅎ  현재 로봇이나 대포의 폭파 표현등을 어떻게 할지를 고민중입니다. 이런 연출(?)은 해본적이 없어서....사운드도 좀 넣어야 되고....

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...