본문 바로가기
개발 일지

비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 5. 적 추가

by PrintedLove 2020. 10. 17.

안녕하세요 Printed입니다. 거의 일주일 만에 돌아왔네요;

이제 진짜 시험이 열흘도 안남아서 다음 일지는 이번보다 늦게 올라올 것 같습니다.

 

이번에는 적과 플레이어의 오토 공격 기능을 추가했습니다! 바로 영상 보시죠.

 

 

 

사방에서 적들이 랜덤 스폰되고(아이템 랜덤스폰 알고리즘과 동일), 플레이어를 향해 몰려옵니다.

여러분은 플레이어를 움직이기만 하면 됩니다! 자동으로 가장 가까운 적을 향해 투사체가 발사됩니다.

 

Imports System.Math

Public Class Enemy : Inherits ObjectBase

    Private enemyHp As Integer
    Private enemyspd, damage_touch, damage_shot As Int16
    Private touchKill As Boolean = False

    Sub New()
        spr = spr_enemy
        Dim enemy_type As Int16 = random.Next(1, 100)
        Dim enemy_per As Int16 = 0

        'spon probability
        For index As Int16 = 0 To 6
            enemy_per += enemy_spon(stage, index)

            If enemy_type <= enemy_per Then
                type = 10 + index
                Exit For
            End If
        Next

        spr_index = type - 10
        rec.Location = GetCoordCircle(S_WIDTH \ 2, S_HEIGHT \ 2,
                                      random.Next(0, 360) * 180 / Math.PI, S_WIDTH + random.Next(0, S_WIDTH \ 2))

        damage_touch = 10
        damage_shot = 0

        'stat setting
        Select Case type
            Case 10                              'normal_small
                rec.Size = New Point(28, 28)
                enemyspd = 7
            Case 11                              'normal_medium
                rec.Size = New Point(65, 65)
                enemyspd = 6
            Case 12                              'normal_big
                rec.Size = New Point(120, 120)
                enemyspd = 5
            Case 13                              'rush_small
                rec.Size = New Point(13, 13)
                damage_touch = 20
                enemyspd = 15
                touchKill = True
            Case 14                              'rush_big
                rec.Size = New Point(25, 25)
                damage_touch = 30
                enemyspd = 12
                touchKill = True
            Case 15                              'shoter_small
                rec.Size = New Point(31, 31)
                damage_shot = 10
                enemyspd = 10
            Case 16                              'shoter_big
                rec.Size = New Point(31, 31)
                damage_shot = 10
                enemyspd = 8
        End Select

        enemyHp = hpToDif(difficulty - 1, type - 10)
    End Sub

    Sub IndividualEvent()
        DefaultEvent()

        'move to player
        Dim move_angle As Double = GetAngleTwoPoint(rec.X, rec.Y, S_WIDTH \ 2, S_HEIGHT \ 2)
        Dim moveCoord As Point = GetCoordCircle(0, 0, move_angle, enemyspd)

        rec.X += moveCoord.X
        rec.Y += moveCoord.Y

        'hp manage
        If enemyHp < 1 Then
            kill = True
        End If

        'collision with player
        If gameTick Mod 10 = 0 And rec.IntersectsWith(player_rec) Then
            If touchKill = True Then
                kill = True
            End If

            hp -= damage_touch      'touch damage
        End If

        If Not kill Then
            'collision with other(enemy, player attack)
            Dim list_index As Int16 = 0

            While list_index < obj_list.Count()
                Dim obj As Object = obj_list.Item(list_index)

                If 9 < obj.type And obj.type < 100 Then                   'collision with enemy
                    If Not obj.Equals(Me) And rec.IntersectsWith(obj.rec) Then
                        rec.X -= Sign(obj.rec.X - rec.X)
                        rec.Y -= Sign(obj.rec.Y - rec.Y)
                    End If
                ElseIf obj.type = 100 Then                   'collision with player attack
                    If rec.IntersectsWith(obj.rec) Then
                        enemyHp -= atk_dam
                        obj.kill = True
                    End If
                End If

                list_index += 1
            End While

            'is enemy in player attack distance
            Dim distanceToPlayer As UInteger = GetDistanceTwoPoint(player_rec.X, player_rec.Y, rec.X, rec.Y)

            If EnemyDistance > distanceToPlayer Then
                EnemyDistance = distanceToPlayer
                nearestEnemyIndex = index
            End If
        End If
    End Sub
End Class

 

Enemy 객체를 생성하는 클래스의 코드입니다.

중요한 부분은 개인 이벤트를 뜻하는 IndividualEvent메소드 부분입니다. 그곳에서 충돌검사(플레이어, 적, 플레이어 공격), 가장 가까운 적 인덱스 반환 등의 처리를 합니다.

적 들끼리 부딛혔을 시 서로 안겹치게 거리 유지를 해주는 코드와 플레이어 방향으로 추적 이동하는 코드가 핵심입니다.

 

충돌 검사에서 프레임 드랍이 발생해 FPS를 100에서 30으로 수정했습니다... 

파이썬에서 슈팅게임 만들때 몇백개를 동시에 돌렸는데도 렉하나 안걸렸던걸 생각해보면 VB.Net 자체가 느린것 같네요(해당 게임은 드로잉 객체가 100개 미만입니다)

 

그래도 충돌검사 최적화쪽으로 공부하면서 Sweep and Prune와 같은 고급 알고리즘 등도 알게 되어 유익했던 것 같습니다. 물리엔진 만들때 필수로 사용되는 기술로 나중에 물리엔진 만들일 있으면 직접 구현도 해볼 계획입니다. ... 지금 프로젝트에 넣기엔 배보다 배꼽이 더 큰지라... ㅋㅋ

Sweep and Prune 참고:

 

https://schteppe.github.io/sweep-and-prune/

 

schteppe.github.io

 

히트박스나 충돌 관련으로 공부하실 분은 이쪽 링크도 참고하시면 좋을 것 같습니다.

 

[0122 구경원]게임에서의 충돌처리

게임 || 충돌.돼지고기(구경원)구제역아 물러가라.

www.slideshare.net

 

 

전 중간고사 치구 다음 일지로 돌아오겠습니다! 다들 즐공하시길!

 

프로젝트 소스코드는 이곳 깃허브에서 확인하세요 ->

 

PrintedLove/VisualBasic-Shooting-Game

shooting game project made with Visual Basic. Contribute to PrintedLove/VisualBasic-Shooting-Game development by creating an account on GitHub.

github.com

 

댓글