An old college project (for the module "Developing Computer Games") in which I developed - against my better judgement, seriously - a puzzle-platformer inspired by Terry Cavanagh's *VVVVVV*.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

466 lines
21 KiB

Attribute VB_Name = "PlayerMovement"
'Increases the velocity of the player's fall.
Public Function IncreaseVelocity(u As Integer, g As Integer, t As Integer, DimensionScaler As Single)
IncreaseVelocity = (u * t + 0.5 * g * t * t) * DimensionScaler
End Function
Public Sub MovePlayer()
'Used to determine where the player's position in be next, and whether it will place them in collision with a solid tile.
Dim FutureRegion(0 To 1) As Integer
'Sets the current animation frame to their idle stance.
frmGravity.imgPlayer.Picture = LoadPicture(PlayerIdle(PlayerGravityDir))
If PlayerFallSpeed = 0 Then
'If the character's gravity direction is up or down, then she can only move left or right.
If PlayerGravityDir = 0 Or PlayerGravityDir = 2 Then
'If D is pressed...
If KeyIsDown(vbKeyD) = True Then
'Determine where the player's right edge will be.
FutureRegion(0) = Int((PlayerPos(0) + 5 + 8) / 32)
FutureRegion(1) = Int(PlayerPos(1) / 32)
'If the player's right edge will land within a solid tile, place the player exactly adjacent to the block instead.
If Map(FutureRegion(0), FutureRegion(1)) >= 1 Then
PlayerPos(0) = FutureRegion(0) * 32 - 8
'If that tile is a shock tile, shock the player.
If Map(FutureRegion(0), FutureRegion(1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If that tile is an exit tile, the player has completed the level.
If Map(FutureRegion(0), FutureRegion(1)) = 4 Then
Call PlayerStates.WinLevel
End If
'If the player's right edge is not going to collide with a solid tile, simply move them along.
Else
PlayerPos(0) = PlayerPos(0) + 5
End If
'Ensure the player animation only displays the right-walking frames.
If PlayerAnim < 3 Then
PlayerAnim = 3
PlayerAnimSequence = 1
PlayerAnimLoaded = False
End If
'Alternate between animation sequences when those sequences reach their first or last frames.
If PlayerAnimSequence = 0 Then
PlayerAnim = PlayerAnim - 1
If PlayerAnim = 3 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
If PlayerAnimSequence = 1 Then
PlayerAnim = PlayerAnim + 1
If PlayerAnim = 5 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
End If
'If A is pressed...
If KeyIsDown(vbKeyA) = True Then
'Determine where the player's left edge will be.
FutureRegion(0) = Int((PlayerPos(0) - 5 - 8) / 32)
FutureRegion(1) = Int(PlayerPos(1) / 32)
'If the player's left edge will land within a solid tile, place the player exactly adjacent to the block instead.
If Map(FutureRegion(0), FutureRegion(1)) >= 1 Then
PlayerPos(0) = (FutureRegion(0) + 1) * 32 + 8
'If that tile is a shock tile, shock the player.
If Map(FutureRegion(0), FutureRegion(1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If that tile is an exit tile, the player has completed the level.
If Map(FutureRegion(0), FutureRegion(1)) = 4 Then
Call PlayerStates.WinLevel
End If
'If the player's left edge is not going to collide with a solid tile, simply move them along.
Else
PlayerPos(0) = PlayerPos(0) - 5
End If
'Ensure the player animation only displays the left-walking frames.
If PlayerAnim > 2 Then
PlayerAnim = 2
PlayerAnimSequence = 1
PlayerAnimLoaded = False
End If
'Alternate between animation sequences when those sequences reach their first or last frames.
If PlayerAnimSequence = 0 Then
PlayerAnim = PlayerAnim + 1
If PlayerAnim = 2 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
If PlayerAnimSequence = 1 Then
PlayerAnim = PlayerAnim - 1
If PlayerAnim = 0 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
End If
End If
'If the character's gravity direction is left or right, then she can only move up or down.
If PlayerGravityDir = 1 Or PlayerGravityDir = 3 Then
'If S is pressed...
If KeyIsDown(vbKeyS) = True Then
'Determine where the player's bottom edge will be.
FutureRegion(0) = Int(PlayerPos(0) / 32)
FutureRegion(1) = Int((PlayerPos(1) + 5 + 8) / 32)
'If the player's bottom edge will land within a solid tile, place the player exactly adjacent to the block instead.
If Map(FutureRegion(0), FutureRegion(1)) >= 1 Then
PlayerPos(1) = FutureRegion(1) * 32 - 8
'If that tile is a shock tile, shock the player.
If Map(FutureRegion(0), FutureRegion(1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If that tile is an exit tile, the player has completed the level.
If Map(FutureRegion(0), FutureRegion(1)) = 4 Then
Call PlayerStates.WinLevel
End If
'If the player's bottom edge is not going to collide with a solid tile, simply move them along.
Else
PlayerPos(1) = PlayerPos(1) + 5
End If
'Ensure the player animation only displays the downward-walking frames.
If PlayerAnim < 3 Then
PlayerAnim = 3
PlayerAnimSequence = 1
PlayerAnimLoaded = False
End If
'Alternate between animation sequences when those sequences reach their first or last frames.
If PlayerAnimSequence = 0 Then
PlayerAnim = PlayerAnim - 1
If PlayerAnim = 3 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
If PlayerAnimSequence = 1 Then
PlayerAnim = PlayerAnim + 1
If PlayerAnim = 5 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
End If
'If W is pressed...
If KeyIsDown(vbKeyW) = True Then
'Determine where the player's top edge will be.
FutureRegion(0) = Int(PlayerPos(0) / 32)
FutureRegion(1) = Int((PlayerPos(1) - 5 - 8) / 32)
'If the player's top edge will land within a solid tile, place the player exactly adjacent to the block instead.
If Map(FutureRegion(0), FutureRegion(1)) >= 1 Then
PlayerPos(1) = (FutureRegion(1) + 1) * 32 + 8
'If that tile is a shock tile, shock the player.
If Map(FutureRegion(0), FutureRegion(1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If that tile is an exit tile, the player has completed the level.
If Map(FutureRegion(0), FutureRegion(1)) = 4 Then
Call PlayerStates.WinLevel
End If
'If the player's top edge is not going to collide with a solid tile, simply move them along.
Else
PlayerPos(1) = PlayerPos(1) - 5
End If
'Ensure the player animation only displays the upward-walking frames.
If PlayerAnim > 2 Then
PlayerAnim = 2
PlayerAnimSequence = 1
PlayerAnimLoaded = False
End If
'Alternate between animation sequences when those sequences reach their first or last frames.
If PlayerAnimSequence = 0 Then
PlayerAnim = PlayerAnim + 1
If PlayerAnim = 2 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
If PlayerAnimSequence = 1 Then
PlayerAnim = PlayerAnim - 1
If PlayerAnim = 0 Then
PlayerAnimSequence = 0
End If
PlayerAnimLoaded = False
End If
End If
End If
'If an arrow key is pressed, the player's gravity direction changes, their fall origin is reset to their
'position at the time of the change and a sprite image corresponding to that direction is loaded.
If KeyIsDown(vbKeyUp) = True Then
PlayerGravityDir = 0
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
frmGravity.imgPlayer.Picture = LoadPicture(PlayerIdle(0))
End If
If KeyIsDown(vbKeyRight) = True Then
PlayerGravityDir = 1
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
frmGravity.imgPlayer.Picture = LoadPicture(PlayerIdle(1))
End If
If KeyIsDown(vbKeyDown) = True Then
PlayerGravityDir = 2
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
frmGravity.imgPlayer.Picture = LoadPicture(PlayerIdle(2))
End If
If KeyIsDown(vbKeyLeft) = True Then
PlayerGravityDir = 3
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
frmGravity.imgPlayer.Picture = LoadPicture(PlayerIdle(3))
End If
End If
'If the current animation frame has not been loaded, then do so.
If PlayerAnimLoaded = False Then
frmGravity.imgPlayer.Picture = LoadPicture(PlayerWalk(PlayerGravityDir, PlayerAnim))
PlayerAnimLoaded = True
End If
End Sub
Public Sub DropPlayer()
'Used to determine where the player's position in be next, and whether it will place them in collision with a solid tile.
Dim FutureRegion(0 To 1, 0 To 1) As Integer
'If the player's gravity is up...
If PlayerGravityDir = 0 Then
'Determine the future location of the player's top side, and their left and right sides.
FutureRegion(0, 0) = Int((PlayerPos(0) - 8) / 32)
FutureRegion(0, 1) = Int((PlayerPos(0) + 7) / 32)
FutureRegion(1, 0) = Int((PlayerPos(1) - PlayerFallSpeed - 17) / 32)
'If the top edge collides with a solid block (by checking both the left and right ends of that side)...
If FutureRegion(1, 0) >= 0 Then
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) >= 1 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) >= 1 Then
'Position the player exactly adjactent to that block and reset TickCount.
PlayerPos(1) = (FutureRegion(1, 0) + 1) * 32 + 16
TickCount = 0
'If the player has fallen more than two blocks, daze them.
If Abs(PlayerPos(1) - PlayerFallOrigin(1)) > 80 Then
Call PlayerStates.DazePlayer
End If
'If the block is a shock tile, shock the player.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 2 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If the block is an exit gate, the player has completed the level.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 4 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) = 4 Then
Call PlayerStates.WinLevel
End If
'Reset the player's fall speed and fall origin.
PlayerFallSpeed = 0
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
'Otherwise just drop the player by the value of their fall speed.
Else
PlayerPos(1) = Int(PlayerPos(1) - PlayerFallSpeed)
End If
End If
End If
'If the player's gravity is right...
If PlayerGravityDir = 1 Then
'Determine the future location of the player's right side, and their top and bottom sides.
FutureRegion(0, 0) = Int((PlayerPos(0) + PlayerFallSpeed + 16) / 32)
FutureRegion(1, 0) = Int((PlayerPos(1) - 8) / 32)
FutureRegion(1, 1) = Int((PlayerPos(1) + 7) / 32)
'If the right edge collides with a solid block (by checking both the top and bottom ends of that side)...
If FutureRegion(0, 0) <= 24 Then
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) >= 1 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) >= 1 Then
'Position the player exactly adjactent to that block and reset TickCount.
PlayerPos(0) = FutureRegion(0, 0) * 32 - 16
TickCount = 0
'If the player has fallen more than two blocks, daze them.
If Abs(PlayerPos(0) - PlayerFallOrigin(0)) > 80 Then
Call PlayerStates.DazePlayer
End If
'If the block is a shock tile, shock the player.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 2 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If the block is an exit gate, the player has completed the level.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 4 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) = 4 Then
Call PlayerStates.WinLevel
End If
'Reset the player's fall speed and fall origin.
PlayerFallSpeed = 0
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
'Otherwise just drop the player by the value of their fall speed.
Else
PlayerPos(0) = Int(PlayerPos(0) + PlayerFallSpeed)
End If
End If
End If
If PlayerGravityDir = 2 Then
'Determine the future location of the player's bottom side, and their left and right sides.
FutureRegion(0, 0) = Int((PlayerPos(0) - 8) / 32)
FutureRegion(0, 1) = Int((PlayerPos(0) + 7) / 32)
FutureRegion(1, 0) = Int((PlayerPos(1) + PlayerFallSpeed + 16) / 32)
'If the bottom edge collides with a solid block (by checking both the left and right ends of that side)...
If FutureRegion(1, 0) < 18 Then
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) >= 1 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) >= 1 Then
'Position the player exactly adjactent to that block and reset TickCount.
PlayerPos(1) = FutureRegion(1, 0) * 32 - 16
TickCount = 0
'If the player has fallen more than two blocks, daze them.
If Abs(PlayerPos(1) - PlayerFallOrigin(1)) > 80 Then
Call PlayerStates.DazePlayer
End If
'If the block is a shock tile, shock the player.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 2 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'If the block is an exit gate, the player has completed the level.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 4 Or Map(FutureRegion(0, 1), FutureRegion(1, 0)) = 4 Then
Call PlayerStates.WinLevel
End If
'Reset the player's fall speed and fall origin.
PlayerFallSpeed = 0
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
'Otherwise just drop the player by the value of their fall speed.
Else
PlayerPos(1) = Int(PlayerPos(1) + PlayerFallSpeed)
End If
End If
End If
If PlayerGravityDir = 3 Then
'Determine the future location of the player's left side, and their top and bottom sides.
FutureRegion(0, 0) = Int((PlayerPos(0) - PlayerFallSpeed - 17) / 32)
FutureRegion(1, 0) = Int((PlayerPos(1) - 8) / 32)
FutureRegion(1, 1) = Int((PlayerPos(1) + 7) / 32)
'If the left edge collides with a solid block (by checking both the top and bottom ends of that side)...
If FutureRegion(0, 0) >= 0 Then
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) >= 1 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) >= 1 Then
'Position the player exactly adjactent to that block and reset TickCount.
PlayerPos(0) = (FutureRegion(0, 0) + 1) * 32 + 16
TickCount = 0
'If the player has fallen more than two blocks, daze them.
If Abs(PlayerPos(0) - PlayerFallOrigin(0)) > 80 Then
Call PlayerStates.DazePlayer
End If
'If the block is a shock tile, shock the player.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 2 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) = 2 Then
Call PlayerStates.ShockPlayer
End If
'Reset the player's fall speed and fall origin.
If Map(FutureRegion(0, 0), FutureRegion(1, 0)) = 4 Or Map(FutureRegion(0, 0), FutureRegion(1, 1)) = 4 Then
Call PlayerStates.WinLevel
End If
'Reset the player's fall speed and fall origin.
PlayerFallSpeed = 0
PlayerFallOrigin(0) = PlayerPos(0)
PlayerFallOrigin(1) = PlayerPos(1)
'Otherwise just drop the player by the value of their fall speed.
Else
PlayerPos(0) = Int(PlayerPos(0) - PlayerFallSpeed)
End If
End If
End If
'Various variables displayed for debugging purposes.
'DebugText = ""
'DebugText = DebugText & "Player X: " & PlayerPos(0)
'DebugText = DebugText & Chr(13) & "Player Y: " & PlayerPos(1)
'DebugText = DebugText & Chr(13) & "Gravity: " & PlayerGravityDir
'DebugText = DebugText & Chr(13) & "Fall Dist X: " & PlayerPos(0) - PlayerFallOrigin(0)
'DebugText = DebugText & Chr(13) & "Fall Dist X: " & PlayerPos(1) - PlayerFallOrigin(1)
'DebugText = DebugText & Chr(13) & "Region X: " & Int(PlayerPos(0) / 32)
'DebugText = DebugText & Chr(13) & "Future X: " & FutureRegion(0, 0)
'DebugText = DebugText & Chr(13) & "Region Y: " & Int(PlayerPos(1) / 32)
'DebugText = DebugText & Chr(13) & "Future Y: " & FutureRegion(1, 0)
'DebugText = DebugText & Chr(13) & "Player State: " & PlayerState
'DebugText = DebugText & Chr(13) & Len(Str(LevelMinutes)) & " " & LevelMinutes
'DebugText = DebugText & Chr(13) & Len(Str(LevelSeconds))
'DebugText = DebugText & Chr(13) & Len(Str(LevelMilliseconds))
'frmDebug.lblDebug.Caption = DebugText
End Sub