|
-
Mar 31st, 2005, 05:11 PM
#1
Thread Starter
Hyperactive Member
About as bad as it can be
VB Code:
Public Sub Collision()
For X = 1 To MaxBullets
With Bullet(X)
'makes sure it is visible, has moved, and can move
If .Visible = True And .Moved = True And .Move = True Then
'Gets rid of bullets outside of the arena (move to collision
If .Left > ArenaWidth Then
BulletCollideEffects (X), ArenaWidth - .Width, .Top, plat(1), True
ElseIf .Left < 0 Then
BulletCollideEffects (X), 0, .Top, plat(1), True
ElseIf .Top < 0 Then
BulletCollideEffects (X), .Left, 0, plat(1), False
ElseIf .Top > ArenaHeight Then
BulletCollideEffects (X), .Left, ArenaHeight - .Height, plat(1), False
End If
If .Xinertia = 0 Then .Xinertia = 1 'prevent divide by 0
M = .Yinertia / .Xinertia 'find slope
If M = 0 Then M = 0.001 'prevent divide by 0
'y intercept for top left (b) and bottom right(bb)
B = (.Top - .Yinertia) - (M * (.Left - .Xinertia))
BB = ((.Top + .Height) - .Yinertia) - (M * ((.Left + .Width) - .Xinertia))
For Y = 1 To PlatCount
If plat(Y).Visible Then
'finds the point where it passes each side
Ty = plat(Y).Top
Tx = (B - Ty) / -M
Tbx = (BB - Ty) / -M
Hy = plat(Y).Top + plat(Y).Height
Hx = (B - Hy) / -M
Hbx = (BB - Hy) / -M
Lx = plat(Y).Left
Ly = M * Lx + B
Lby = M * Lx + BB
Wx = plat(Y).Left + plat(Y).Width
Wy = M * Wx + B
Wby = M * Wx + BB
'makes sure that it crosses the line inside the block
If Ly >= plat(Y).Top And Ly <= plat(Y).Top + plat(Y).Height And .Left >= Lx And .Left - .Xinertia <= Lx Then
BulletCollideEffects (X), Lx - .Width, (Ly), plat(Y), True
ElseIf Wy >= plat(Y).Top And Wy <= plat(Y).Top + plat(Y).Height And .Left <= Wx And .Left - .Xinertia >= Wx Then
BulletCollideEffects (X), (Wx), (Wy), plat(Y), True
ElseIf Lby >= plat(Y).Top And Lby <= plat(Y).Top + plat(Y).Height And .Left >= Lx And .Left - .Xinertia <= Lx Then
BulletCollideEffects (X), Lx - .Width, Lby - .Height, plat(Y), True
ElseIf Wby >= plat(Y).Top And Wby <= plat(Y).Top + plat(Y).Height And .Left <= Wx And .Left - .Xinertia >= Wx Then
BulletCollideEffects (X), (Wx), Wby - .Height, plat(Y), True
End If
If Tx >= plat(Y).Left And Tx <= plat(Y).Left + plat(Y).Width And .Top >= Ty And .Top - .Yinertia <= Ty Then
BulletCollideEffects (X), (Tx), Ty - .Height, plat(Y), False
ElseIf Hx >= plat(Y).Left And Hx <= plat(Y).Left + plat(Y).Width And .Top <= Hy And .Top - .Yinertia >= Hy Then
BulletCollideEffects (X), (Hx), (Hy), plat(Y), False
ElseIf Tbx >= plat(Y).Left And Tbx <= plat(Y).Left + plat(Y).Width And .Top >= Ty And .Top - .Yinertia <= Ty Then
BulletCollideEffects (X), Tbx - .Width, Ty - .Height, plat(Y), False
ElseIf Hbx >= plat(Y).Left And Hbx <= plat(Y).Left + plat(Y).Width And .Top <= Hy And .Top - .Yinertia >= Hy Then
BulletCollideEffects (X), Hbx - .Width, (Hy), plat(Y), False
End If
End If
Next Y
For Y = 1 To PlayerCount
If player(Y).Visible Then
'finds the point where it passes each side
Ty = player(Y).Top
Tx = (B - Ty) / -M
Tbx = (BB - Ty) / -M
Hy = player(Y).Top + player(Y).Height
Hx = (B - Hy) / -M
Hbx = (BB - Hy) / -M
Lx = player(Y).Left
Ly = M * Lx + B
Lby = M * Lx + BB
Wx = player(Y).Left + player(Y).Width
Wy = M * Wx + B
Wby = M * Wx + BB
'makes sure that it crosses the line inside the block
If Ly >= player(Y).Top And Ly <= player(Y).Top + player(Y).Height And .Left >= Lx And .Left - .Xinertia <= Lx Then
BulletCollideEffects (X), Lx - .Width, (Ly), player(Y), True
ElseIf Wy >= player(Y).Top And Wy <= player(Y).Top + player(Y).Height And .Left <= Wx And .Left - .Xinertia >= Wx Then
BulletCollideEffects (X), (Wx), (Wy), player(Y), True
ElseIf Lby >= player(Y).Top And Lby <= player(Y).Top + player(Y).Height And .Left >= Lx And .Left - .Xinertia <= Lx Then
BulletCollideEffects (X), Lx - .Width, Lby - .Height, player(Y), True
ElseIf Wby >= player(Y).Top And Wby <= player(Y).Top + player(Y).Height And .Left <= Wx And .Left - .Xinertia >= Wx Then
BulletCollideEffects (X), (Wx), Wby - .Height, player(Y), True
End If
If Tx >= player(Y).Left And Tx <= player(Y).Left + player(Y).Width And .Top >= Ty And .Top - .Yinertia <= Ty Then
BulletCollideEffects (X), (Tx), Ty - .Height, player(Y), False
ElseIf Hx >= player(Y).Left And Hx <= player(Y).Left + player(Y).Width And .Top <= Hy And .Top - .Yinertia >= Hy Then
BulletCollideEffects (X), (Hx), (Hy), player(Y), False
ElseIf Tbx >= player(Y).Left And Tbx <= player(Y).Left + player(Y).Width And .Top >= Ty And .Top - .Yinertia <= Ty Then
BulletCollideEffects (X), Tbx - .Width, Ty - .Height, player(Y), False
ElseIf Hbx >= player(Y).Left And Hbx <= player(Y).Left + player(Y).Width And .Top <= Hy And .Top - .Yinertia >= Hy Then
BulletCollideEffects (X), Hbx - .Width, (Hy), player(Y), False
End If
End If
Next Y
End If
If Bullet(X).Type = 1 Then
For Y = 1 To PlayerCount
If collide(Bullet(X), player(Y)) = True And Bullet(X).Belong <> (Y) And Bullet(X).Visible = True Then
player(Y).Xinertia = Bullet(X).Xinertia
player(Y).Yinertia = Bullet(X).Yinertia
player(Y).Life = player(Y).Life - GT(1).Power
End If
Next Y
End If
If .Visible And .Kiboshed Then
For Y = 1 To PlayerCount
If player(Y).OnFire = False And player(Y).Visible And collide(player(Y), Bullet(X)) And GT(.Type).Explode Then
CenterX = .Left + (.Width / 2)
CenterY = .Top + (.Height / 2)
CenterX2 = player(Y).Left + (player(Y).Width / 2)
CenterY2 = player(Y).Top + (player(Y).Height / 2)
'absolute of cursor position
XXX = Abs(CenterX2 - CenterX)
YYY = Abs(CenterY - CenterY2)
'Makes sure you do not divide by 0
If XXX = 0 Then
Angle = 0
Else
'find angle
Angle = Atn(YYY / XXX)
End If
'finds absolute x and y aim
XXX = RR * Cos(Angle)
YYY = RR * Sin(Angle)
'Sets result aiming co-ordinates
player(Y).Xinertia = Sgn(CenterX2 - CenterX) * XXX / 20
player(Y).Yinertia = (Sgn(CenterY2 - CenterY) * YYY) / 20
'other effects
player(Y).OnFire = True
player(Y).Firetime = 40
player(Y).Life = player(Y).Life - 10
End If
Next Y
End If
End With
Next X
This is my collision sub, it checks (almost) every collision in my game however it is VERY redundant as you can see but i cant figure out how to shrink it
also note that collide is a function elsewhere in the code for finding if two things are actually touching where the majority of this code is for objects moving over something and finding if and where they should have hit
and if you were wondering, that is the bulletcollideeffects sub
It's not just Good, It's Good enough!
Spelling Eludes Me
-
Mar 31st, 2005, 05:12 PM
#2
Thread Starter
Hyperactive Member
Re: About as bad as it can be
this is the bullet collide effects sub if you were wondering
VB Code:
Public Sub BulletCollideEffects(BulletNum As Integer, X As Integer, Y As Integer, WhoHit As Bltty, HitSide As Boolean)
With Bullet(BulletNum)
.Top = Y
.Left = X
If WhoHit.Move = True Then
WhoHit.Xinertia = WhoHit.Xinertia + (.Xinertia * GT(.Type).Weight)
WhoHit.Yinertia = WhoHit.Yinertia + (.Yinertia * GT(.Type).Weight)
WhoHit.Life = WhoHit.Life - GT(.Type).Power
If .Type = 3 Then
WhoHit.OnFire = True
WhoHit.Firetime = 10
End If
KillBullet BulletNum
ElseIf GT(.Type).Bounce = True And HitSide = True Then
.Xinertia = .Xinertia * -1
Moved = False
ElseIf GT(.Type).Bounce = True Then
.Yinertia = .Yinertia * -1
Moved = False
Else
.Move = False
KillBullet BulletNum
End If
End With
End Sub
It's not just Good, It's Good enough!
Spelling Eludes Me
-
Apr 1st, 2005, 12:47 AM
#3
Re: About as bad as it can be
Show the code where you declared your variables (all of them that are in these Subs) so I can see what data types you are using.
Here is one area you can increase some speed. The Cos() and Sin() functions. Rather than using them, let's create some lookup tables. This is based on Andre Lamothe's code in my Tricks of the 3D Game Programming Gurus book written by him.
VB Code:
Public Const PI As Double = 3.14159265358979 '4 * Atn(1)
Public Cos_Look_Up_Table(361) As Single
Public Sin_Look_Up_Table(361) As Single
Public Sub Build_Sin_Cos_Tables()
Dim Angle As Long
For Angle = 0 To 360
Dim Theta As Single
Theta = Angle * PI / 180
Cos_Look_Up_Table(Angle) = Cos(Theta)
Sin_Look_Up_Table(Angle) = Sin(Theta)
Next Angle
End Sub
Public Function Fast_Cos(ByVal Theta As Single) As Single
Theta = Theta Mod 360
If Theta < 0 Then Theta = Theta + 360
Dim Theta_Integer As Long
Dim Theta_Fraction As Single
Theta_Integer = Theta
Theta_Fraction = Theta - Theta_Integer
Fast_Cos = Cos_Look_Up_Table(Theta_Integer) + Theta_Fraction * (Cos_Look_Up_Table(Theta_Integer + 1) - Cos_Look_Up_Table(Theta_Integer))
End Function
Public Function Fast_Sin(ByVal Theta As Single) As Single
Theta = Theta Mod 360
If Theta < 0 Then Theta = Theta + 360
Dim Theta_Integer As Long
Dim Theta_Fraction As Single
Theta_Integer = Theta
Theta_Fraction = Theta - Theta_Integer
Fast_Sin = Sin_Look_Up_Table(Theta_Integer) + Theta_Fraction * (Sin_Look_Up_Table(Theta_Integer + 1) - Sin_Look_Up_Table(Theta_Integer))
End Function
Then you add the line Build_Sin_Cos_Tables in the area where you initialize everything to build a look up table, and then use Fast_Cos() and Fast_Sin() in replace of your Cos() and Sin() functions. 
Another area to improve is this area:
VB Code:
BulletCollideEffects(BulletNum As Integer, X As Integer, Y As Integer, WhoHit As Bltty, HitSide As Boolean)
Never use the Integer data type unless it's needed, like for example, API's. For a good speed difference, use the Long data type. Here are the reasons. 1) Don't have to worry about overflow that much. 2) Your CPU processor in your computer is 32 bit, and works with 32 bit variables faster. The Long data type is 4 bytes (32 bits) while the Integer data type is only 2 bytes (16 bits), and the processor will have to convert it in order to accomidate.
And also be sure to either include ByVal or ByRef. Leaving it blank, although by default it'll be ByRef, every time the function is called, it's somewhat slower. Using ByVal is faster. Only use ByRef if your varables in your arguements are gonna be returning a result. Only thing is though you can't use ByVal on variables that are User Defined Types, such as Blitty.
Now I got that out of the way, here is your new and improved Sub setup:
VB Code:
BulletCollideEffects(ByVal BulletNum As Long, ByVal X As Long, ByVal Y As Long, WhoHit As Bltty, ByVal HitSide As Boolean)
Last edited by Jacob Roman; Apr 1st, 2005 at 01:08 AM.
-
Apr 3rd, 2005, 03:56 PM
#4
Thread Starter
Hyperactive Member
Re: About as bad as it can be
"Only use ByRef if your varables in your arguements are gonna be returning a result"
???
what does byval do
It's not just Good, It's Good enough!
Spelling Eludes Me
-
Apr 3rd, 2005, 05:00 PM
#5
Re: About as bad as it can be
ByVal variables in the arguements don't return values. If you were to do something like this:
VB Code:
Option Explicit
Private Sub Test(ByVal Testing As Long)
Testing = 5
End Sub
Private Sub Test2(ByRef Testing As Long)
Testing = 5
End Sub
Private Sub Form_Activate()
Dim I As Long
Test I
Print I 'Returns 0
Test2 I
Print I 'Returns 5
End Sub
You would see that ByVal did not make the variable I equal 5. It stayed the same value as it was before. But when I used ByRef, it made I equal 5. Hope this helps.
-
Apr 4th, 2005, 06:28 PM
#6
Thread Starter
Hyperactive Member
Re: About as bad as it can be
It's not just Good, It's Good enough!
Spelling Eludes Me
-
Apr 12th, 2005, 01:26 PM
#7
Hyperactive Member
Re: About as bad as it can be
 Originally Posted by notquitehere188
[Highlight=VB] Public Sub Collision()
This is my collision sub, it checks (almost) every collision in my game however it is VERY redundant as you can see but i cant figure out how to shrink it
also note that collide is a function elsewhere in the code for finding if two things are actually touching where the majority of this code is for objects moving over something and finding if and where they should have hit
and if you were wondering, that is the bulletcollideeffects sub
Well the first thing I noticed is that you're using divison a lot with a variable called M. After you setup M, dividie it into 1 one time. After that use multiplication to get you're divison results.
Tx = (B - Ty) * -M
Tbx = (BB - Ty) * -M
You may have to use an extra variable but you'll be trading 8 division instructions for 8 multiplication instuctions. Should give you an instant speedup.
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
-
Apr 13th, 2005, 02:17 AM
#8
Hyperactive Member
Re: About as bad as it can be
 Originally Posted by Maven
Well the first thing I noticed is that you're using divison a lot with a variable called M. After you setup M, dividie it into 1 one time. After that use multiplication to get you're divison results.
Tx = (B - Ty) * -M
Tbx = (BB - Ty) * -M
You may have to use an extra variable but you'll be trading 8 division instructions for 8 multiplication instuctions. Should give you an instant speedup.
In fact if the following doesn't change with every iteration of the loop, then i would move it outside of the loops and setup the above suggestion outside of the loop.
M = .Yinertia / .Xinertia 'find slope
Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde
-
May 3rd, 2005, 04:47 PM
#9
Hyperactive Member
Re: About as bad as it can be
 Originally Posted by Jacob Roman
Show the code where you declared your variables (all of them that are in these Subs) so I can see what data types you are using.
Here is one area you can increase some speed. The Cos() and Sin() functions. Rather than using them, let's create some lookup tables. This is based on Andre Lamothe's code in my Tricks of the 3D Game Programming Gurus book written by him.
VB Code:
Public Const PI As Double = 3.14159265358979 '4 * Atn(1)
Public Cos_Look_Up_Table(361) As Single
Public Sin_Look_Up_Table(361) As Single
Public Sub Build_Sin_Cos_Tables()
Dim Angle As Long
For Angle = 0 To 360
Dim Theta As Single
Theta = Angle * PI / 180
Cos_Look_Up_Table(Angle) = Cos(Theta)
Sin_Look_Up_Table(Angle) = Sin(Theta)
Next Angle
End Sub
Public Function Fast_Cos(ByVal Theta As Single) As Single
Theta = Theta Mod 360
If Theta < 0 Then Theta = Theta + 360
Dim Theta_Integer As Long
Dim Theta_Fraction As Single
Theta_Integer = Theta
Theta_Fraction = Theta - Theta_Integer
Fast_Cos = Cos_Look_Up_Table(Theta_Integer) + Theta_Fraction * (Cos_Look_Up_Table(Theta_Integer + 1) - Cos_Look_Up_Table(Theta_Integer))
End Function
Public Function Fast_Sin(ByVal Theta As Single) As Single
Theta = Theta Mod 360
If Theta < 0 Then Theta = Theta + 360
Dim Theta_Integer As Long
Dim Theta_Fraction As Single
Theta_Integer = Theta
Theta_Fraction = Theta - Theta_Integer
Fast_Sin = Sin_Look_Up_Table(Theta_Integer) + Theta_Fraction * (Sin_Look_Up_Table(Theta_Integer + 1) - Sin_Look_Up_Table(Theta_Integer))
End Function
Then you add the line Build_Sin_Cos_Tables in the area where you initialize everything to build a look up table, and then use Fast_Cos() and Fast_Sin() in replace of your Cos() and Sin() functions.
Another area to improve is this area:
VB Code:
BulletCollideEffects(BulletNum As Integer, X As Integer, Y As Integer, WhoHit As Bltty, HitSide As Boolean)
Never use the Integer data type unless it's needed, like for example, API's. For a good speed difference, use the Long data type. Here are the reasons. 1) Don't have to worry about overflow that much. 2) Your CPU processor in your computer is 32 bit, and works with 32 bit variables faster. The Long data type is 4 bytes (32 bits) while the Integer data type is only 2 bytes (16 bits), and the processor will have to convert it in order to accomidate.
And also be sure to either include ByVal or ByRef. Leaving it blank, although by default it'll be ByRef, every time the function is called, it's somewhat slower. Using ByVal is faster. Only use ByRef if your varables in your arguements are gonna be returning a result. Only thing is though you can't use ByVal on variables that are User Defined Types, such as Blitty.
Now I got that out of the way, here is your new and improved Sub setup:
VB Code:
BulletCollideEffects(ByVal BulletNum As Long, ByVal X As Long, ByVal Y As Long, WhoHit As Bltty, ByVal HitSide As Boolean)
The amount of calculations (especially the conversion between integer and floating points) by far exceeds the normal amount of work done using the floating-point processor alone.
It is far wiser to stay using doubles or singles than to constantly convert between to and from integer formats. The process of loading an integer into a floating-point register is long enough; and the floating-point processor already has an instruction to calculate the sine of the value in the register. This is far more efficient than constantly converting between two types and jumping around memory, and adding latency by performing extra calculations.
Consider the following and assume x, a and b are integers:
x = 1.5 * b - a + 3
We could load all constants into the floating point registers, which would be highly inefficient, but we would still acheive results (inefficient because we would have to convert the result back to integers). Instead, we could cast the result of the floating point calculation so that it forces the remaining calculations to be done with integer operations. This is quicker than allowing all operands to be converted to floating point.
x = CLng(1.5 * b) - a + 3
Bearing this in mind, you could save on latency times, and just the tiniest improvements can go a long way in a lengthy loop.
I can see how the sine tables would improve performance on a CPU without an FPU co-processor, but even the AMD efficiency guide shows you should never use tables for sine.
Last edited by Dreamlax; May 3rd, 2005 at 04:53 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|