Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발이 취미인 개발자

슈팅게임 알고리즘-n-way탄 구현하기 본문

슈팅게임 알고리즘(pygame)

슈팅게임 알고리즘-n-way탄 구현하기

도그풋79 2022. 4. 16. 12:25

 슈팅게임의 난이도를 높이기 위해서는 바로 이 n-way탄은 필수적인 요소이다. 한번에 여러발을 발사하여 플레이어가 피할 수 있는 공간 줄이고 움직임이 제한하여 게임의 긴장감을 높일 수가 있다. 여러발이 동시에 발사되어 꽤 어려운 것 같지만 기본 원리는 조준탄과 거의 유사하다. 정말 단순하다. 조준한 원래 탄에 좌우로 각도가 다른 총알만 생성해주면 끝이다.

 

 처음 총알은 플레이어를 조준한 각도 θ로 만든다. 그리고 좌우로 θ₁, -θ₁각도를 더한 추가로 탄을 생성한다. 원하는 방향을 늘리고 싶다면 위의 각도 추가하는 걸 반복만 하면 된다. 여기서는 3방향, 5방향만 구현을 했다. 더 많은 방향으로 총알이 나가고 싶다면 그냥 소스에서 nway의 값만 늘려주면 된다.

    def createBullet(self, bullet_group, sx, sy, tx, ty, theta, speed):
        nway = 3
        orig_theta = theta
        for i in range(1, nway):
            enemyBullet_right = NWayBullet(sx, sy, tx, ty, theta, speed)
            enemyBullet_left = NWayBullet(sx, sy, tx, ty, theta * -1, speed)
            bullet_group.add(enemyBullet_right)
            bullet_group.add(enemyBullet_left)
            theta += orig_theta
        
        enemyBullet = NWayBullet(sx, sy, tx, ty, 0, speed)
        bullet_group.add(enemyBullet)

 

아래 NWayBullet 코드를 보자. 기존에 개발된 조준탄 소스와 차이는 좌표값과 n-way탄의 각도를 받아서 다시 조준해서 총알을 생성하는 차이 밖에 없다.

class NWayBullet(pygame.sprite.Sprite):
    def __init__(self, sx, sy, tx, ty, rad, speed):
        pygame.sprite.Sprite.__init__(self)        
        self.image = pygame.image.load(img_dir + "/img/circle_bullet_01.png")
        self.rect = self.image.get_rect()
        self.rect.center = [sx, sy]
        self.angle = math.atan2(ty - sy, tx - sx) + math.radians(rad)
        self.speed = speed
        self.max_speed = 5.0
        self.x = sx
        self.y = sy

    def update(self, GameMain):
        self.dx = math.cos(self.angle) * self.speed
        self.dy = math.sin(self.angle) * self.speed
        if self.max_speed > self.speed:
            self.speed += 0.2

 기존에 이열 포대는 n-way탄과는 별로 어울리지 않아 포열이미지도 변경해 보았다. 총알이 발사되는 구멍이 고정되어 있으면 왠지 심심해 보여 기관단총처럼 회전하는 애니메이션을 넣어 보았다.

 

 애니메이션 효과를 위해 위의 6개 이미지를 순서대로 배열에 넣었다. 그리고 animation_interval의 값을 준 후, self.image의 값을 interval 값에 따라 배열 순서대로 변경해준다.

class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.images = \
            [pygame.image.load(img_dir + "/img/nway_turret_01.png")
            ,pygame.image.load(img_dir + "/img/nway_turret_02.png")
            ,pygame.image.load(img_dir + "/img/nway_turret_03.png")
            ,pygame.image.load(img_dir + "/img/nway_turret_04.png")
            ,pygame.image.load(img_dir + "/img/nway_turret_05.png")
            ,pygame.image.load(img_dir + "/img/nway_turret_06.png")
            ]
        self.image = self.images[0]
        self.image_idx = 0
        self.rect = self.image.get_rect()
        self.rect.center = [x, y]
        self.speed = 4
        self.x = x
        self.y = y
        self.theta = 0
        self.angle = 0        
        self.animation_frame = 0
        self.animation_interval = 5
        self.fire_frame = 0
        self.fire_delay_frame = random.randint(200, 300)        
        self.id = uuid.uuid4()
        
    def update(self, GameMain):
        self.fire_frame += 1        
        self.animation_frame += 1
        ty = GameMain.flight.rect.centery
        sy = self.rect.centery
        tx = GameMain.flight.rect.centerx
        sx = self.rect.centerx
        self.angle = math.atan2(ty - sy, tx - sx)
        self.theta = math.degrees(self.angle) * -1
        self.image = pygame.transform.rotate(self.images[self.image_idx], self.theta)
        self.rect = self.image.get_rect()
        self.rect.center = [self.x, self.y]            
        if self.animation_frame >= self.animation_interval:
            self.image_idx +=1
            self.animation_frame = 0
            if self.image_idx > 5:
                self.image_idx = 0
    
        if self.fire_frame >= self.fire_delay_frame:
            self.createBullet(GameMain.bullet_group, sx, sy, tx, ty, 15, self.speed)
            self.fire_frame = 0

n-way탄 전체 소스를 첨부한다.

03_n_way_bullet.zip
0.03MB