有自己做stg的前辈吗 想请教下弹幕的算法
用的是C++和DX9 (因为还是xp的系统 最高只能dx9了 然而大约不久后会换机子吧)关于弹幕的移动 主要是考虑到弹幕并不一定是直线移动的(可能涉及奇怪的弧线或者中途变成狙之类的) 所以大概不大好用csv之类的记录一串数据直线移动就做出来
当前的做法是 弹幕的class里面有个函数指针成员pFunc 然后每次移动的时候如果pFunc==NULL 则当前的x和y坐标分别加上vx和vy 如果pFunc不是NULL则跑这个函数来改变弹幕的相应参数 这样就可以写各种不同的弹幕移动函数了
但是昨天在测试的时候试着写了个恋恋的本我(原作心弹素材 显示方面用的是sprite) 在全屏才100弹幕左右的时候就已经开始频繁的掉帧 而且我现在自机都没做 都是无判定弹幕 再加上弹幕判定可能会更卡
想请教下前辈们是怎么处理弹幕的算法的 谢谢大家
因为C++和DX9都是自学的 所以很多地方可能知识点有疏漏可能会有追问 或是问题表述不清楚还请见谅 _(:з」∠)_真是厉害啊,【关注此问题←我也想知道(虽然我能撑几千弹幕才掉帧,,不过大概是电脑比较好的原因) song_5007 发表于 2015-6-8 17:37 static/image/common/back.gif
_(:з」∠)_真是厉害啊,【关注此问题←我也想知道(虽然我能撑几千弹幕才掉帧,,不过大概是电脑比较好的原 ...
哇 几千弹幕很酷炫诶 请问前辈是什么做法 fancydz 发表于 2015-6-8 17:49 static/image/common/back.gif
同关注此问题
因为找不到顺手的弹幕编写方式
所以一直处于半弃坑状态,一直在打别人家的飞机
我也在打别人的飞机(怎么听起来那么少儿不宜 你掉帧是用debug测的吗……
不论怎样,100弹就掉帧也太…… 额这个。。。。我是用vb.net,大概2W之后才有比较明显掉帧。。。 刚刚看了一下,感觉本我[本能的释放]这张应该不难写,弹幕class里边存储几个简单数据即可:坐标,速度,角度,速度增量,角度增量。
放弹时以BOSS为坐标,有一定初速度,方向是圆形四周各个方向,速度增量设成负的,每次同方向发弹发两弹,然后把方向增量设成一正一副两个绝对值相等的数。最后在每帧处理的时候限定一下弹幕的最低速度就可以了。
这样就不用每个弹幕单跑一次函数了,只用作简单的加减法和三角函数计算就可以了。
http://img4q.duitang.com/uploads/item/201506/09/20150609004810_K8mcA.gif
这个效果其实不够好。
更可行的方法是弄个叫Anim的类,里边存储弹幕在不同时刻的数据。
在弹幕类里边声明anim为他的属性之一,平时可以空着,像这张卡的时候可以可以填上3个anim,
分别对应
1 弹幕开始发出时速度正常,只有一定角加速度的状态
2 弹幕转弯一段时间后减速,速度增量为负,角加速度随着减小的状态
3 弹幕不再减速后,只有速度和角度的状态
根据弹幕发出后的时间决定套用哪个anim的计算方式。
弹幕时间可以在每次帧处理时+1。
(以上均为口胡。) 本帖最后由 krh 于 2015-6-8 14:11 编辑
100 确实太少了
是哪里搜索了 或者大量循环才会这样吧(看起来100*100 次计算距离比较符合计算机的速度
Public Class STG3D
' STG相关的数据结构和函数
' 此类不可实例化
Public Const DivideNum As Integer = 12
Public Const JUDGE_GRAZE As Integer = 1
Public Const JUDGE_MISS As Integer = 2
Public Const JUDGE_AWAY As Integer = 3
Public Const TEX_SPHERE As Integer = -2
Public Const TEX_CIRCLE As Integer = -1
Public Class Bullet
' 抽象的弹幕类
' 也可作为物体的基类
Private Position As Base.Point3D
Private Speed As Base.Point3D
Private Rotate As Base.Point3D
Private Scale As Base.Point3D
Private TexPtr As Integer
Private Texture As DxVB.DxImage
Public IsEnabled As Boolean
Public IsGrazed As Boolean
Public Sub New()
Position.x = 0 : Position.y = 0 : Position.z = 0
Speed.x = 0 : Speed.y = 0 : Speed.z = 0
Rotate.x = 0 : Rotate.y = 0 : Rotate.z = 0
Scale.x = 0 : Scale.y = 0 : Scale.z = 0
TexPtr = 0 : IsEnabled = False : IsGrazed = True
Texture = New DxVB.DxImage
End Sub
Public Sub New(ByVal Texture As DxVB.DxImage)
Position.x = 0 : Position.y = 0 : Position.z = 0
Speed.x = 0 : Speed.y = 0 : Speed.z = 0
Rotate.x = 0 : Rotate.y = 0 : Rotate.z = 0
Scale.x = 0 : Scale.y = 0 : Scale.z = 0
TexPtr = Texture.Handle : IsEnabled = False : IsGrazed = True
Me.Texture = Texture
End Sub
Public Sub SetTexture(ByVal Texture As DxVB.DxImage)
TexPtr = Texture.Handle
Me.Texture = Texture
End Sub
Public Function GetPosition() As Base.Point3D
Return Position
End Function
Public Sub SetPosition(ByVal x As Double, ByVal y As Double, ByVal z As Double)
Position.x = x : Position.y = y : Position.z = z
End Sub
Public Sub SetPosition(ByRef Point As Base.Point3D)
Position = Point
End Sub
Public Function GetSpeed() As Base.Point3D
Return Speed
End Function
Public Sub SetSpeed(ByVal x As Double, ByVal y As Double, ByVal z As Double)
Speed.x = x : Speed.y = y : Speed.z = z
End Sub
Public Sub SetSpeed(ByRef Point As Base.Point3D)
Speed = Point
End Sub
Public Sub SetRotate(ByVal x As Double, ByVal y As Double, ByVal z As Double)
Rotate.x = x : Rotate.y = y : Rotate.z = z
End Sub
Public Sub SetScale(ByVal x As Double, ByVal y As Double, ByVal z As Double)
Scale.x = x : Scale.y = y : Scale.z = z
End Sub
Public Function PreJudge(ByRef Point As Base.Point3D, ByVal Range As Double) As Boolean
Return Math.Abs(Point.x - Position.x) < Range And Math.Abs(Point.y - Position.y) < Range And Math.Abs(Point.z - Position.z) < Range
End Function
Public Function PreJudge(ByRef Point As Base.Point3D, ByVal RangeX As Double, ByVal RangeY As Double, ByVal RangeZ As Double) As Boolean
Return Math.Abs(Point.x - Position.x) < RangeX And Math.Abs(Point.y - Position.y) < RangeY And Math.Abs(Point.z - Position.z) < RangeZ
End Function
Public Function Judge(ByRef Point As Base.Point3D) As Integer
If (Base.Distance3D(Point, Position) > Base.Average3D(Scale) * 1.5D) Then
Return JUDGE_AWAY
ElseIf (Base.Distance3D(Point, Position) > Base.Average3D(Scale)) Then
Return JUDGE_GRAZE
Else
Return JUDGE_MISS
End If
End Function
Public Function Distance(ByRef Bullet As Bullet) As Single
Return Base.Distance3D(Position, Bullet.GetPosition())
End Function
Public Sub Draw()
'If TexPtr = -2 Then DxVB.DrawSphere(Position.x, Position.y, Position.z, Base.Average3D(Scale), DivideNum, 255, 255, 255, 0, 0, 0, True)
'If TexPtr = -1 Then DxVBDLL.DX.DrawCircle(Position.x, Position.z, Base.Average3D(Scale), DX.GetColor(255, 255, 255))
'If TexPtr > 0 Then DxVB.DrawPic(Texture, Position.x, Position.z)
If TexPtr = 0 Then DX.DrawPixel(Position.x, Position.z, &HFFFFFF)
DxVB.DrawPic(Texture, Position.x, Position.z, Base.Average3D(Rotate))
End Sub
End Class
Public Class STGCore
' STG的核心函数在这里
' 包括绘制,判定和控制
' 弹幕生成需要继承这个类
' 此类需要实例化
Protected ArrayNumA As Integer
Protected ArrayNumB As Integer
Protected Bullets As Bullet(,)
Public Shared Player As Bullet
Protected Shared OriPlayer As Base.Point3D
Protected Shared GameCenter As Bullet
Protected CorePosition As Bullet
Protected Shared GameRange As Double
Protected Shared DefaultTex As Integer
Protected Shared Graze, Miss, Num As Integer
'Protected STGThread As Thread
Public Shared Sub InitShared(ByVal CenterX As Double, ByVal CenterY As Double, ByVal CenterZ As Double, ByVal Range As Double, _
ByVal PlayerX As Double, ByVal PlayerY As Double, ByVal PlayerZ As Double, ByVal PlayerSize As Double, ByVal DefaultTexture As Integer)
Player = New Bullet(New DxVB.DxImage)
Player.SetPosition(PlayerX, PlayerY, PlayerZ)
Player.SetScale(PlayerSize, PlayerSize, PlayerSize)
Player.IsEnabled = True
OriPlayer = Player.GetPosition()
GameCenter = New Bullet()
GameCenter.SetPosition(CenterX, CenterY, CenterZ)
GameRange = Range : DefaultTex = DefaultTexture
Graze = 0 : Miss = 0 : Num = 0
End Sub
Public Sub New(ByVal ArrayNum1 As Integer, ByVal ArrayNum2 As Integer, ByVal CenterX As Double, ByVal CenterY As Double, ByVal CenterZ As Double, ByVal Range As Double, _
ByVal PlayerX As Double, ByVal PlayerY As Double, ByVal PlayerZ As Double, ByVal PlayerSize As Double, ByVal DefaultTexture As Integer)
ArrayNumA = ArrayNum1
ArrayNumB = ArrayNum2
ReDim Bullets(ArrayNumA, ArrayNumB)
InitBullet()
Player = New Bullet(New DxVB.DxImage)
Player.SetPosition(PlayerX, PlayerY, PlayerZ)
Player.SetScale(PlayerSize, PlayerSize, PlayerSize)
Player.IsEnabled = True
OriPlayer = Player.GetPosition()
GameCenter = New Bullet()
GameCenter.SetPosition(CenterX, CenterY, CenterZ)
CorePosition = New Bullet()
CorePosition.SetPosition(CenterX, CenterY, CenterZ)
GameRange = Range : DefaultTex = DefaultTexture
'STGThread = New Thread(JudgeACtrl)
End Sub
Public Sub New(ByVal ArrayNum1 As Integer, ByVal ArrayNum2 As Integer, ByVal CenterX As Double, ByVal CenterY As Double, ByVal CenterZ As Double)
ArrayNumA = ArrayNum1
ArrayNumB = ArrayNum2
ReDim Bullets(ArrayNumA, ArrayNumB)
InitBullet()
CorePosition = New Bullet()
CorePosition.SetPosition(CenterX, CenterY, CenterZ)
'STGThread = New Thread(JudgeACtrl)
End Sub
Public Sub Run()
'STGThread.Start();
End Sub
Public Sub Close()
'STGThread.Abort();
End Sub
Public Sub GetInfo(ByVal x As Single, ByVal y As Single)
DxVB.DrawString("Graze: " + Graze.ToString(), x, y, 20)
DxVB.DrawString("Miss:" + Miss.ToString(), x, y + 25, 20)
DxVB.DrawString("Num: " + Num.ToString(), x, y + 50, 20)
End Sub
Public Shared Sub GetInfo(ByRef Miss As Integer, ByRef Graze As Integer, ByRef Num As Integer)
Miss = STGCore.Miss : Graze = STGCore.Graze : Num = STGCore.Num
End Sub
Public Function GetCenter() As Base.Point3D
Return CorePosition.GetPosition()
End Function
Public Sub SetCenter(ByVal Point As Base.Point3D)
CorePosition.SetPosition(Point)
End Sub
Private Sub InitBullet()
For i = 0 To Bullets.GetUpperBound(0) Step 1
For j = 0 To Bullets.GetUpperBound(1) Step 1
Bullets(i, j) = New Bullet()
Next j
Next i
End Sub
Public Sub MainCircle()
GenBullet()
JudgeBullet()
DrawBullet()
End Sub
Public Sub MainCircle(ByVal Time As Long, ByVal JmpRate As Integer)
GenBullet()
JudgeBullet()
If Time Mod JmpRate = 0 Then DrawBullet()
End Sub
Protected Overridable Sub GenBullet()
Dim TmpPoint As Base.Point3D
For i = 0 To ArrayNumA - 1
For j = 0 To ArrayNumB - 1
If Not Bullets(i, j).IsEnabled Then
TmpPoint.x = CorePosition.GetPosition().x
TmpPoint.y = CorePosition.GetPosition().y
TmpPoint.z = CorePosition.GetPosition().z
Bullets(i, j).SetPosition(TmpPoint)
Bullets(i, j).SetScale(20, 20, 20)
Bullets(i, j).IsEnabled = True
End If
TmpPoint.x = 0
TmpPoint.y = 0
TmpPoint.z = 0
TmpPoint.x = Bullets(i, j).GetPosition().x + TmpPoint.x
TmpPoint.y = Bullets(i, j).GetPosition().y + TmpPoint.y
TmpPoint.z = Bullets(i, j).GetPosition().z + TmpPoint.z
If Base.Distance3D(Bullets(i, j).GetPosition(), GameCenter.GetPosition()) > GameRange Then
Bullets(i, j) = New EngineCore.STG3D.Bullet()
End If
Next j
Next i
End Sub
Protected Overridable Sub DrawBullet()
For i = 0 To Bullets.GetUpperBound(0) Step 1
For j = 0 To Bullets.GetUpperBound(1) Step 1
If Bullets(i, j).IsEnabled Then Bullets(i, j).Draw()
Next j
Next i
DrawPlayer()
End Sub
Protected Shared Sub DrawPlayer()
Player.Draw()
End Sub
Protected Overridable Sub JudgeBullet()
Num = 0
For i = 0 To Bullets.GetUpperBound(0) Step 1
For j = 0 To Bullets.GetUpperBound(1) Step 1
If Bullets(i, j).IsEnabled Then
If GameCenter.PreJudge(Bullets(i, j).GetPosition(), GameRange) Then
Num = Num + 1
Else
Bullets(i, j) = New Bullet()
End If
End If
Next j
Next i
For i = 0 To Bullets.GetUpperBound(0) Step 1
For j = 0 To Bullets.GetUpperBound(1) Step 1
If Bullets(i, j).IsEnabled Then
If Bullets(i, j).IsEnabled And Player.PreJudge(Bullets(i, j).GetPosition(), GameRange) Then
If Player.Judge(Bullets(i, j).GetPosition()) = JUDGE_AWAY And Not Bullets(i, j).IsGrazed Then
Bullets(i, j).IsGrazed = True
End If
If Player.Judge(Bullets(i, j).GetPosition()) = JUDGE_GRAZE And Bullets(i, j).IsGrazed Then
Bullets(i, j).IsGrazed = False
Graze = Graze + 1
End If
If Player.Judge(Bullets(i, j).GetPosition()) = JUDGE_MISS Then
Bullets(i, j) = New Bullet()
Miss = Miss + 1
Player.SetPosition(OriPlayer)
End If
End If
End If
Next j
Next i
End Sub
Public Shared Sub Control()
Dim TmpPos As Base.Point3D
TmpPos = Player.GetPosition()
If DefaultTex = TEX_SPHERE Then
If Base.GetKey(Base.Keys.KeyLSHIFT) Or Base.GetKey(Base.Keys.KeyRSHIFT) Then
If Base.GetKey(Base.Keys.KeyUP) Then
TmpPos.z = TmpPos.z + 3
End If
If Base.GetKey(Base.Keys.KeyDOWN) Then
TmpPos.z = TmpPos.z - 3
End If
If Base.GetKey(Base.Keys.KeyLEFT) Then
TmpPos.x = TmpPos.x - 3
End If
If Base.GetKey(Base.Keys.KeyRIGHT) Then
TmpPos.x = TmpPos.x + 3
End If
Else
If Base.GetKey(Base.Keys.KeyUP) Then
TmpPos.z = TmpPos.z + 5
End If
If Base.GetKey(Base.Keys.KeyDOWN) Then
TmpPos.z = TmpPos.z - 5
End If
If Base.GetKey(Base.Keys.KeyLEFT) Then
TmpPos.x = TmpPos.x - 5
End If
If Base.GetKey(Base.Keys.KeyRIGHT) Then
TmpPos.x = TmpPos.x + 5
End If
End If
Else
If Base.GetKey(Base.Keys.KeyLSHIFT) Or Base.GetKey(Base.Keys.KeyRSHIFT) Then
If Base.GetKey(Base.Keys.KeyUP) Then
TmpPos.z = TmpPos.z - 3
End If
If Base.GetKey(Base.Keys.KeyDOWN) Then
TmpPos.z = TmpPos.z + 3
End If
If Base.GetKey(Base.Keys.KeyLEFT) Then
TmpPos.x = TmpPos.x - 3
End If
If Base.GetKey(Base.Keys.KeyRIGHT) Then
TmpPos.x = TmpPos.x + 3
End If
Else
If Base.GetKey(Base.Keys.KeyUP) Then
TmpPos.z = TmpPos.z - 6
End If
If Base.GetKey(Base.Keys.KeyDOWN) Then
TmpPos.z = TmpPos.z + 6
End If
If Base.GetKey(Base.Keys.KeyLEFT) Then
TmpPos.x = TmpPos.x - 6
End If
If Base.GetKey(Base.Keys.KeyRIGHT) Then
TmpPos.x = TmpPos.x + 6
End If
End If
End If
If GameCenter.PreJudge(TmpPos, 432, 1, 504) Then Player.SetPosition(TmpPos)
End Sub
End Class这是我用的STG类,应该能做下参考。
继承STGCore类,重写GenBullet,再创建对象,执行MainCircle。
对于帧率控制
Public Class FPSCounter
' 进行帧率计算和控制的类
' 此类需要实例化
' 精度为小数点后一位
' 其中的Update要加入主游戏循环
Private StartTime As Integer
Private Count As Integer
Private FPSNum As Single
Private Const N As Integer = 60
Private Const FPS As Integer = 60
Public Sub New()
StartTime = 0
Count = 0
FPSNum = 0
End Sub
Public Sub Update()
If Count = 0 Then
StartTime = System.Environment.TickCount
End If
If Count = N Then
Dim TmpTime As Integer = System.Environment.TickCount
FPSNum = 1000.0F / ((CType(TmpTime, Single) - CType(StartTime, Single)) / CType(N, Single))
Count = 0
StartTime = TmpTime
End If
Count = Count + 1
End Sub
Public Sub WaitTime()
Dim TookTime As Integer = System.Environment.TickCount - StartTime
Dim WaitTime As Integer = Count * 1000 / FPS - TookTime
If WaitTime > 0 Then
DX.WaitTimer(WaitTime)
End If
End Sub
Public Function GetFPS(ByVal Digits As Integer) As Single
Return Math.Round(FPSNum, Digits)
End Function
Public Function GetFPS() As Single
Return FPSNum
End Function
End Class感觉还是垂直同步方便(((
页:
[1]
2