Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
VERSION 1.0 CLASS
|
||||
BEGIN
|
||||
MultiUse = -1 'True
|
||||
Persistable = 0 'NotPersistable
|
||||
DataBindingBehavior = 0 'vbNone
|
||||
DataSourceBehavior = 0 'vbNone
|
||||
MTSTransactionMode = 0 'NotAnMTSObject
|
||||
END
|
||||
Attribute VB_Name = "cPuck"
|
||||
Attribute VB_GlobalNameSpace = False
|
||||
Attribute VB_Creatable = True
|
||||
Attribute VB_PredeclaredId = False
|
||||
Attribute VB_Exposed = False
|
||||
Option Explicit
|
||||
|
||||
Private Const mnMaxSpinSpeed As Single = 0.9
|
||||
'Here we will encapsulate all of the code needed for the puck
|
||||
'Local variables for the properties of the puck
|
||||
Private moPosition As D3DVECTOR 'Current position of the puck
|
||||
Private moVelocity As D3DVECTOR 'Current velocity of the puck
|
||||
Private moLastPosition As D3DVECTOR 'Last position of the puck
|
||||
|
||||
Public Spinning As Boolean 'Is the puck currently spinning?
|
||||
Public MaximumPuckVelocity As Single
|
||||
|
||||
Private mnSpinDir As Single 'Direction of the pucks spinning
|
||||
Private mlPuckTime As Long 'Last time the puck was updated
|
||||
Private mnPuckSpin As Single
|
||||
|
||||
Private moPuck As CD3DFrame 'D3D Mesh for the puck
|
||||
'Default spin speed
|
||||
Private mnDefaultSpin As Single
|
||||
|
||||
'Position property
|
||||
Public Property Let Position(oPos As D3DVECTOR)
|
||||
moPosition = oPos
|
||||
End Property
|
||||
|
||||
Public Property Get Position() As D3DVECTOR
|
||||
Position = moPosition
|
||||
End Property
|
||||
|
||||
'Velocity property
|
||||
Public Property Let Velocity(oVel As D3DVECTOR)
|
||||
moVelocity = oVel
|
||||
'Update the velocity, but make sure it isn't too high
|
||||
EnsurePuckVelocityIsBelowMax
|
||||
End Property
|
||||
|
||||
Public Property Get Velocity() As D3DVECTOR
|
||||
Velocity = moVelocity
|
||||
End Property
|
||||
|
||||
'LastPosition prop
|
||||
Public Property Let LastPosition(oLastPos As D3DVECTOR)
|
||||
moLastPosition = oLastPos
|
||||
End Property
|
||||
|
||||
Public Property Get LastPosition() As D3DVECTOR
|
||||
LastPosition = moLastPosition
|
||||
End Property
|
||||
|
||||
'Different methods from the puck.
|
||||
Public Sub Init(ByVal sMedia As String, sFile As String)
|
||||
Set moPuck = D3DUtil_LoadFromFile(AddDirSep(sMedia) & sFile, Nothing, Nothing)
|
||||
End Sub
|
||||
|
||||
Public Sub UpdatePosition()
|
||||
Dim RealVelocity As D3DVECTOR
|
||||
|
||||
'Here we will update the position of the puck
|
||||
'and move it based on the velocity assigned.
|
||||
If mlPuckTime = 0 Then mlPuckTime = timeGetTime
|
||||
'First calculate the 'real' velocity (based on the time)
|
||||
RealVelocity.X = ((timeGetTime - mlPuckTime) / 100) * moVelocity.X
|
||||
RealVelocity.Y = ((timeGetTime - mlPuckTime) / 100) * moVelocity.Y
|
||||
RealVelocity.z = ((timeGetTime - mlPuckTime) / 100) * moVelocity.z
|
||||
'Let's save our current position
|
||||
moLastPosition = moPosition
|
||||
|
||||
moPosition.X = moPosition.X + RealVelocity.X
|
||||
moPosition.Y = moPosition.Y + RealVelocity.Y
|
||||
moPosition.z = moPosition.z + RealVelocity.z
|
||||
|
||||
If Spinning Then
|
||||
'Update Puck Spin
|
||||
mnPuckSpin = mnPuckSpin + ((((timeGetTime - mlPuckTime) / 100) * mnDefaultSpin) * mnSpinDir)
|
||||
If mnPuckSpin > 2 * g_pi Then mnPuckSpin = 0
|
||||
End If
|
||||
|
||||
mlPuckTime = timeGetTime
|
||||
End Sub
|
||||
|
||||
Public Sub Render(dev As Direct3DDevice8)
|
||||
Dim matRot As D3DMATRIX, matTrans As D3DMATRIX
|
||||
Dim matPuck As D3DMATRIX
|
||||
|
||||
D3DXMatrixRotationAxis matRot, vec3(0, 1, 0), mnPuckSpin
|
||||
D3DXMatrixTranslation matTrans, moPosition.X, moPosition.Y, moPosition.z
|
||||
D3DXMatrixMultiply matPuck, matRot, matTrans
|
||||
|
||||
moPuck.SetMatrix matPuck
|
||||
moPuck.Render dev
|
||||
|
||||
End Sub
|
||||
|
||||
Public Sub LaunchPuck()
|
||||
Randomize
|
||||
DefaultStartPosition
|
||||
Do While (D3DXVec3Length(moVelocity) < (MaximumPuckVelocity / 4)) And (Abs(moVelocity.z) < 0.2) 'Make sure there is *some* z movement
|
||||
moVelocity.z = Rnd * (MaximumPuckVelocity / 3)
|
||||
moVelocity.X = Rnd * (MaximumPuckVelocity / 3)
|
||||
If Rnd > 0.5 Then moVelocity.X = moVelocity.X * -1
|
||||
If Rnd < 0.5 Then moVelocity.z = moVelocity.z * -1
|
||||
Loop
|
||||
End Sub
|
||||
|
||||
Public Sub DefaultStartPosition()
|
||||
moPosition = vec3(0, 2.5, 0)
|
||||
moVelocity = vec3(0, 0, 0)
|
||||
moLastPosition = vec3(0, 0, 0)
|
||||
End Sub
|
||||
|
||||
Public Sub ChangePuckVelocity(oPaddle As cPaddle, oAudio As cAudio, Optional ByVal fIgnoreMax As Boolean = False)
|
||||
|
||||
Dim vDir As D3DVECTOR
|
||||
Dim a As Single, b As Single, c As Single
|
||||
Dim t0 As Single, t1 As Single
|
||||
Dim vIntersect As D3DVECTOR, vIntersectHigh As D3DVECTOR
|
||||
Dim oPlane As D3DPLANE, matReflect As D3DMATRIX
|
||||
Dim oPoint As D3DVECTOR, vNewVelDir As D3DVECTOR
|
||||
Dim vPuck As D3DVECTOR, tSmall As Single
|
||||
Dim nVelocity As Single, nVelocityPaddle As Single
|
||||
Dim vNewVelPad As D3DVECTOR
|
||||
|
||||
'We hit with the paddle, randomly change the spin direction
|
||||
UpdatePuckSpin
|
||||
glPaddleCollideTime = timeGetTime
|
||||
'gfRecentlyHitPaddle = True
|
||||
'Notify the user that the puck hit the paddle by playing a sound
|
||||
If Not (oAudio Is Nothing) Then oAudio.PlayHitSound
|
||||
'Let's store the original velocity
|
||||
nVelocity = D3DXVec3Length(moVelocity)
|
||||
nVelocityPaddle = D3DXVec3Length(oPaddle.Velocity) * gnPaddleMass
|
||||
'First we need to find the intersection point
|
||||
'To do that we first need to solve for t:
|
||||
'x = Dxt + x0
|
||||
'z = Dzt + z0
|
||||
D3DXVec3Subtract vPuck, moPosition, oPaddle.Position
|
||||
D3DXVec3Normalize vDir, moVelocity
|
||||
a = 1 ' (vDir.x ^ 2) + (vDir.z ^ 2) will always be one since the vector is normalized
|
||||
b = (2 * vPuck.X * vDir.X) + (2 * vPuck.z * vDir.z)
|
||||
c = ((vPuck.X ^ 2) + (vPuck.z ^ 2) - ((gnPaddleRadius + gnPuckRadius) ^ 2))
|
||||
't = (-b <20> SQR(b<>-4ac))/2a
|
||||
If (b ^ 2) - (4 * a * c) > 0 Then
|
||||
t0 = (-b + Sqr((b ^ 2) - (4 * a * c))) / (2 * a)
|
||||
t1 = (-b - Sqr((b ^ 2) - (4 * a * c))) / (2 * a)
|
||||
Else 'We shouldn't hit this case, but just in case.
|
||||
t0 = 0
|
||||
t1 = 0
|
||||
End If
|
||||
|
||||
Dim vInt1 As D3DVECTOR, vInt2 As D3DVECTOR
|
||||
Dim vDifInt1 As D3DVECTOR, vDifInt2 As D3DVECTOR
|
||||
'Find both possible intersection points
|
||||
vInt1.X = (vDir.X * t0) + vPuck.X: vInt1.z = (vDir.z * t0) + vPuck.z
|
||||
vInt2.X = (vDir.X * t1) + vPuck.X: vInt2.z = (vDir.z * t1) + vPuck.z
|
||||
'Find the difference from the starting location
|
||||
D3DXVec3Subtract vDifInt1, oPaddle.Position, vInt1
|
||||
D3DXVec3Subtract vDifInt2, oPaddle.Position, vInt2
|
||||
|
||||
'Find the smallest t
|
||||
'If t0 > t1 Then
|
||||
If D3DXVec3Length(vDifInt1) < D3DXVec3Length(vDifInt2) Then
|
||||
tSmall = t1
|
||||
Else
|
||||
tSmall = t0
|
||||
End If
|
||||
'Let's get the intersected point
|
||||
vIntersect.X = (vDir.X * tSmall) + vPuck.X
|
||||
vIntersect.z = (vDir.z * tSmall) + vPuck.z
|
||||
|
||||
'Create a new vector with an enormously high Y field to create our reflection plane
|
||||
vIntersectHigh = vIntersect
|
||||
vIntersectHigh.Y = 500
|
||||
'Let's create a plane from this point
|
||||
D3DXPlaneFromPoints oPlane, vec3(0, 0, 0), vIntersect, vIntersectHigh
|
||||
|
||||
'Now we can create a reflection matrix based on this plane
|
||||
D3DXMatrixReflect matReflect, oPlane
|
||||
'Create a new point that is reflected
|
||||
D3DXVec3TransformCoord oPoint, vPuck, matReflect
|
||||
D3DXVec3Subtract vNewVelDir, oPoint, vIntersect
|
||||
'Normalize the vector
|
||||
D3DXVec3Normalize vNewVelDir, vNewVelDir
|
||||
vNewVelDir.X = -vNewVelDir.X
|
||||
vNewVelDir.z = -vNewVelDir.z
|
||||
D3DXVec3Scale moVelocity, vNewVelDir, nVelocity
|
||||
If nVelocityPaddle > 0 Then 'The paddle is moving, add it's velocity
|
||||
'Now let's add the velocity of the paddle to our resulting velocity
|
||||
D3DXVec3Normalize vNewVelPad, oPaddle.Velocity
|
||||
D3DXVec3Scale vNewVelPad, vNewVelPad, nVelocityPaddle
|
||||
D3DXVec3Add moVelocity, moVelocity, vNewVelPad
|
||||
End If
|
||||
Debug.Print "Old Velocity:"; nVelocity; " - New Velocity:"; D3DXVec3Length(moVelocity)
|
||||
'If we are limiting the velocity to it's maximum (most times), do so
|
||||
If Not fIgnoreMax Then EnsurePuckVelocityIsBelowMax
|
||||
End Sub
|
||||
|
||||
Public Sub CheckCollisions(oPaddle() As cPaddle, Optional oAudio As cAudio = Nothing)
|
||||
'First we should check to see if we are scoring in this frame.
|
||||
Dim nDistance As Single
|
||||
Dim lCount As Long, fCollided As Boolean
|
||||
Dim lCollided As Long, nCollideDist As Single
|
||||
|
||||
If gfScored Then Exit Sub
|
||||
'Check to see if the puck has collided with any of the walls
|
||||
'We could do an exhaustive check to see if any of the polygons collide, but since the table
|
||||
'is static, in the name of faster calculations, we will use a group of constants defining the
|
||||
'edges of the walls. We will check those instead.
|
||||
|
||||
'If the puck does hit one of the walls, we can easily calculate it's new direction by simply reversing
|
||||
'it's velocity (of that vector). If we want to be even more accurate we can lower the velocity by a small amount as well
|
||||
|
||||
'The left and right walls are bound to the X axis
|
||||
If moPosition.X > (gnSideLeftWallEdge - (gnPuckRadius)) Then
|
||||
'We hit the wall
|
||||
'Reverse the velocity of the X axis
|
||||
moVelocity = vec3((moVelocity.X * -1) * gnVelocityDamp, 0, moVelocity.z)
|
||||
moPosition = vec3((gnSideLeftWallEdge - (gnPuckRadius)), moPosition.Y, moPosition.z)
|
||||
If Not (oAudio Is Nothing) Then oAudio.PlayBankSound
|
||||
gfRecentlyHitPaddle = False
|
||||
ElseIf moPosition.X < (gnSideRightWallEdge + (gnPuckRadius)) Then
|
||||
'We hit the wall
|
||||
moVelocity = vec3((moVelocity.X * -1) * gnVelocityDamp, 0, moVelocity.z)
|
||||
moPosition = vec3((gnSideRightWallEdge + (gnPuckRadius)), moPosition.Y, moPosition.z)
|
||||
If Not (oAudio Is Nothing) Then oAudio.PlayBankSound
|
||||
gfRecentlyHitPaddle = False
|
||||
End If
|
||||
|
||||
'The front and rear walls are count to the Z axis
|
||||
If moPosition.z > (gnNearWallEdge - (gnPuckRadius)) Then
|
||||
'Only reverse the velocity if we hit the sides of the 'scoring area'
|
||||
If (moPosition.X > (gnScoringEdgeLeft - (gnPuckRadius))) Or (moPosition.X < (gnScoringEdgeRight + (gnPuckRadius))) Then
|
||||
'We hit the wall
|
||||
'Reverse the velocity of the Z axis
|
||||
moVelocity = vec3(moVelocity.X, 0, (moVelocity.z * -1) * gnVelocityDamp)
|
||||
moPosition = vec3(moPosition.X, moPosition.Y, gnNearWallEdge - (gnPuckRadius))
|
||||
If Not (oAudio Is Nothing) Then oAudio.PlayBankSound
|
||||
gfRecentlyHitPaddle = False
|
||||
End If
|
||||
ElseIf moPosition.z < (gnFarWallEdge + (gnPuckRadius)) Then
|
||||
If (moPosition.X > (gnScoringEdgeLeft - (gnPuckRadius))) Or (moPosition.X < (gnScoringEdgeRight - (gnPuckRadius))) Then
|
||||
'We hit the wall
|
||||
moVelocity = vec3(moVelocity.X, 0, (moVelocity.z * -1) * gnVelocityDamp)
|
||||
moPosition = vec3(moPosition.X, moPosition.Y, gnFarWallEdge + (gnPuckRadius))
|
||||
If Not (oAudio Is Nothing) Then oAudio.PlayBankSound
|
||||
gfRecentlyHitPaddle = False
|
||||
End If
|
||||
End If
|
||||
|
||||
'Next we should check to see if the puck has collided with either of the paddles
|
||||
'We will use a simple formula to determine if the puck has collided with one of the
|
||||
'paddles. Simply put if the distance between the center of the puck, and the center
|
||||
'of the paddle in question is greater than the radius of the puck + the radius of the
|
||||
'paddle, they haven't collided
|
||||
Dim vecDif As D3DVECTOR
|
||||
|
||||
If ((timeGetTime - glPaddleCollideTime) > glMinDelayPaddleHit) Or (Not gfRecentlyHitPaddle) Then
|
||||
gfRecentlyHitPaddle = False
|
||||
For lCount = 0 To 1 'Both paddles
|
||||
'We only check the X/Z coords because in this demo the puck will never leave the table
|
||||
'so it will maintain a constant Y coord.
|
||||
D3DXVec3Subtract vecDif, moPosition, oPaddle(lCount).Position
|
||||
nDistance = D3DXVec3Length(vecDif)
|
||||
If nDistance < (gnPaddleRadius + gnPuckRadius) Then 'They have collided
|
||||
nCollideDist = nDistance
|
||||
lCollided = lCount
|
||||
fCollided = True
|
||||
If gfMultiplayer Then
|
||||
'Let each client handle it's own collision detection
|
||||
'in a multiplayer game. This balances the load between
|
||||
'the host machine, and the client machine and gives the
|
||||
'most realistic playing feel.
|
||||
If glMyPaddleID = lCount Then 'We collided with our paddle
|
||||
ChangePuckVelocity oPaddle(lCount), oAudio
|
||||
SendPuck
|
||||
SendCollidePaddle
|
||||
End If
|
||||
Else
|
||||
ChangePuckVelocity oPaddle(lCount), oAudio
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
' Make sure we aren't colliding anymore
|
||||
If fCollided Then EnsurePuckIsNotInPaddle nCollideDist, oPaddle(lCollided)
|
||||
'Lastly we should check if we have scored (on either side)
|
||||
If gfMultiplayer And (Not gfHost) Then Exit Sub 'Only the host should check for scoring
|
||||
If moPosition.z > (gnNearWallEdge) Then
|
||||
'We scored!
|
||||
goPuck.DropPuckIntoScoringPosition goAudio
|
||||
ElseIf moPosition.z < (gnFarWallEdge) Then
|
||||
'We scored!
|
||||
goPuck.DropPuckIntoScoringPosition goAudio
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Sub EnsurePuckIsNotInPaddle(ByVal nDistance As Single, oPaddle As cPaddle, Optional ByVal fSentPaddle As Boolean = False)
|
||||
'Move the paddle back out so it's not hitting the puck
|
||||
Dim vDir As D3DVECTOR, vScale As D3DVECTOR, vPaddleVel As D3DVECTOR
|
||||
|
||||
If fSentPaddle Then
|
||||
D3DXVec3Subtract vPaddleVel, oPaddle.LastPosition, oPaddle.Position
|
||||
'Get the direction vector by normalizing the paddle's velocity
|
||||
D3DXVec3Normalize vDir, vPaddleVel
|
||||
Else
|
||||
'Get the direction vector by normalizing the pucks velocity
|
||||
D3DXVec3Normalize vDir, moVelocity
|
||||
End If
|
||||
'Scale the vector, just enough to get it out of the paddle
|
||||
D3DXVec3Scale vScale, vDir, (gnPuckRadius + gnPaddleRadius) - nDistance
|
||||
'Move the puck to it's new location
|
||||
D3DXVec3Add moPosition, moPosition, vScale
|
||||
'Now, let's increase the pucks velocity that much as well..
|
||||
If fSentPaddle Then D3DXVec3Add moVelocity, moVelocity, vScale
|
||||
End Sub
|
||||
|
||||
Private Sub UpdatePuckSpin()
|
||||
Randomize
|
||||
If Rnd > 0.5 Then
|
||||
mnSpinDir = mnSpinDir * -1
|
||||
'Update the spin, change speed from 75%-125% of current speed..
|
||||
mnDefaultSpin = (Rnd * (mnSpinDir * 0.75)) + (mnSpinDir * 0.5)
|
||||
If Abs(mnDefaultSpin) > mnMaxSpinSpeed Then
|
||||
mnDefaultSpin = mnMaxSpinSpeed * (Abs(mnDefaultSpin) \ mnDefaultSpin)
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Sub CleanupFrame()
|
||||
moPuck.Destroy
|
||||
Set moPuck = Nothing
|
||||
End Sub
|
||||
|
||||
Public Sub DropPuckIntoScoringPosition(oAudio As cAudio, Optional ByVal fFromReceive As Boolean = False)
|
||||
|
||||
gfScored = True
|
||||
glTimeCompPaddle = 0
|
||||
If Not gfMultiplayer Then
|
||||
With goPaddle(1).Velocity
|
||||
.X = 0: .z = 0
|
||||
End With
|
||||
End If
|
||||
glTimePuckScored = timeGetTime
|
||||
oAudio.PlayScoreSound
|
||||
If gfMultiplayer Then
|
||||
If Not gfHost And Not fFromReceive Then Exit Sub
|
||||
End If
|
||||
'First stop the velocity
|
||||
moVelocity = vec3(0, 0, 0)
|
||||
|
||||
With moPosition
|
||||
'Now position the puck
|
||||
If .z < 0 Then
|
||||
gPlayer(1).Score = gPlayer(1).Score + 1
|
||||
.z = gnFarWallEdge - 1.2
|
||||
ElseIf .z > 0 Then
|
||||
.z = gnNearWallEdge + 1.2
|
||||
gPlayer(0).Score = gPlayer(0).Score + 1
|
||||
End If
|
||||
If Abs(.X) > gnScoringEdgeLeft / 3 Then
|
||||
If Abs(.X) <> .X Then
|
||||
.X = gnScoringEdgeRight / 3
|
||||
Else
|
||||
.X = gnScoringEdgeLeft / 3
|
||||
End If
|
||||
End If
|
||||
.Y = gnPuckScored
|
||||
End With
|
||||
|
||||
Spinning = False
|
||||
'If we are the host, notify everyone that we've scored
|
||||
If gfMultiplayer Then NotifyPlayersWeScored
|
||||
|
||||
End Sub
|
||||
|
||||
Public Function FadeMesh(FadeInterval As Single) As Boolean
|
||||
Dim lNumMaterial As Long
|
||||
Dim lCount As Long
|
||||
Dim oMaterial As D3DMATERIAL8
|
||||
Dim fDoneFading As Boolean
|
||||
Dim oMesh As CD3DMesh
|
||||
Dim nInternalInterval As Single
|
||||
Static lFadeTime As Long
|
||||
|
||||
nInternalInterval = FadeInterval
|
||||
If lFadeTime = 0 Then
|
||||
lFadeTime = timeGetTime
|
||||
Exit Function 'We'll do the fade next render pass
|
||||
End If
|
||||
nInternalInterval = (((timeGetTime - lFadeTime) / 1000000) * nInternalInterval)
|
||||
|
||||
Set oMesh = moPuck.FindChildObject("puck", 0)
|
||||
fDoneFading = True
|
||||
lNumMaterial = oMesh.GetMaterialCount
|
||||
For lCount = 0 To lNumMaterial - 1
|
||||
oMaterial = oMesh.GetMaterial(lCount)
|
||||
If nInternalInterval > 0 And oMaterial.diffuse.a <= 1 Then
|
||||
oMaterial.diffuse.a = oMaterial.diffuse.a + nInternalInterval
|
||||
fDoneFading = False
|
||||
ElseIf nInternalInterval < 0 And oMaterial.diffuse.a >= -1 Then
|
||||
oMaterial.diffuse.a = oMaterial.diffuse.a + nInternalInterval
|
||||
fDoneFading = False
|
||||
End If
|
||||
oMesh.SetMaterial lCount, oMaterial
|
||||
Next
|
||||
FadeMesh = fDoneFading
|
||||
End Function
|
||||
|
||||
Public Sub PauseSystem(ByVal fPause As Boolean)
|
||||
If Not fPause Then
|
||||
mlPuckTime = timeGetTime
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'************
|
||||
'Private functions that the public subs here will call, but the main application doesn't need to know about
|
||||
|
||||
Private Sub EnsurePuckVelocityIsBelowMax()
|
||||
Dim VelVec As D3DVECTOR
|
||||
'Let's make sure the puck's velocity isn't above the max,
|
||||
'and if it is, lower it to the max velocity
|
||||
If D3DXVec3Length(moVelocity) > MaximumPuckVelocity Then
|
||||
'Yup, lower the velocity to the max
|
||||
Dim vNrm As D3DVECTOR
|
||||
|
||||
D3DXVec3Normalize vNrm, moVelocity
|
||||
D3DXVec3Scale VelVec, vNrm, MaximumPuckVelocity
|
||||
moVelocity = VelVec
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub Class_Initialize()
|
||||
mnSpinDir = 1
|
||||
mnDefaultSpin = 0.15
|
||||
Set moPuck = Nothing
|
||||
DefaultStartPosition
|
||||
End Sub
|
||||
|
||||
Private Sub Class_Terminate()
|
||||
If Not moPuck Is Nothing Then moPuck.Destroy
|
||||
Set moPuck = Nothing
|
||||
End Sub
|
||||
Reference in New Issue
Block a user