Attribute VB_Name = "modMove"
'-------------------------------------------------------------------------------------
'
'  Project: Shooter
'  Date:    24/04/03
'  File:    modMove
'
'  Description
'   All movement, collision, Enemy AI and animation routines are within this file
'-------------------------------------------------------------------------------------
Option Explicit
Sub DoMovement()

    Select Case nScreen
        Case SCREEN_GAME
            DoMovementGame
        Case SCREEN_MENU
            DoMovementMenu
        Case SCREEN_HIGH
            DoMovementHigh
    End Select
End Sub
Sub DoMovementGame()
'All movement routines are in here
    If bInit Then
        NewGameInit
        bInit = False
    End If
    
    'Animate player
    If PStartY > 0 Then
        PStartY = PStartY - 2
        PY = PY - 1
    End If
    If PAni > 0 Then
        PAni = PAni - 1
        If PAni = 1 Then
            CreatePlayer
            PLives = PLives - 1
            kbFirePressed = AutoFireSpeed
        End If
        If PLives = 0 Then PAni = 10
    End If
        
    'Normallise the screen shake
    If ShakeX < 0 Then ShakeX = ShakeX + 1
    If ShakeX > 0 Then ShakeX = ShakeX - 1
    If ShakeY < 0 Then ShakeY = ShakeY + 1
    If ShakeY > 0 Then ShakeY = ShakeY - 1
    
    'Normalise Gamma
    NormaliseGamma

    ProcessPowerUps
    ProcessGems
    ProcessStars
    ProcessEnemies
    ProcessMissiles
    ProcessEnemyMissiles
    ProcessExplosions
    
    
    'Scroll the text
    
    yTextPos = yTextPos + yTextDir
    If yTextPos > 480 Then yTextDir = -1
    If yTextPos < 0 Then yTextDir = 1
    
    'Scroll the map
    If bPause = False And bMapScroll Then
        If nCounter Mod SCROLLSPEED = 0 Then
            MapScroll = MapScroll - 1
            If MapScroll < 0 Then
                MapPointer = MapPointer - 1
                MapScroll = 63
                If MapPointer < 0 Then  'Stop scrolling when at end of map
                    MapPointer = 0
                    MapScroll = 0
                    bMapScroll = False
                End If
                CheckMapSpawn
            End If
        End If
    End If

End Sub
Sub DoMovementMenu()
    If bInit Then
        GameInit
        bInit = False
    End If
    
    If nMenu > 0 Then
        nMenu = nMenu - 1
    Else
        nMenuPos = nMenuPos - 1
        If nMenuPos < -800 Then
            nMenuPos = 600
        End If
        If nMenuPos = 400 Then
            nMenu = MENU_DELAY
        End If
    End If
End Sub
Sub DoMovementHigh()
    If bInit Then
        'HighInit
        bInit = False
    End If

End Sub
Sub DoCollisions()
'Check for collisions between player and scenary, enemies, enemy bullets
'Check for collisions between player bullets and scenary, enemies
    
'Players are invincible for a very small amount of time...
    If PStartY = 0 Or PLives = 0 Or PHealth < 0 Then
'Player and Scenary (top layer only)
' Work out were on the screen/map the player is... could be colliding with more than
'  one square...
        PlayerMapCollide
'Player and Enemy
        PlayerEnemyCollide
'Player and Enemy Bullet
        PlayerMissileCollide
    End If


'Player and Gem
    PlayerGemCollide

    
'Bullet and Scenary
    MissileMapCollide
'Bullet and Enemy
    MissileEnemyCollide
End Sub
Sub ProcessMissiles()
    Dim nLoop   As Long
    For nLoop = 1 To MAXMISSILES
        If Missiles(nLoop).Type > 0 Then
            With Missiles(nLoop)
                .yPos = .yPos - .dY
                .dY = .dY + .Thrust
                If .dY > .Thrust * 4 Then .dY = .Thrust * 4
                If .yPos < 0 Then .Type = 0   'Make sure it is out of sight
                If .dX <> 0 Then
                    .xPos = .xPos + .dX
                    If .xPos < 0 Then .Type = 0
                    If .xPos > 800 Then .Type = 0
                End If
            End With
        End If
    Next nLoop
End Sub
Sub CreateMissile()
    Dim nLoop   As Long
        
    'Normal Shot
    If PDual = False Then
        For nLoop = 1 To MAXMISSILES
            If Missiles(nLoop).Type = 0 Then
                With Missiles(nLoop)
                    .xPos = PX + POffset(P_OFF_WEAP1, 1) + 1
                    .yPos = PY + POffset(P_OFF_WEAP1, 2) - 6
                    .dY = 0
                    .Thrust = 1
                    .dX = 0
                    .Damage = PWeap
                    .Type = PWeap
                End With
                Exit For
            End If
        Next nLoop
    Else    'Dual = true
        For nLoop = 1 To MAXMISSILES
            If Missiles(nLoop).Type = 0 Then
                With Missiles(nLoop)
                    .xPos = PX + POffset(P_OFF_WEAP1, 1) - 3
                    .yPos = PY + POffset(P_OFF_WEAP1, 2) - 7
                    .dY = 0
                    .Thrust = 1
                    .dX = 0
                    .Damage = PWeap
                    .Type = PWeap
                End With
                Exit For
            End If
        Next nLoop
        For nLoop = 1 To MAXMISSILES
            If Missiles(nLoop).Type = 0 Then
                With Missiles(nLoop)
                    .xPos = PX + POffset(P_OFF_WEAP1, 1) + 5
                    .yPos = PY + POffset(P_OFF_WEAP1, 2) - 7
                    .dY = 0
                    .Thrust = 1
                    .dX = 0
                    .Damage = PWeap
                    .Type = PWeap
                End With
                Exit For
            End If
        Next nLoop
    End If
    Call DS_PlaySound(SND_LASER, False)
End Sub
Sub ProcessExplosions()
    Dim nLoop   As Long
    Dim nTemp   As Long
    
    For nLoop = 1 To MAXEXPLOSIONS
        nTemp = Explosions(nLoop).Frame
        If nTemp > 0 Then
            Explosions(nLoop).Counter = Explosions(nLoop).Counter - 1
            If Explosions(nLoop).Counter = 0 Then
                Explosions(nLoop).Frame = ExpDetail(nTemp).Next
                Explosions(nLoop).Counter = ExpDetail(nTemp).Delay
            End If
        End If
    Next nLoop
End Sub
Sub CreateExplosion(xPos As Long, yPos As Long)
    Dim nLoop   As Long
    Call CreateStars(xPos, yPos)
    For nLoop = 1 To MAXEXPLOSIONS
        If Explosions(nLoop).Frame = 0 Then
            With Explosions(nLoop)
                .Frame = 1
                .Counter = EXPLOSIONSPEED
                .xPos = xPos
                .yPos = yPos
            End With
            nLoop = MAXEXPLOSIONS
        End If
    Next nLoop
    Call DS_PlaySound(SND_EXPLODE, False)

End Sub
Sub CreateBigExplosion(xPos As Long, yPos As Long, bPlayer As Boolean)
    Dim nLoop   As Long
    For nLoop = 1 To MAXEXPLOSIONS
        If Explosions(nLoop).Frame = 0 Then
            With Explosions(nLoop)
                .Frame = 9
                If bPlayer Then .Frame = 17
                .Counter = EXPLOSIONSPEED
                .xPos = xPos
                .yPos = yPos
            End With
            nLoop = MAXEXPLOSIONS
        End If
    Next nLoop

    Call DS_PlaySound(SND_BEXPLODE, False)
End Sub
Sub ProcessEnemies()
'This will end up being a fairly large routine
    Dim nLoop   As Long
    Dim nTemp   As Long
    
    For nLoop = 1 To MAXENEMIES
        nTemp = Enemies(nLoop).Type
        If nTemp > 0 Then
            With Enemies(nLoop)
                If .Flash Then
                    'Decrease the amount of time an enemy is red for
                    .FlashCounter = .FlashCounter - 1
                    If .FlashCounter = 0 Then .Flash = False
                End If
                .Counter = .Counter - 1
                If .Counter = 0 Then
                    .Counter = EnemyDetail(.Frame).Delay
                    .Frame = EnemyDetail(.Frame).Next
                End If
                'Check the Type of the enemy, what's he capable of...
                Select Case .Type
                    Case 0  'Just sit there...
                    Case 1  'Asteriod - moves straight down the screen
                        .yPos = .yPos + 2
                        If .yPos > 600 Then .Type = 0   'off bottom of screen
                    Case 2  'Down screen and leftwards
                        .xPos = .xPos - 1
                        .yPos = .yPos + 2
                        If .yPos > 600 Then .Type = 0   'off bottom of screen
                    Case 3  'Down screen and rightwards
                        .xPos = .xPos + 1
                        .yPos = .yPos + 2
                        If .yPos > 600 Then .Type = 0   'off bottom of screen
                    Case 4  'Enemy moves down 200, left 400, up 200
                        Call ProcessMove1(nLoop)
                    Case 5  'moves down the screen slowly
                        .yPos = .yPos + 1
                        If .yPos > 600 Then .Type = 0   'off bottom of screen
                End Select
                If .CanShoot > 0 Then
                    If .ShootDelay = 0 Then
                        Call ProcessEnemyFire(nLoop)
                    Else
                        .ShootDelay = .ShootDelay - 1
                    End If
                End If
            End With
        End If
    Next nLoop

End Sub
Sub ProcessMove1(nEnemy As Long)
'The first of our movements.
'Enemy moves down screen, to the left, then back up...
'When movecounter = 1 then set up down move
'   =2 then move down
'   =3 then wait for 3 seconds
'   =4 then set up move left
'   =5 then move left
'   =6 then wait for 3 seconds
'   =7 then set up move up
'   =8 then move up
'   =9 then remove enemy

    With Enemies(nEnemy)
        Select Case .MoveCounter
            Case 0  'Not set to any thing yet
                If .xDest = 0 Then
                    .MoveCounter = .MoveCounter + 1
                Else
                    .xDest = .xDest - 1
                End If
            Case 1
                .xDest = .xPos
                .yDest = .yPos + 200
                .MoveCounter = .MoveCounter + 1
            Case 2, 5, 8
                If .xDest > .xPos Then .xPos = .xPos + .Speed
                If .xDest < .xPos Then .xPos = .xPos - .Speed
                If .yDest > .yPos Then .yPos = .yPos + .Speed
                If .yDest < .yPos Then .yPos = .yPos - .Speed
                If .xDest = .xPos And .yDest = .yPos Then
                    .MoveCounter = .MoveCounter + 1
                    .xDest = ONESECOND * 3  'delay time
                End If
            Case 3, 6
                .CanShoot = 1
                If .xDest > 0 Then .xDest = .xDest - 1
                If .xDest = 0 Then .MoveCounter = .MoveCounter + 1
            Case 4
                .xDest = .xPos - 400
                .yDest = .yPos
                .MoveCounter = .MoveCounter + 1
            Case 7
                .xDest = .xPos
                .yDest = .yPos - 200
                .MoveCounter = .MoveCounter + 1
            Case 9
                .Type = 0
        End Select
    End With
End Sub
Sub ProcessEnemyFire(nEnemy As Long)
'Fire an enemy shot...
    Dim nLoop   As Long
    
    With Enemies(nEnemy)
        If Int(Rnd(1) * 10) < 2 Then    '10% chance of actually firing
            Call CreateEnemyMissile(GetEmptyEnemyFire(), .CanShoot, .xPos, .yPos)
            .ShootDelay = ONESECOND + Int(Rnd(1) * ONESECOND)
        End If
    End With

End Sub
Function GetEmptyEnemyFire() As Long
'Find an empty slot in the Enemy Fire array

    Dim nLoop   As Long
    
    For nLoop = 1 To MAXMISSILES
        If EnemyFire(nLoop).Type = 0 Then
            GetEmptyEnemyFire = nLoop
            nLoop = MAXMISSILES
        End If
    Next nLoop
        
End Function
Sub CreateEnemyMissile(nSlot As Long, nType As Long, xPos As Long, yPos As Long)

    If nSlot = 0 Then Exit Sub
    
    With EnemyFire(nSlot)
        .Type = nType
        .xPos = xPos * 4    'Missiles are divided by four before shown on screen
        .yPos = yPos * 4
        If Int(Rnd(1) * 3) > 1 Then 'Fire at player
            .dX = (PX - xPos) / 20
            .dY = (PY - yPos) / 20
        Else    'Fire straight down
            .dX = 0
            .dY = 12         'Move down the screen
        End If
    End With
End Sub
Sub ProcessEnemyMissiles()
'Move all the missiles around
    Dim nLoop   As Long
    
    For nLoop = 1 To MAXMISSILES
        If EnemyFire(nLoop).Type > 0 Then
            With EnemyFire(nLoop)
                .xPos = .xPos + .dX
                .yPos = .yPos + .dY
                If .xPos < 0 Then .Type = 0
                If .xPos > SCREEN_WIDTH * 4 Then .Type = 0
                If .yPos < 0 Then .Type = 0
                If .yPos > SCREEN_HEIGHT * 4 Then .Type = 0
            End With
        End If
    Next nLoop
End Sub
Sub CreateGem(xPos As Long, yPos As Long, nAmount As Long, nType As Long)
    Dim nLoop   As Long
    Dim nGems   As Long
    
    For nGems = 1 To nAmount
        For nLoop = 1 To MAXGEMS
            If Gems(nLoop).Type = 0 Then
                With Gems(nLoop)
                    .Frame = 1
                    .Counter = GemDetail(1).Delay
                    .Type = nType
                    .xPos = xPos + Int(Rnd(1) * 3) - 2
                    .yPos = yPos
                    .yVel = -16 + (Int(Rnd(nLoop) * 17) - 8)
                    .xVel = Int(Rnd(nLoop) * 17) - 8
                End With
                nLoop = MAXGEMS
            End If
        Next nLoop
    Next nGems
End Sub
Sub ProcessGems()
'This will end up being a fairly large routine
    Dim nLoop   As Long
    Dim nTemp   As Long
    
    For nLoop = 1 To MAXGEMS
        nTemp = Gems(nLoop).Type
        If nTemp > 0 Then
            With Gems(nLoop)
                .yPos = .yPos + (.yVel / 8)
                .xPos = .xPos + (.xVel / 8)
                .Counter = .Counter - 1
                .yVel = .yVel + 1
                If .Counter = 0 Then
                    .Counter = GemDetail(.Frame).Delay
                    .Frame = GemDetail(.Frame).Next
                End If
                If .yPos > 1000 Then .Type = 0
            End With
        End If
    Next nLoop
    
End Sub
Sub CreateStars(xPos As Long, yPos As Long)

    Dim nNumber As Long
    Dim nLoop   As Long
    Dim nStar   As Long
    
    nNumber = Int(Rnd(1) * 4) + 4
    For nLoop = 1 To nNumber
        For nStar = 1 To MAXSTARS
            If Stars(nStar).Active = False Then
                With Stars(nStar)
                    .Active = True
                    .xPos = xPos + Int(Rnd(1) * 3) - 1
                    .yPos = yPos + Int(Rnd(1) * 3) - 1
                    .xVel = Int(Rnd(1) * 5) - 2
                    .yVel = Int(Rnd(1) * 5) - 2
                    If .xVel = 0 And .yVel = 0 Then .yVel = 2
                End With
                nStar = MAXSTARS
            End If
        Next nStar
    Next nLoop
End Sub
Sub ProcessStars()
'Make the stars move...
    Dim nLoop   As Long
    
    For nLoop = 1 To MAXSTARS
        If Stars(nLoop).Active Then
            With Stars(nLoop)
                .xPos = .xPos + .xVel
                .yPos = .yPos + .yVel
                If .yPos < 0 Then .Active = False
                If .yPos > SCREEN_HEIGHT Then .Active = False
                If .xPos < 0 Then .Active = False
                If .xPos > SCREEN_WIDTH Then .Active = False
            End With
        End If
    Next nLoop

End Sub
Sub ProcessPowerUps()
'If the Collected number is equal to the needed number give the player his
' powerup!!!
    Dim nLoop   As Long
    
    If pup_upgrade Then
        pup_ani = pup_ani - 1
        If pup_ani = 0 Then pup_upgrade = False
        GoTo EndProcessPowerUps
    End If
    
    If PowerUps(0).Collected > 0 Then
        With PowerUps(PowerUps(0).Collected)
            If .Collected >= .Needed Then
                If .Sound = False Then
                    Call DS_PlaySound(SND_POWER, False)
                    .Sound = True
                End If
                pup_ani_count = pup_ani_count + 1
                pup_ani = KEY_DELAY * 2
                pup_upgrade = True
                For nLoop = 1 To .Collected
                    Call CreateGem(nLoop * 16 + 106, 548, 1, 2)
                Next nLoop
            End If
            If pup_ani_count = 10 Then
                .Active = True
                PowerUps(0).Collected = .Next
                If PowerUps(.Next).Available = False Then PowerUps(.Next).Available = True
                If .Next = 0 Then Call ChangePowerUp
                pup_ani_count = 0
                Select Case .Type
                    Case PUP_AUTOFIRE
                        AutoFireSpeed = AutoFireSpeed - 5
                    Case PUP_POWER
                        PWeap = PWeap + 1
                    Case PUP_DUALFIRE
                        PDual = True
                    Case PUP_SIDEFIRE
                        PSide = True
                    Case PUP_BACKFIRE
                        PBack = True
                End Select
            End If
        End With
    End If
EndProcessPowerUps:
End Sub
Sub PlayerMapCollide()
'Collide the player with the top layer of the map.
' It is possible for the player to be on four squares of the map at any one time...

    Dim nMapOff     As Long
    Dim xPos        As Long
    Dim yPos        As Long
    Dim nTile       As Long
    Dim rTile       As RECT
    Dim rResult     As RECT
    Dim xPosDone    As Long
    Dim yPosDone    As Long
    Dim bCollision  As Boolean

    If PHealth < 1 Then GoTo EndPlayerMapCollide
    
    'Take the left side of the player and remove the offset bit to normalise
    nMapOff = MapScroll * 2   'Performance change
    With rTile
        xPos = Fix((PRect.Left - 48) / 64)
        .Left = 48 + (xPos * 64)
        .Right = .Left + 64
        yPos = Fix((PRect.Top + nMapOff) / 64)
        .Top = yPos * 64 - nMapOff
        .Bottom = .Top + 64
        yPos = yPos + (MapPointer * 2)
    End With
    
    'OK now lets check if we need to check
    nTile = Map2(xPos, yPos)
    Pdebug(0) = nTile
    If nTile > 0 Then
        'First quick check to see if the rectangles overlap
        If IntersectRect(rResult, PRect, rTile) Then
            'They Do - now do Pixel Perfect Check
            bCollision = IntersectGraphic(LOCK_32XTILE, rResult, PRect, rTile, 1, nTile)
            If bCollision Then
                PY = PY + PSpeed 'Move player down a bit
                Call DamageShip(1)
            End If
        End If
    End If
    
    If PHealth < 1 Then GoTo EndPlayerMapCollide

    'Store the xpos and ypos and if they match up then we dont need to check again
    '1st do the right hand side
    xPosDone = xPos
    xPos = Fix((PRect.Right - 48) / 64)
    If xPos <> xPosDone Then
        With rTile
            .Left = 48 + (xPos * 64)
            .Right = .Left + 64
        End With
        'OK now lets check if we need to check
        nTile = Map2(xPos, yPos)
        If nTile > 0 Then
            Pdebug(0) = nTile + 10
            'First quick check to see if the rectangles overlap
            If IntersectRect(rResult, PRect, rTile) Then
                'They do - now do Pixel Perfect check...
                bCollision = IntersectGraphic(LOCK_32XTILE, rResult, PRect, rTile, 1, nTile)
                If bCollision Then
                    PY = PY + PSpeed 'Move Player down a bit
                    Call DamageShip(1)
                End If
            End If
        End If
    End If
    
    If Pdebug(0) = 0 Then Pdebug(0) = 10
EndPlayerMapCollide:
End Sub
Sub PlayerGemCollide()
'A player needs to collide with a gem to collect it...

    Dim nGem        As Long
    Dim rGem        As RECT
    Dim rResult     As RECT
    Dim bCollision  As Boolean
    Dim nPowerUp    As Long
    
    If PHealth < 1 Then GoTo EndPlayerGemCollide
    
    'Loop through all the Gems
    For nGem = 1 To MAXGEMS
        If Gems(nGem).Type = 1 Then 'its active
            With rGem   'A Gem is of variable width but we'll call it 16
                .Left = Gems(nGem).xPos - 8 - GemDetail(Gems(nGem).Frame).OffsetX
                .Right = .Left + 16
                .Top = Gems(nGem).yPos - 8 - GemDetail(Gems(nGem).Frame).OffsetY
                .Bottom = .Top + 16
            End With
            If IntersectRect(rResult, rGem, PRect) Then
                'They do, so now move to pixel perfect
                ' Removed pixel perfect check
'                bCollision = IntersectGraphic(LOCK_32X16, rResult, PRect, rGem, GetPlayerFrame, Gems(nGem).Frame)
'                If bCollision Then
                    'Get rid of the gem and increase the current power up
                    Call DS_PlaySound(SND_GEM, False)
                    nPowerUp = PowerUps(0).Collected
                    PowerUps(nPowerUp).Collected = PowerUps(nPowerUp).Collected + 1
                    If PowerUps(nPowerUp).Collected > PowerUps(nPowerUp).Needed Then
                        PowerUps(nPowerUp).Collected = PowerUps(nPowerUp).Needed
                        Gems(nGem).yVel = -32   'Bounce the gem back upwards
                    Else
                        Gems(nGem).Type = 0
                    End If
                    pup_upgrade = True
                    pup_ani = KEY_DELAY * 2
                    Call CreateStars(PRect.Left + 4, PRect.Top + 4)
                    Call CreateStars(PowerUps(nPowerUp).Collected * 16 + 108, 568)
'                End If
            End If
        End If
    Next nGem
    
EndPlayerGemCollide:
End Sub
Sub MissileMapCollide()
'Collide a bullet with the top layer of the map.
' Whilst it is possible for a bullet to be on 4squares for the sake of speed we only
' check against the first...

    Dim nMapOff     As Long
    Dim nLoop       As Long
    Dim xPos        As Long
    Dim yPos        As Long
    Dim nTile       As Long
    Dim rTile       As RECT
    Dim rMissile    As RECT
    Dim rResult     As RECT
    Dim xPosDone    As Long
    Dim yPosDone    As Long
    Dim bCollision  As Boolean

    'Take the left side of the player and remove the offset bit to normalise
    nMapOff = MapScroll * 2   'Performance change
    For nLoop = 1 To MAXMISSILES
        If Missiles(nLoop).Type > 0 Then
        
            With rMissile   'A missile is 6x8 pixels but we trim a 1pixel border...
                .Left = Missiles(nLoop).xPos + 1
                .Right = .Left + 4
                .Top = Missiles(nLoop).yPos + 1
                .Bottom = .Top + 6
            End With
            With rTile
                xPos = Fix((rMissile.Left - 48) / 64)
                .Left = 48 + (xPos * 64)
                .Right = rTile.Left + 64
                yPos = Fix((rMissile.Top + nMapOff) / 64)
                .Top = yPos * 64 - nMapOff
                .Bottom = rTile.Top + 64
                yPos = yPos + (MapPointer * 2)
            End With
            'OK now lets check if we need to check
            nTile = Map2(xPos, yPos)
            Pdebug(0) = nTile
            If nTile > 0 Then
                'First quick check to see if the rectangles overlap
                If IntersectRect(rResult, rMissile, rTile) Then
                    'They Do - now do Pixel Perfect Check only against the tile
                    bCollision = Intersect1Graphic(1, rResult, rTile, nTile)
                    If bCollision Then
                        With Missiles(nLoop)
                            Call CreateExplosion(Int(.xPos), Int(.yPos))
                            .Type = 0
                        End With
                    End If
                End If
            End If
            
        End If  'End of [Missiles(nLoop).yPos > 0]
    Next nLoop
    
End Sub
Sub MissileEnemyCollide()
'Collide a bullet with an enemy.

    Dim nMissile    As Long
    Dim xPos        As Long
    Dim yPos        As Long
    Dim nOffsetX    As Long
    Dim nOffsetY    As Long
    Dim nGraphic    As Long
    Dim nEnemy      As Long
    Dim rEnemy      As RECT
    Dim rMissile    As RECT
    Dim rResult     As RECT
    Dim xPosDone    As Long
    Dim yPosDone    As Long
    Dim bCollision  As Boolean
    Dim nSize       As Long
    Dim nSurface    As Long

    'Loop through all the missiles
    For nMissile = 1 To MAXMISSILES
        If Missiles(nMissile).Type > 0 Then
            With rMissile   'A missile is 6x8 pixels but we trim a 1pixel border...
                .Left = Missiles(nMissile).xPos + 1
                .Right = .Left + 4
                .Top = Missiles(nMissile).yPos + 1
                .Bottom = .Top + 6
            End With
            For nEnemy = MAXENEMIES To 1 Step -1  'so Enemies drawn last are checked first
                If Enemies(nEnemy).Type > 0 Then
                    Select Case EnemyDetail(Enemies(nEnemy).Frame).Surface
                        Case 4
                            nSize = 4
                        Case 8
                            nSize = 8
                        Case 16
                            nSize = 16
                            nSurface = 2
                        Case 32
                            nSize = 32
                            nSurface = 3
                        Case 64
                            nSize = 64
                            nSurface = 4
                        Case 128
                            nSize = 128
                            nSurface = 5
                    End Select
                    With rEnemy
                        nGraphic = Enemies(nEnemy).Frame
                        .Left = Enemies(nEnemy).xPos - EnemyDetail(nGraphic).OffsetX
                        .Right = .Left + nSize
                        .Top = Enemies(nEnemy).yPos - EnemyDetail(nGraphic).OffsetY
                        .Bottom = .Top + nSize
                    End With
                    
                    'debug boxes...
                    'OK now lets check if we need to check
                    'First quick check to see if the rectangles overlap
                    If IntersectRect(rResult, rMissile, rEnemy) Then
                        'They Do - now do Pixel Perfect Check
                        With rMissile
                            Bdebug(0, 0) = 1
                            Bdebug(0, 1) = .Left
                            Bdebug(0, 2) = .Top
                            Bdebug(0, 3) = .Right - .Left
                            Bdebug(0, 4) = .Bottom - .Top
                        End With
                        With rEnemy
                            Bdebug(1, 0) = 1
                            Bdebug(1, 1) = .Left
                            Bdebug(1, 2) = .Top
                            Bdebug(1, 3) = .Right - .Left
                            Bdebug(1, 4) = .Bottom - .Top
                        End With
                        
                        bCollision = Intersect1Graphic(nSurface, rResult, rEnemy, nGraphic)
                        If bCollision Then
                            Pdebug(2) = 999
                            With Missiles(nMissile)
                                Call CreateExplosion(Int(.xPos), Int(.yPos))
                                Call DamageEnemy(nEnemy, .Damage)
                                .Type = 0
                                nEnemy = 0
                            End With
                        End If  'End of bCollision
                        
                    End If  'End of IntersectRect
                    
                End If  'End of If Enemy().Type > 0
            Next nEnemy
        End If  'End of If Missile() >0
    Next nMissile
End Sub
Sub PlayerEnemyCollide()
'Collide an enemy with the Player.

    Dim xPos        As Long
    Dim yPos        As Long
    Dim nOffsetX    As Long
    Dim nOffsetY    As Long
    Dim nEnemy      As Long
    Dim rEnemy      As RECT
    Dim rResult     As RECT
    Dim xPosDone    As Long
    Dim yPosDone    As Long
    Dim bCollision  As Boolean
    Dim nSurface    As Long
    Dim nSize       As Long     'Size of the sprite (width and height)

    If PHealth < 1 Then GoTo EndPlayerEnemyCollide
    
    For nEnemy = 1 To MAXENEMIES
        If Enemies(nEnemy).Type > 0 Then
            Select Case EnemyDetail(Enemies(nEnemy).Type).Surface
                Case 4
                    nSize = 4
                Case 8
                    nSize = 8
                Case 16
                    nSize = 16
                Case 32
                    nSize = 32
                    nSurface = LOCK_32X32
                    nOffsetX = 16
                    nOffsetY = 16
                Case 64
                    nSize = 64
                    nSurface = LOCK_32X64
                Case 128
                    nSize = 128
            End Select
            With rEnemy
                .Left = Enemies(nEnemy).xPos - nOffsetX
                .Right = .Left + nSize
                .Top = Enemies(nEnemy).yPos - nOffsetY
                .Bottom = .Top + nSize
            End With
            
            'debug boxes...
            'OK now lets check if we need to check
            'First quick check to see if the rectangles overlap
            If IntersectRect(rResult, PRect, rEnemy) Then
                With PRect
                    Bdebug(0, 0) = 1
                    Bdebug(0, 1) = .Left
                    Bdebug(0, 2) = .Top
                    Bdebug(0, 3) = .Right - .Left
                    Bdebug(0, 4) = .Bottom - .Top
                End With
                With rEnemy
                    Bdebug(1, 0) = 1
                    Bdebug(1, 1) = .Left
                    Bdebug(1, 2) = .Top
                    Bdebug(1, 3) = .Right - .Left
                    Bdebug(1, 4) = .Bottom - .Top
                End With
                'They Do - now do Pixel Perfect Check
                'Send as Player and then Enemy on the rectangles and surface
                bCollision = IntersectGraphic(nSurface, rResult, PRect, rEnemy, GetPlayerFrame, Enemies(nEnemy).Frame)
                If bCollision Then
                    Pdebug(2) = 999
                    Call CreateExplosion(rResult.Left, rResult.Top)
                    Call DamageEnemy(nEnemy, 1)
                    Call DamageShip(10)
                End If  'End of bCollision
                
            End If  'End of IntersectRect
            
        End If  'End of If Enemy().Type > 0
    Next nEnemy
EndPlayerEnemyCollide:
End Sub
Sub PlayerMissileCollide()
'Collide an enemy Missile with the Player.

    Dim xPos        As Long
    Dim yPos        As Long
    Dim nOffsetX    As Long
    Dim nOffsetY    As Long
    Dim nEnemy      As Long
    Dim rEnemy      As RECT
    Dim rResult     As RECT
    Dim xPosDone    As Long
    Dim yPosDone    As Long
    Dim bCollision  As Boolean
    Dim nSurface    As Long

    If PHealth < 1 Then GoTo EndPlayerMissileCollide
    
    For nEnemy = 1 To MAXENEMIES
        If EnemyFire(nEnemy).Type > 0 Then
            Select Case EnemyFire(nEnemy).Type
                Case 1
                    nSurface = LOCK_16X32
            End Select
            With rEnemy
                .Left = (EnemyFire(nEnemy).xPos / 4) - 4
                .Right = .Left + 8
                .Top = (EnemyFire(nEnemy).yPos / 4) - 4
                .Bottom = .Top + 8
            End With
            
            'debug boxes...
            'OK now lets check if we need to check
            'First quick check to see if the rectangles overlap
            If IntersectRect(rResult, PRect, rEnemy) Then
                With PRect
                    Bdebug(0, 0) = 1
                    Bdebug(0, 1) = .Left
                    Bdebug(0, 2) = .Top
                    Bdebug(0, 3) = .Right - .Left
                    Bdebug(0, 4) = .Bottom - .Top
                End With
                With rEnemy
                    Bdebug(1, 0) = 1
                    Bdebug(1, 1) = .Left
                    Bdebug(1, 2) = .Top
                    Bdebug(1, 3) = .Right - .Left
                    Bdebug(1, 4) = .Bottom - .Top
                End With
                    'They Do - now do Pixel Perfect Check
                    'Send as Missile then Player on the rectangles and surface
                bCollision = IntersectGraphic(nSurface, rResult, rEnemy, PRect, GetPlayerFrame, 2)
                If bCollision Then
                    Pdebug(2) = 999
                    Call CreateExplosion(rResult.Left, rResult.Top)
                    Call DamageShip(10)
                    EnemyFire(nEnemy).Type = 0
                End If  'End of bCollision
                
            End If  'End of IntersectRect
            
        End If  'End of If Enemy().Type > 0
    Next nEnemy

EndPlayerMissileCollide:
End Sub
Function IntersectGraphic(nLock As Long, rResult As RECT, r1 As RECT, r2 As RECT, g1 As Long, g2 As Long) As Boolean
'Intersect two Graphic Sets
' nLock 0=Not Used,
'rResult - the intersection rectangle
'r1      - the position of the first rectangle
'r2      - the position of the Second rectangle
'g1      - graphic id for first sprite
'g2      - graphic id for second sprite

    Dim rOverlap1   As RECT 'The first rectangle to overlap
    Dim rOverlap2   As RECT 'The second rectangle to overlap
    Dim bCollision  As Boolean
    Dim intWidth    As Long
    Dim intHeight   As Long
    'Dim bytP()      As Byte    'Used to point into the memory of the graphic
    'Dim bytT()      As Byte    ' When used will lead to faster collision detection
    Dim nLoopX      As Long
    Dim nLoopY      As Long
    Dim nSize       As Long
    Dim nSize2      As Long
    
    Select Case nLock
        Case 0  'Not Used
        Case LOCK_32XTILE  'Sprite 32 and Tile
            nSize = 32
            nSize2 = 64
        Case LOCK_16XTILE  'Sprite 16 and Tile
            nSize = 16
            nSize2 = 64
        Case LOCK_16X32  'Sprite 16 and Sprite 32
            nSize = 16
            nSize2 = 32
        Case LOCK_16X16  'Sprite 16 and Sprite 16
            nSize = 16
            nSize2 = 16
        Case LOCK_32X16  'Sprite 32 and Sprite 16
            nSize = 32
            nSize2 = 32
        Case LOCK_32X32  'Sprite 32 and Sprite 32
            nSize = 32
            nSize2 = 32
        Case LOCK_32X64  'Sprite 32 and Sprite 64
            nSize = 32
            nSize2 = 64
        Case LOCK_16X64  'Sprite 16 and Sprite 64
            nSize = 16
            nSize2 = 64
        Case Default
            Stop
    End Select
        
    'Get the RECT structures for the overlapped portions of both surfaces
    With rOverlap1  'Needs to point to the first graphic
        .Top = rResult.Top - r1.Top
        .Bottom = rResult.Bottom - r1.Top
        .Left = rResult.Left - r1.Left + (nSize * g1)
        .Right = rResult.Right - r1.Left + (nSize * g1)
        While .Left > 639
            .Top = .Top + nSize
            .Bottom = .Bottom + nSize
            .Left = .Left - 640
            .Right = .Right - 640
        Wend
    End With
    With rOverlap2  'Needs to point to the second graphic
        .Top = rResult.Top - r2.Top
        .Bottom = rResult.Bottom - r2.Top
        .Left = rResult.Left - r2.Left + (nSize2 * g2)
        .Right = rResult.Right - r2.Left + (nSize2 * g2)
        While .Left > 639
            .Top = .Top + nSize2
            .Bottom = .Bottom + nSize2
            .Left = .Left - 640
            .Right = .Right - 640
        Wend
    End With

    'Determine the width and height of the overlaps (for use in the loops)
    intWidth = rResult.Right - rResult.Left - 1
    intHeight = rResult.Bottom - rResult.Top - 1
    bCollision = False

    Select Case nLock
        Case 0  'Tile & Tile - not used
        Case LOCK_32XTILE  'Sprite 32 and Tile
            'Lock and GetLockedArray each surface
            Sprite32Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
            TileSurf.Lock rOverlap2, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
        Case LOCK_16XTILE  'Sprite 16 and Tile
            'Lock and GetLockedArray each surface
            Sprite16Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
            TileSurf.Lock rOverlap2, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
        Case LOCK_16X32  'Sprite 16 and Sprite32
            'Lock and GetLockedArray each surface
            Sprite16Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite16Surf.GetLockedArray bytP   'Lock the memory
            Sprite32Surf.Lock rOverlap2, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
        Case LOCK_16X16  'Sprite 16 and Sprite16
            'Lock and GetLockedArray each surface
            Sprite16Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite16Surf.GetLockedArray bytP   'Lock the memory
        Case LOCK_32X16  'Sprite 32 and Sprite16
            'Lock and GetLockedArray each surface
            Sprite32Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
            Sprite16Surf.Lock rOverlap2, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite16Surf.GetLockedArray bytP   'Lock the memory
        Case LOCK_32X32  'Sprite 32 and Sprite32
            'Lock and GetLockedArray each surface
            Sprite32Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
        Case LOCK_32X64  'Sprite 32 and Sprite64
            'Lock and GetLockedArray each surface
            Sprite32Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
            Sprite64Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite64Surf.GetLockedArray bytP   'Lock the memory
        Case LOCK_16X64  'Sprite 16 and Sprite64
            'Lock and GetLockedArray each surface
            Sprite16Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytP   'Lock the memory
            Sprite64Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite64Surf.GetLockedArray bytP   'Lock the memory
    End Select
    
    'Pdebug(2) = ddsdBlank.lPitch
    'Compare the surface data from the overlapping portions
    For nLoopX = 0 To intWidth
        For nLoopY = 0 To intHeight
            'If BOTH surfaces are non-transparent at this pixel...
            Select Case nLock
                Case 0
                Case LOCK_32XTILE
                    Pdebug(2) = TileSurf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top)
                    Pdebug(3) = Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top)
                    If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (TileSurf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_16XTILE
                    If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (TileSurf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_16X32
                    If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_16X16
                    If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_32X16
                    If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_32X32
                    If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_32X64
                    If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite64Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
                Case LOCK_16X64
                    If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        If (Sprite64Surf.GetLockedPixel(nLoopX + rOverlap2.Left, nLoopY + rOverlap2.Top) > COLOUR_KEY) Then
                            '...then we have a collision!!
                            bCollision = True
                        End If
                    End If
            End Select
            If bCollision = True Then Exit For
        Next nLoopY
        If bCollision = True Then Exit For
    Next nLoopX
    
    'Unlock the surfaces
    Select Case nLock
        Case 0  'Tile and Tile - not used
        Case LOCK_32XTILE  'Sprite 32 and Tile
            Sprite32Surf.Unlock rOverlap1
            TileSurf.Unlock rOverlap2
        Case LOCK_16XTILE  'Sprite 16 and Tile
            TileSurf.Unlock rOverlap2
            Sprite16Surf.Unlock rOverlap1
        Case LOCK_16X32  'Sprite 16 and Sprite 32
            Sprite16Surf.Unlock rOverlap1
            Sprite32Surf.Unlock rOverlap2
        Case LOCK_16X16  'Sprite 16 and Sprite 16
            Sprite16Surf.Unlock rOverlap1
        Case LOCK_32X16  'Sprite 32 and Sprite 16
            Sprite32Surf.Unlock rOverlap1
            Sprite16Surf.Unlock rOverlap2
        Case LOCK_32X32  'Sprite 32 and Sprite 32
            Sprite32Surf.Unlock rOverlap1
        Case LOCK_32X64  'Sprite 32 and Sprite 64
            Sprite32Surf.Unlock rOverlap1
            Sprite64Surf.Unlock rOverlap2
        Case LOCK_16X64  'Sprite 16 and Sprite 64
            Sprite16Surf.Unlock rOverlap1
            Sprite64Surf.Unlock rOverlap2
    End Select
    
    IntersectGraphic = bCollision
    
End Function

Function Intersect1Graphic(nLock As Long, rResult As RECT, r1 As RECT, g1 As Long) As Boolean
'Intersect ONE Graphic Sets - For small objects hitting really big
' objects we only want to do pixel perfect stuff against the big object...
' nLock 0=Not Used,
'       1=Tile,
'       2=Sprite16
'       3=Sprite32
'       4=Sprite64
'       5=Sprite128
' rResult the intersection rectangle
' r1 the position on the screen of the sprte
' g1 points to the graphic - for more details see into the enemyframe file or
'   the tiles file...
    Dim rOverlap1   As RECT 'The first rectangle to overlap
    Dim bCollision  As Boolean
    Dim intWidth    As Long
    Dim intHeight   As Long
    'Dim bytT()      As Byte    ' When used will lead to faster collision detection
    Dim nLoopX      As Long
    Dim nLoopY      As Long
    Dim nSize       As Long
        
    nCalled = nCalled + 1
    Select Case nLock
        Case 0  'Not Used
        Case 1  'Tile
            nSize = 64
        Case 2  'Sprite 16
            nSize = 16
        Case 3  'Sprite 32
            nSize = 32
        Case 4  'Sprite 64
            nSize = 64
        Case 5  'Sprite 128
            nSize = 128
    End Select
    
    'Get the RECT structures for the overlapped portions of both surfaces
    With rOverlap1  'Needs to point to the graphic on the big object
        If nLock = 1 Then   'Tiles...
            .Top = rResult.Top - r1.Top
            .Bottom = rResult.Bottom - r1.Top
            .Left = rResult.Left - r1.Left + (nSize * g1)
            .Right = rResult.Right - r1.Left + (nSize * g1)
            While .Left > 639
                .Top = .Top + nSize
                .Bottom = .Bottom + nSize
                .Left = .Left - 640
                .Right = .Right - 640
            Wend
        Else
            .Top = rResult.Top - r1.Top + EnemyDetail(g1).StartY
            .Bottom = rResult.Bottom - r1.Top + EnemyDetail(g1).StartY
            .Left = rResult.Left - r1.Left + EnemyDetail(g1).StartX
            .Right = rResult.Right - r1.Left + EnemyDetail(g1).StartX
        End If
    End With

    'Determine the width and height of the overlaps (for use in the loops)
    intWidth = rResult.Right - rResult.Left - 1
    intHeight = rResult.Bottom - rResult.Top - 1
    bCollision = False

    Select Case nLock
        Case 0  'Tile & Tile - not used
        Case 1  'Tile
            TileSurf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
        Case 2  'Sprite 16
            'Lock and GetLockedArray each surface
            Sprite16Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'Sprite32Surf.GetLockedArray bytT   'Lock the memory
        Case 3  'Sprite32
            Sprite32Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
        Case 4  'Sprite64
            Sprite64Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
        Case 5  'Sprite128
            Sprite128Surf.Lock rOverlap1, ddsdBlank, DDLOCK_READONLY Or DDLOCK_WAIT, 0
            'TileSurf.GetLockedArray bytT   'Lock the memory
    End Select
    
    'Pdebug(2) = ddsdBlank.lPitch
    'Compare the surface data from the overlapping portions
    For nLoopX = 0 To intWidth
        For nLoopY = 0 To intHeight
            'If BOTH surfaces are non-transparent at this pixel...
            Select Case nLock
                Case 0
                Case 1
                    If (TileSurf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        '...then we have a collision!!
                        bCollision = True
                    End If
                Case 2
                    If (Sprite16Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        '...then we have a collision!!
                        bCollision = True
                    End If
                Case 3
                    If (Sprite32Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        '...then we have a collision!!
                        bCollision = True
                    End If
                Case 4
                    If (Sprite64Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        '...then we have a collision!!
                        bCollision = True
                    End If
                Case 5
                    If (Sprite128Surf.GetLockedPixel(nLoopX + rOverlap1.Left, nLoopY + rOverlap1.Top) > COLOUR_KEY) Then
                        '...then we have a collision!!
                        bCollision = True
                    End If
            End Select
            If bCollision = True Then Exit For
        Next nLoopY
        If bCollision = True Then Exit For
    Next nLoopX
    
    'Unlock the surfaces
    Select Case nLock
        Case 0  'Tile and Tile - not used
        Case 1  'Tile
            TileSurf.Unlock rOverlap1
        Case 2  'Sprite 16
            Sprite16Surf.Unlock rOverlap1
        Case 3  'Sprite 32
            Sprite32Surf.Unlock rOverlap1
        Case 4  'Sprite 64
            Sprite64Surf.Unlock rOverlap1
        Case 5  'Sprite 128
            Sprite128Surf.Unlock rOverlap1
    End Select
    
    Intersect1Graphic = bCollision
    
End Function

Sub GammaFlashWhite()
    nGammaMode = GAMMA_WHITE
    nGammaRed = 95
    nGammaGreen = 95
    nGammaBlue = 95

End Sub
Sub GammaFlashRed()
    nGammaMode = GAMMA_RED
    nGammaRed = 95
    nGammaGreen = 0
    nGammaBlue = 0

End Sub

Sub NormaliseGamma()
'Set the screen back to black
    nGammaRed = 0
    nGammaGreen = 0
    nGammaBlue = 0

    nGammaMode = GAMMA_NORMAL
End Sub
Sub CheckMapSpawn()
'This looks through the spawns to see if any match the map pointer.
' Zero doesn't count
    Dim nLoop   As Long
    
    For nLoop = 1 To MAXSPAWNS
        If Spawn(nLoop).Map < nLoop Then nLoop = MAXSPAWNS 'quick exit as done
        
        If Spawn(nLoop).Map = MapPointer Then
        'We have something spawning.
            'Its a group of bad guys...
            If Spawn(nLoop).Group > 0 Then
                MapSpawnGroup (Spawn(nLoop).Group)
            End If
        End If
    Next nLoop
End Sub

Sub MapSpawnGroup(nGroup As Long)

    Dim nLoop   As Long
    Dim eLoop   As Long
    Dim nEnemy  As Long
    
    For nLoop = 1 To EnemyGroups(nGroup).Number
        nEnemy = 0
        For eLoop = 1 To MAXENEMIES
            If Enemies(eLoop).Type = 0 Then
                nEnemy = eLoop
                eLoop = MAXENEMIES
            End If
        Next eLoop
        
        If nEnemy > 0 Then
            With Enemies(nEnemy)
                .Counter = EnemyGroups(nGroup).Counter(nLoop)
                .Frame = EnemyGroups(nGroup).Frame(nLoop)
                .Hits = EnemyGroups(nGroup).Hits(nLoop)
                .State = EnemyGroups(nGroup).State(nLoop)
                .Score = EnemyGroups(nGroup).Score(nLoop)
                .Type = EnemyGroups(nGroup).nType(nLoop)
                .xPos = EnemyGroups(nGroup).xPos(nLoop)
                .yPos = EnemyGroups(nGroup).yPos(nLoop)
                .Group = nGroup
                .MoveCounter = 0
            End With
        End If
    Next nLoop
End Sub
Sub EnemySpawnGroup(ByVal nGroup As Long, ByVal xPos As Long, ByVal yPos As Long)

    Dim nLoop   As Long
    Dim eLoop   As Long
    Dim nEnemy  As Long
    
    For nLoop = 1 To EnemyGroups(nGroup).Number
        nEnemy = 0
        For eLoop = 1 To MAXENEMIES
            If Enemies(eLoop).Type = 0 Then
                nEnemy = eLoop
                eLoop = MAXENEMIES
            End If
        Next eLoop
        
        If nEnemy > 0 Then
            With Enemies(nEnemy)
                .Counter = EnemyGroups(nGroup).Counter(nLoop)
                .Frame = EnemyGroups(nGroup).Frame(nLoop)
                .Hits = EnemyGroups(nGroup).Hits(nLoop)
                .State = EnemyGroups(nGroup).State(nLoop)
                .Score = EnemyGroups(nGroup).Score(nLoop)
                .Type = EnemyGroups(nGroup).nType(nLoop)
                .xPos = xPos + EnemyGroups(nGroup).xPos(nLoop)
                .yPos = yPos + EnemyGroups(nGroup).yPos(nLoop)
                .Group = nGroup
                .MoveCounter = 0
            End With
        End If
    Next nLoop
End Sub
Sub CreatePlayer()
'Create a brand new player spacecraft

    PX = 400
    PY = 600
    PStartY = 120
    PAni = 0
    If PLives > 0 Then PHealth = 80

End Sub
