기본 콘텐츠로 건너뛰기

[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 = pygame.mask.from_surface(img) #충돌체크용 마스크 생성 

보통 스프라이트 클래스는 기본적으로 위와 같이 만듭니다. 맨 마지막줄에 보면 pygame.mask.from_surface(img) 문장으로 이미지를 이용해서 mask 를 만들고 있습니다. 

>

위의 2가지가 준비되었으면 이제 스프라이트 충돌 함수를 사용할 수 있습니다.

hit_list = pygame.sprite.spritecollide(bullet,robot_list,True,pygame.sprite.collide_mask)

첫번째가 단일 스프라이트, 두번째가 스프라이트 그룹, 세번째 True 는 충돌한 스프라이트를 스프라이트 그룹에서 제거하라는것, 네번째는 충돌체크를 mask 를 이용해서 하라는 것 입니다. 

스프라이트 그룹은...

robot_list = pygame.sprite.Group()
robot_list.add(robot1)
robot_list.add(robot2)
robot_list.add(robot3)

방법으로 여러 스프라이트를 추가하는 스프라이트들의 리스트 입니다.  

리턴값인 hit_list 는 말 그대로 충돌한 스프라이트들의 리스트 입니다.

 

위 함수를 사용하면 bullet 스프라이트가 스프라이트 그룹인 robot_list 의 스프라이트들중 하나와 충돌하면 해당 스프라이트는 robot_list 에서 삭제되고 hit_list 로 리턴 됩니다.

저는 이번에 이 함수를 사용하지 않았는데요. 왜냐하면 캐릭터 하나가 2개의 스프라이트로 이루어져 있었기 때문입니다. 게임상의 이유로 스프라이트 그룹을 이용하지 않고 따로 리스트를 이용하는 방법을 선택했습니다.

>

pygame.sprite.collide_mask(bullet,robot)

bullet 과 robot 모두 스프라이트 이고 만일 충돌했으면 True 를 리턴 합니다. 매우 간단하죠. if 문으로 리턴값을 판단해서 충돌후 처리를 하면 됩니다. 

넘 간단하지만....끝이고요.  나머지는 사족 입니다.

>


 

혹시라도 mask 충돌 체크 자체에 대한 이해를 못하는 분을 위해 간단히 설명하자면......

위 이미지는 제가 만든 robot.png 파일을 gimp 에서 읽어온 이미지 입니다. 격자부분은 투명한 부분을 표시하는 겁니다. 녹색으로 된 부분이 캐릭터 이고요. mask 충돌 방법을 이용하면 투명한 부분(격자 부분)은 충돌 체크에서 제외됩니다. 

따라서 사각형, 원 충돌체크 같은 특정 범위를 체크 하는 방법에 비해, 정확히 캐릭터의 형태에 따른 충돌 체크를 할 수 있습니다. 

위와 같이 배경이 투명한 이미지를 만드는 법은 인터넷에 찾아 보면 나오는데요. 언제 시간나면 저도 한번 포스팅 해 보도록 하겠습니다. 

>

사각형, 원으로 체크 하는 방법은 스프라이트 클래스의 rect 값과 radius 값을 기준으로 두 스프라이트의 충돌을 체크 합니다. mask 방식과는 달리 스프라이트에 mask 를 만들 필요가 없으며(당연하지만...) 스프라이트 클래스에 radius 변수가 없다거나 rect 값이 정확하지 않으면 당연히 제대로 작동이 안됩니다. 

pygame.sprite.collide_rect(bullet,robot)
pygame.sprite.collide_circle(bullet,robot)
pygame.sprite.spritecollide(bullet,robot_list,True,pygame.sprite.collide_rect)
pygame.sprite.spritecollide(bullet,robot_list,True,pygame.sprite.collide_circle)

위와 같은 방법으로 사용하면 됩니다.

댓글

  1. 전제 코드를 보여주실 수 있나요?

    답글삭제
    답글
    1. 댓글이 달린걸 확인을 못해서 늦게나마 댓글을 씁니다.

      소스가 잘 정리되면 올릴 수도 있겠지만 지금 현재의 소스는 올리기 어렵습니다. 수많은 삽질 코드가 같이 있기 때문입니다.
      언제 전체 코드를 올릴날이 있을지도 모르겠지만 기약을 드리긴 어렵습니다.

      삭제

댓글 쓰기

이 블로그의 인기 게시물

유로트럭 시뮬레이터 2 순간이동 치트 사용방법

최근 이벤트때 운송해야 할 물건이 나오지 않아 고민중에 어떤 게임사이트에서 찾아낸 방법입니다. 이미 게임을 충분히 하신 분들은 여기저기에 창고가 이미 있을것이기 때문에 그 창고로 이동하면 되지만 그렇지 못한 분들은 지역을 이동하는것이 시간이 많이 걸립니다. 이 방법을 쓰면 특정 도시로 빠르게 이동이 가능합니다. 내문서 -> Euro Truck Simulator 2 의 config.cfg 를 사용하시는 텍스트 에디터로 수정합니다. 수정해야 할 부분은 위에 표시해 놓은 부분입니다. 원래값은 0 이며 1로 바꿔줍니다. 이제 키보드의 '~' 키를 누르면 콘솔창이 뜹니다. 위의 스크린샷이 콘솔을 띄운 화면 입니다. 위와 같이 키보드를 눌렀을때 콘솔이 뜨면 일단 준비과정은 끝납니다. 이제 순간이동 사용법을 알려드리겠습니다. 1. 숫자키 '0'을 눌러서 프리카메라 모드로 들어갑니다. 2. 'm' 키를 눌러서 이동해야 할 도시를 확인하고 도시의 이름을 외워둡니다. 3. 콘솔을 열고 'goto 도시이름' 을 입력합니다. 성공했으면 해당 도시로 바로 이동합니다. 4. 마우스와 키보드 오른쪽의 숫자키패드를 이용해서 지상으로 이동합니다. 5. Ctrl + F9 키를 눌러 트럭을 소환합니다. 위의 순서에서 4번은 주의 하셔야 합니다. 트럭은 Ctrl + F9 를 누르는 순간 카메라의 위치로 소환됩니다. 만일 지상으로 이동하지 않고 트럭을 소환하실 경우 트럭이 지상으로 추락하여 손상 100%가 될 수도 있습니다. 즐거운 게임 되시길 바랍니다.    2022 년 2월 3일 수정사항 트럭의 소환키가 F9 에서 Ctrl + F9 로 변경되었다는 걸 확인해서 본문을 수정했습니다.

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

최근 우분투 리눅스에서 snap 앱을 모두 삭제했습니다

 사실 조금 된 이야기이긴 한데. 제 우분투 리눅스에서 snap 앱을 모두 삭제 했습니다.  여러 이유로 snap 을 싫어하는 분들이 있기는 한데 제 경우는 그렇게 부정적인 입장은 아닙니다.  개발자들 세계에서도 여러 라이브러리 버전문제로 인해 docker 같은것을 쓰는걸 보면 실행에 필요한 라이브러리를 내장한다는 개념은 편리함으로 다가올수도 있습니다.  그냥 제 경우는 간단히 프로그램들이 차지하는 용량(크기)의 문제였습니다.  저는 오래전에 구입한 64기가 SSD 에 리눅스를 설치해서 계속 쓰고 있습니다. 그리 큰용량은 아니지만 이걸로 리눅스를 사용하는데 용량이 크게 부족하다고 느낀적은 없었는데(대량의 데이터는 NTFS 로 포맷한 데이터 저장용/게임용 SSD 에 저장합니다) snap 앱들을 설치하니 64기가가 부족하더군요.  좀 더 용량이 큰 SSD를 추가 구입해서 리눅스를 다시 설치할까 고민을 했었는데 제가 사용하는 프로그램이나 그런걸 보고 snap 용 프로그램을 정리해 보니 사용에 딱히 지장은 없겠더군요. 그래서 snap 앱을 정리하고 쓰고 있습니다.   snap 앱들의 크기를 너무 간과했습니다. 실제 써보니 꽤 많이 먹네요. 이렇게 해 놓고 보니 그냥 arch 리눅스나 설치해서 쓸까 하는 유혹이 또 들긴합니다만....이젠 다시 설치도 귀찮아서....manjaro 정도로 타협도 고려중입니다. ^^;