스푸79 기록 보관소

운석 피하기 게임 개발(12)- 충돌 시 파편 만들기 본문

게임개발

운석 피하기 게임 개발(12)- 충돌 시 파편 만들기

스푸79 2024. 9. 22. 12:00

운석과 메인 캐릭터와 충돌할 때

운석과 운석이 충돌할 때

충돌로 인한 파편이 발생하는 부분을 구현해 보았다.

 

어떤 물체가 폭발할 때

폭발하는 파편의 방향은 아래 그림과 같은 것이다.

 

 

360도 방향으로 물체의 조각이 퍼질 것이고

그 방향과 속도 그리고 파편의 크기는 모두 일정하지 않다.

위와 같은 모양이 되도록 한번 코드로 구현해보자

class Particle(pygame.sprite.Sprite):
    def __init__(self, x, y, size, dir, sprites):
        pygame.sprite.Sprite.__init__(self)
        self.sprites = sprites
        self.size = size
        self.image = sprites[size]
        self.rect = self.image.get_rect()
        self.pos = (x, y)
        self.rect.center = (x, y)
        self.speed = random.uniform(0.5, 2)
        self.target = pygame.Vector2(env.ANGLE_TO_VECTORS[dir])
        self.vel = self.target * self.speed
        self.shrink_delay_frame = 10
        self.frame = 0
        self.inc = -1

 

우선 파편 조각 클래스이다.

sprites 는 resources에서 생성하는데 이때 크기가 점점 시간이 지날 수록 사라지도록 처리할 것이다.

shrink_delay_frame 은 사라지는 효과의 프레임 속도를 조절하기 위해 넣었다.

 

env.ANGLE_TO_VERTORS[dir] 이 부분은 각도에 따른 vector값을 미리 enviroments에 설정하기로 했다.

Particle class의 객체가 생성될 때마다 각도에 따른 소숫점이 많은 계산을 돌리는 것보다는

미리 계산해 놓은 값을 불러오는 것이 속도 처리가 훨씬 빠르다.

    ANGLE_TO_VECTORS = [(0.0, -1.0), (0.02, -1.0), (0.03, -1.0), (0.05, -1.0), (0.07, -1.0)
   , (0.09, -1.0), (0.1, -0.99), (0.12, -0.99), (0.14, -0.99), (0.16, -0.99)
   , (0.17, -0.98), (0.19, -0.98), (0.21, -0.98), (0.22, -0.97), (0.24, -0.97)
   , (0.26, -0.97), (0.28, -0.96), (0.29, -0.96), (0.31, -0.95), (0.33, -0.95)                        
                        ....(중략)

 

0도부터 359도까지의 vector값이 미리 계산된 배열을 선언했다. dir 변수는 해당 각도를 뜻한다.

아래는 위의 Particle class를 활용하여 충돌 효과를 주는 코드이다.

    def radial_explode(self, id, x, y, size, cnt):        
        for _ in range(cnt):
            size = random.randint(0, size)
            dir = random.randint(0, 359)            
            self.main.effect_sprites.add(Particle(x, y, size, dir, getattr(self, "effect" + str(id))))

 

어떤가 생각보다 코드가 너무 간단해서 놀랐는가?

파편의 갯수와 크기, 방향만 무작위로 뽑은 다음 그것을 생성해 주면 된다.

 

그러면 파편 조각 resource를 만들어보자.

    def render(self):
        a1_image = pygame.image.load(env.GAME_IMG_DIR + "meteor_01_A.png").convert_alpha()
        b1_image = pygame.image.load(env.GAME_IMG_DIR + "meteor_01_B.png").convert_alpha()
        ... (중략) ..
        effect0_image = pygame.Surface((env.EFFECT_DEFAULT_SIZE, env.EFFECT_DEFAULT_SIZE))
        effect0_image.fill(env.EFFECT_01_COLOR)
        pygame.draw.rect(effect0_image, env.EFFECT_00_COLOR, effect0_image.get_rect())

        effect1_image = pygame.Surface((env.EFFECT_DEFAULT_SIZE, env.EFFECT_DEFAULT_SIZE))
        effect1_image.fill(env.EFFECT_01_COLOR)
        pygame.draw.rect(effect1_image, env.EFFECT_01_COLOR, effect1_image.get_rect())

        effect2_image = pygame.Surface((env.EFFECT_DEFAULT_SIZE, env.EFFECT_DEFAULT_SIZE))
        effect2_image.fill(env.EFFECT_02_COLOR)
        pygame.draw.rect(effect2_image, env.EFFECT_02_COLOR, effect2_image.get_rect())

        effect3_image = pygame.Surface((env.EFFECT_DEFAULT_SIZE, env.EFFECT_DEFAULT_SIZE))
        effect3_image.fill(env.EFFECT_03_COLOR)
        pygame.draw.rect(effect3_image, env.EFFECT_03_COLOR, effect3_image.get_rect())

        effect4_image = pygame.Surface((env.EFFECT_DEFAULT_SIZE, env.EFFECT_DEFAULT_SIZE))
        effect4_image.fill(env.EFFECT_04_COLOR)
        pygame.draw.rect(effect4_image, env.EFFECT_04_COLOR, effect4_image.get_rect())

 

기존 코드에서 Surface만을 활용하여 네모난 상자 형태의 블럭을 생성했다.

그리고 각 effect에 따른 배열에 사이즈별로 resize된 이미지를 생성하여 넣었다.

방식은 운석과 동일하고 차이점이 있다면 회전을 주지 않았다는 점이다.

        for i in range(1, env.EFFECT_DEFAULT_SIZE + 1):
            self.effect0.append(Util.resize_image(effect0_image, env.EFFECT_DEFAULT_SIZE - i))
            self.effect1.append(Util.resize_image(effect1_image, env.EFFECT_DEFAULT_SIZE - i))
            self.effect2.append(Util.resize_image(effect2_image, env.EFFECT_DEFAULT_SIZE - i))
            self.effect3.append(Util.resize_image(effect3_image, env.EFFECT_DEFAULT_SIZE - i))
            self.effect4.append(Util.resize_image(effect4_image, env.EFFECT_DEFAULT_SIZE - i))

 

미리 계산된 각도별 vector값부터 운석 sprites에 맞는 effect효과 색상까지 추가 Envoriment.py 에 추가했다.

이전보다 좀 소스코드가 조금 많이 길어졌다.

class Enviroment:
 .. (중략) ..

    EFFECT_00_COLOR = (255, 0, 0)
    EFFECT_01_COLOR = (108, 93, 83)
    EFFECT_02_COLOR = (72, 55, 55)
    EFFECT_03_COLOR = (160, 90, 44)
    EFFECT_04_COLOR = (68, 80, 22)
    EFFECT_DEFAULT_SIZE = 10

    ANGLE_TO_VECTORS = [(0.0, -1.0), (0.02, -1.0), (0.03, -1.0), (0.05, -1.0), (0.07, -1.0)
            , (0.09, -1.0), (0.1, -0.99), (0.12, -0.99), (0.14, -0.99), (0.16, -0.99)
            , (0.17, -0.98), (0.19, -0.98), (0.21, -0.98), (0.22, -0.97), (0.24, -0.97)
            , (0.26, -0.97), (0.28, -0.96), (0.29, -0.96), (0.31, -0.95), (0.33, -0.95)
 .. (중략) ..

 

소스코드를 첨부한다.

10. effect.zip
0.04MB

 

이번에 구현된 화면을 보면 느끼겠지만

운석이 아주 큰 경우

충돌이 많아져서 폭발할 때

별다른 효과없이 그냥 훅 사라지고 만다.

다음 포스트에는 운석이 폭발하는 효과를 한번 추가해 보도록 하겠다.