안녕하세요 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 참고:
히트박스나 충돌 관련으로 공부하실 분은 이쪽 링크도 참고하시면 좋을 것 같습니다.
전 중간고사 치구 다음 일지로 돌아오겠습니다! 다들 즐공하시길!
프로젝트 소스코드는 이곳 깃허브에서 확인하세요 ->
'개발 일지' 카테고리의 다른 글
비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 7. 애니메이션, 스탯 효과 (0) | 2020.11.06 |
---|---|
비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 6. 적 종류 및 이펙트 추가 (0) | 2020.11.02 |
비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 4. 오브젝트 추가 (0) | 2020.10.12 |
비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 3. HP, exp바 (0) | 2020.10.09 |
비주얼 베이직(vb.net)으로 슈팅게임 만들기 - 2. 캐릭터 이동 (0) | 2020.10.04 |
댓글