기본 콘텐츠로 건너뛰기

[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 끼리 연산이 가능합니다. 

b 에서 a 값을 빼서 두 좌표 사이의 거리 벡터 값인 c 를 구했습니다. 

a 위치에서 b 위치로 1 만큼 이동 시킬때의 값은 d = c.normalize() 로 구할 수 있습니다. 이제 d 값을 a 에 계속 더해주면 물체를 a 에서 b 로 이동시킬 수 있습니다. 

>

대포는 180도 안에서 회전을 하고 총알을 발사합니다. 이제 특정 좌표를 회전축을 중심으로 회전시켰을때의 좌표를 구해야 합니다. Vector2 에서는 이러한 연산도 가능합니다.

>>> a = pygame.math.Vector2(0,-100)
>>> a
<Vector2(0, -100)>
>>> b = a.rotate(-90)
>>> b
<Vector2(-100, -0)>
>>> c = a.rotate(270)
>>> c
<Vector2(-100, -0)>
>>> d = a.rotate(90)
>>> d
<Vector2(100, 0)>
>>> e = b.normalize()
>>> e
<Vector2(-1, -0)>
 

초기 좌표는 (0,-100) 입니다. 

대포는 중심에서 위쪽을 향해 발사합니다. 대포의 길이는 100 이라고 가정 하겠습니다. 대포의 회전축은 (0,0) 이 되고요. 총알이 나가는 대포의 끝부분은 중심에서 100 위쪽입니다. 따라서 초기 좌표값은 (0,-100) 이 된 것 입니다.

이제 이 좌표를 회전 시켜 봅시다. rotate 함수를 이용하면 됩니다. 왼쪽으로 회전하면 각도가 마이너스 값이고 오른쪽으로 회전하면 각도가 플러스 값입니다. 물론 위에 보이는것 처럼  -90 도와 270도의 값은 당연히 같습니다. 

특정 각도로 총알을 계속 보내기 위해서는 rotate 로 구한 Vector 값에 normalize() 를 하면 됩니다. 위에서는 -90 도로 회전시켰을 때의 좌표인 b 의 값을 normalize() 해서 e 값을 구했습니다. b 값에 e 를 계속 더해주면 -90 도의 방향으로 총알은 계속 전진할 것 입니다. 


댓글

이 블로그의 인기 게시물

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

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 을 실행해서 설치해 주면 됩니다.    그런다음 업데이트를 시도해 보면 잘 됩니다.   

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

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