Rem DB Classic Programming Challenge Entry
Rem 20 July 2007
Rem TDK_Man's Missile Command V3
 
Gosub Setup
 
T1=Timer()
T2=Timer()
Do
  Mx=MouseX(): My=MouseY(): Mc=MouseClick()
  Sprite 1,Mx-16,My-16,Sight
  If Mc=1 And MissilesLeft>0 and BulletInFlight = False Then Gosub Fire_Bullet
  If BulletInFlight = True Then Gosub Move_Bullet
  If Released < EnemyMissiles Then Gosub DropMissiles
  If (Timer()-T1) >= EMissileSpeed And Released > 0 Then Gosub MoveEnemyMissiles: T1=Timer()
  If BangsGoing > 0 Then Gosub GrowExplosions
  If (Timer()-T2) >= 50 Then Gosub UpdateScores: T2=Timer()
  Sync
Loop
End
 
 
Rem **************************************************************
Rem ***                      Procedures                        ***
Rem **************************************************************
 
DropMissiles:
  rem If Released < EnemyMissiles
    Rem Not All Missiles Released For This Level
    Rem Cities Are Sprites 101 to 106
    ReleaseOne = Rnd(MissileFrequency): Rem Only release periodically
    If ReleaseOne = 10
      Rem OK To release another so select a target 101 - 106
      TargetLocked=0
      Repeat
        TargetCity = Rnd(5)+1
        If Sprite Exist(TargetCity+100)
          Inc CurrentEnemyMissile: Rem Starts at 0 so first is number 1
          TargetLocked=1
          Inc Released
        Endif
      Until TargetLocked=1: Rem Target Exists
      Rem Missile Start X/Y Position
      EMissilesSlot(CurrentEnemyMissile) = 1: Rem This slot in use
      Rem Missile End X/Y Position
      MX#(CurrentEnemyMissile) = Rnd(640): Rem Enemy Missile X Start Position
      MY#(CurrentEnemyMissile) = 32.0: Rem Enemy Missile Y Start Position
      MEndPointX = Sprite X(TargetCity+100)+16
      MEndPointY = Sprite Y(TargetCity+100)+9
      MXDist# = ABS(MEndPointX-MX#(CurrentEnemyMissile))
      MYDist# = ABS(MEndPointY-MY#(CurrentEnemyMissile))
      Sprite 300+CurrentEnemyMissile,MX#(CurrentEnemyMissile),MY#(CurrentEnemyMissile),EMissile
      XStep#(CurrentEnemyMissile) = (MXDist#/MYDist#): Rem *MissileSpeed#(CurrentEnemyMissile)
      If MX#(CurrentEnemyMissile) > MEndPointX Then XStep#(CurrentEnemyMissile) = 0-XStep#(CurrentEnemyMissile)
    Endif
  rem Endif
Return
 
MoveEnemyMissiles:
  For N=1 To EnemyMissiles
    If EMissilesSlot(N) = 1: Rem Missile Exists
      MX#(N)=MX#(N)+XStep#(N)
      MY#(N)=MY#(N)+1
      Sprite 300+N,MX#(N),MY#(N),EMissile
      If MY#(N) > 455
        EMissilesSlot(N) = 0: Rem Empty Enemy Missile Slot
        Delete Sprite 300+N: Rem Delete Enemy Missile
      Endif
      CityHit = Sprite Collision(300+N,0)
      If CityHit > 100 and CityHit < 107
        EMissilesSlot(N) = 0: Rem Empty Enemy Missile Slot
        Delete Sprite 300+N: Rem Delete Enemy Missile
        Sprite CityHit+50,Sprite X(CityHit),439,BaseExplosion
        Delete Sprite CityHit: Rem Delete City Sprite
      Endif
    Endif
  Next N
Return
 
UpdateScores:
  S$=Str$(Score)
  While Len(S$) < 6
    S$="0"+S$
  EndWhile
  If Score > Hiscore then Hiscore=Score
  HS$=Str$(HiScore)
  While Len(HS$) < 6
    HS$="0"+HS$
  EndWhile
 
  Set Current Bitmap 1
  CLS 0
  Text 10,0,"Score: "+S$
  Text 490,0,"HiScore: "+HS$
  Get Image Menu,0,0,639,31
  Set Current Bitmap 0
  Sprite 500,0,0,Menu
  Set Sprite 500,0,0
Return
 
Move_Bullet:
  If XDist# > YDist#: Rem X axis is longest distance
    If Left=0
      Sprite 50,X#,BulletPosY#,Missile
      Inc X#,Speed#
      Inc BulletPosY#,Ratio#
      If X# >= EndPointX: Rem Reached Target
        BulletInFlight = False
        Sprite 50,-100,100,Missile: Rem Place off-screen for collision purposes
        Rem Initiate Explosion - Sprites 201 - 210
 
        For N2=1 To 10: Rem Max number of missiles this level
          If Explosions(N2,0)=0: Rem First Empty Slot
            Explosions(N2,0)=20: Rem Starting Sprite Scale Size
            Explosions(N2,1)=EndPointX-1: Rem initial explosion X position
            Explosions(N2,2)=EndPointY-1: Rem initial explosion Y position
            Sprite 200+N2,Explosions(N2,1)-4,Explosions(N2,2)-4,Explosion
            Scale Sprite 200+N2,Explosions(N2,0)
            Inc BangsGoing
            Exit
          Endif
        Next N2
      Endif
    Else
      Sprite 50,X#,BulletPosY#,Missile
      Inc X#,Speed#
      Inc BulletPosY#,Ratio#
      If X# <= EndPointX: Rem Reached Target
        BulletInFlight = False
        Sprite 50,-100,100,Missile: Rem Place off-screen for collision purposes
        Rem Initiate Explosion - Sprites 201 - 210
        For N2=1 To 10
          If Explosions(N2,0)=0: Rem First Empty Slot
            Explosions(N2,0)=20: Rem Starting Sprite Scale Size
            Explosions(N2,1)=EndPointX-1: Rem initial explosion X position
            Explosions(N2,2)=EndPointY-1: Rem initial explosion Y position
            Sprite 200+N2,Explosions(N2,1)-4,Explosions(N2,2)-4,Explosion
            Scale Sprite 200+N2,Explosions(N2,0)
            Inc BangsGoing
            Exit
          Endif
        Next N2
      Endif
    Endif
  Else: Rem Y axis is longest distance
    Sprite 50,BulletPosX#,Y#,Missile
    Inc Y#,Speed#
    Inc BulletPosX#,Ratio#
    If Y# <= EndPointY: Rem Reached Target
      BulletInFlight = False
      Sprite 50,-100,100,Missile: Rem Place off-screen for collision purposes
      Rem Initiate Explosion - Sprites 201 - 210
      For N2=1 To 10
        If Explosions(N2,0)=0: Rem First Empty Slot
          Explosions(N2,0)=20: Rem Starting Sprite Scale Size
          Explosions(N2,1)=EndPointX-1: Rem initial explosion X position
          Explosions(N2,2)=EndPointY-1: Rem initial explosion Y position
          Sprite 200+N2,Explosions(N2,1)-4,Explosions(N2,2)-4,Explosion
          Scale Sprite 200+N2,Explosions(N2,0)
          Inc BangsGoing
          Exit
        Endif
      Next N2
    Endif
  Endif
Return
 
Fire_Bullet:
  EndPointX=Mx: EndPointY=My: Speed# = 8.0: Left=0: Up=0
  BulletPosX# = SpritePosX: BulletPosY# = SpritePosY
  XDist# = ABS(EndPointX-SpritePosX)
  YDist# = ABS(EndPointY-SpritePosY)
  Show Sprite 50
  BulletInFlight = True
  If XDist# > YDist#: Rem X axis is longest distance
    Ratio# = (YDist#/XDist#)*Speed#
    If EndPointX<BulletPosX# Then Speed#=0-Speed#: Left=1: Rem Bullet moving left
    If EndPointY<BulletPosY# Then Ratio#=0-Ratio#: Up=1: Rem Bullet moving up
    X# = BulletPosX#: Rem Start X position of bullet
  Else: Rem Y axis is longest distance
    Ratio# = (XDist#/YDist#)*Speed#
    If EndPointX<BulletPosX# Then Ratio#=0-Ratio#: Left=1: Rem Bullet moving left
    If EndPointY<BulletPosY# Then Speed#=0-Speed#: Up=1: Rem Bullet moving up
    Y# = BulletPosY#: Rem Start X position of bullet
  Endif
  Rem Remove a missile from base
  Paste Image MissileBlank,MissileLeftPos(MissilesLeft,0),MissileLeftPos(MissilesLeft,1)
  Dec MissilesLeft
Return
 
GrowExplosions:
  For M3=1 To MaxMissiles
    If Explosions(M3,0) <> 0
      Rem If not zero then slot being used for explosion
      Explosions(M3,0) = Explosions(M3,0)+2: Rem increase sprite scale value
      Scale Sprite 200+M3,Explosions(M3,0): Rem increase sprite size
      Sprite 200+M3,Explosions(M3,1)-Sprite Width(200+M3)/2,Explosions(M3,2)-Sprite Height(200+M3)/2,Explosion
      Rem Check for Explosion Colliding With Enemy Missile
      MissileHit = Sprite Collision(200+M3,0): Rem object this explosion colliding with
      If MissileHit > 300 And MissileHit <= 340: Rem Enemy Missile Intercepted
        rem EMissiles(MissileHit-300) = 0
        EMissilesSlot(MissileHit-300) = 0
        Delete Sprite MissileHit
        Inc Score,50
        Dec EnemyMissilesLeft
        If EnemyMissilesLeft = 0
          Rem End Of Level
          Gosub RestartLevel
          EndOfLevel=True
        Endif
      Endif
      If Explosions(M3,0) >= 400: Rem Reached max size
        Dec BangsGoing
        Sprite 200+M3,-400,100,Explosion
        Explosions(M3,0) = 0
        Scale Sprite 200+M3,Explosions(M3,0)
      Endif
    Endif
    If EndOfLevel=True Then Exit
  Next M3
Return
 
RestartLevel:
  Ink RGB(255,0,0),0: Center Text 320,200,"LEVEL COMPLETE!"
  Ink RGB(255,255,255),0: Center Text 318,198,"LEVEL COMPLETE!"
  T=Timer()
  Repeat
   Mx=MouseX(): My=MouseY()
   Sprite 1,Mx-16,My-16,Sight
   Sync
  Until Timer()-T >= 3000
 
  For N=201 To 220
    If Sprite Exist(N)
      Sprite N,-500,0,Sprite Image(N)
    Endif
  Next N
 
  For N=101 To 106
    If Sprite Exist(N)
      Sprite N,-500,0,Sprite Image(N)
      Inc Score,100
    Endif
  Next N
 
  For N=151 To 250
    If Sprite Exist(N)
      Sprite N,-500,0,Sprite Image(N)
    Endif
  Next N
 
  CLS: Sync
  Rem Set Up Next Screen
  Dec EMissileSpeed,10
  If EMissileSpeed < 0 Then EMissileSpeed = 0
  Inc EnemyMissiles,2
  EnemyMissilesLeft = EnemyMissiles
  Dec MissileFrequency,10
  If MissileFrequency < 50 Then MissileFrequency = 50
 
 
  BangsGoing = 0
  Released = 0
  CurrentEnemyMissile = 0
  BulletInFlight = False
  MaxMissiles = 10
  MissilesLeft = MaxMissiles
  EndOfLevel=False
 
  For N=1 To 10: Rem MaxMissiles
    Explosions(N,0) = 0
    Explosions(N,1) = -200
    Explosions(N,2) = 0
    EMissilesSlot(N) = 0
  Next N
 
  Inc Level
  Ink RGB(255,0,0),0: Center Text 320,200,"GET READY FOR LEVEL "+Str$(Level)+"..."
  Ink RGB(255,255,255),0: Center Text 318,198,"GET READY FOR LEVEL "+Str$(Level)+"..."
 
  T=Timer()
  Repeat
   Mx=MouseX(): My=MouseY()
   Sprite 1,Mx-16,My-16,Sight
   Sync
  Until Timer()-T >= 3000
 
  CLS
  Gosub BuildScreen
  T=Timer()
Return
 
BuildScreen:
  Rem Player Base
  Paste Image Base,0,SH-42
  Rem Player Cities
  For N=0 To 2
    Sprite N+101,N*64+72,438,City: Rem 101 - 103
  Next N
  For N=0 To 2
    Sprite N+104,N*64+408,438,City
  Next N
  Rem Player Gun
  Paste Image Gun,315,434
  Rem Player Missile
  Sprite 50,318,431,Missile
 
  Rem Off-Screen Explosion Sprites
  For N=1 To 10
    Explosions(N,0)=0
    Sprite 200+N,-100,100,Explosion
    Scale Sprite 200+N,Explosions(N,0)
  Next N
 
  Rem Lives Left Icons
  For N=0 To Lives-1
    Paste Image Lives,N*20+3,463
  Next N
 
  TLX=316: TLY=450: Num=0: Count=1
  For Ny=0 To 3
    For Nx=0 To Num
      Paste Image NumMissiles, Nx*14+TLX,TLY
      MissileLeftPos(Count,0)=Nx*14+TLX
      MissileLeftPos(Count,1)=TLY
      Inc Count
    Next Nx
    Inc Num: Dec TLX,7: Inc TLY,3
  Next Ny
Return
 
Setup:
  SW=640: SH=480
  Set Display Mode SW,SH,16: Wait 100
  Sync On: Sync Rate 0: CLS 0: Wait 100
  Sync: Wait 100
  Randomize Timer()
  Set Text Font "Comic Sans MS"
  Set Text Size 24
  Set Text Transparent
  Hide Mouse
 
  Rem Image Numbers
  City = 100
  Base = 101
  Sight = 102
  Gun = 103
  Missile = 104
  EMissile = 105
  Explosion = 106
  Lives = 107
  NumMissiles = 108
  LivesBlank = 109
  MissileBlank = 110
  Menu = 111
  BaseExplosion = 112
 
  Rem Game Variables
  SpritePosX = 318: SpritePosY = 431
  Lives = 3
 
  MaxMissiles = 10
  MissilesLeft = MaxMissiles
 
  MSpeed# = 1.0
  EnemyMissiles = 6
  EnemyMissilesLeft = EnemyMissiles
  MissileFrequency = 50
  EMissileSpeed = 150
  CurrentEnemyMissile = 0
  OldScore = -1
  Score = 0
  Level = 1
  True = 1: False = 0
 
  Dim Explosions(10,2)
  Dim MissileLeftPos(21,1)
  rem  Dim EMissiles(40)
  Dim EMissilesSlot(40)
  Dim XStep#(20)
  Dim X#(20)
  Dim MLeft(20)
  Dim MX#(20)
  Dim MY#(20)
  Dim MBulletPosX#(20)
  Dim MBulletPosY#(20)
 
  For N=1 To 20
    X#(N)=MSpeed#
  Next N
 
  Create Bitmap 1,640,480
 
  Rem Image For City Sprites
  Ink RGB(45,50,184),0
  For N=0 To 7
    Width = 4
    Top = Rnd(6)*2
    Box N*4,Top,N*4+3,18
  Next N
  Get Image City,0,0,32,18
 
  Rem Image For Base Sprite
  CLS 0
  Ink RGB(135,183,84),0
  Box 0,SH-24,SW-1,SH-1
  Box 0,SH-42,31,SH-1
  Box SW-32,SH-42,SW-1,SH-1
  Box 320-50,SH-30,320+50,SH-1
  Box 320-34,SH-36,320+34,SH-1
  Box 320-18,SH-42,320+16,SH-1
  Get Image Base,0,SH-42,SW-1,SH-1
 
  CLS 0
  Get Image 500,0,0,639,31
  Sprite 500,0,0,500
 
  Rem Image For Gun Sprite
  CLS 0
  Ink RGB(162,64,180),0
  Box 0,0,8,1
  Ink RGB(45,50,184),0
  Box 0,2,8,3
  Get Image Gun,0,0,9,4
 
  Rem Image For Sight Sprite
  CLS 0
  Ink RGB(155,0,0),0: Circle 16,15,15: Circle 16,16,15
  Ink RGB(155,0,0),0
  Circle 16,15,14: Circle 16,16,14
  Ink RGB(170,0,0),0: Line 2,15,39,15: Line 2,17,39,17
  Line 15,1,15,30: Line 17,1,17,30
  Ink 0,0:  Box 15,15,17,17
  Get Image Sight,0,0,32,32
 
  Rem Image For Bullet Sprite
  CLS 0
  Ink RGB(255,255,255),0
  Box 0,0,2,2
  Get Image Missile,0,0,3,3
 
  Rem Image For Enemy Missiles Sprites
  CLS 0
  Ink RGB(255,0,255),0
  Dot 0,0: Dot 3,0: Dot 0,3: Dot 3,3
  Box 1,1,2,2
  Get Image EMissile,0,0,4,4
 
  Rem Image For Explosion Sprite
  CLS 0
  R=255: G=255: B=0
  For N=1 To 14
    Ink RGB(R,G,B),0
    Circle 16,16,N
    Circle 16,17,N
    Dec G,16
  Next N
  Blur Bitmap 1,1
  Get Image Explosion,0,0,32,32
 
  Rem Image For Base Explosion Sprite
  CLS 0
  R=255: G=31: B=100
  For N=1 To 14
    Ink RGB(R,G,B),0
    Circle 16,16,N
    Circle 16,17,N
    Inc G,16
  Next N
  Blur Bitmap 1,1
  Get Image BaseExplosion,0,0,32,16
 
  Rem Image For Lives Indicator 16 x 8
  CLS 0
  Ink RGB(255,0,0),0: Box 0,0,15,7
  Ink RGB(12,12,12),0: Box 1,1,14,6
  Get Image Lives,0,0,16,8
  CLS RGB(135,183,84)
  Get Image LivesBlank,0,0,16,8
 
  Rem Image For Missiles Left Indicator 7 x 3
  CLS 0
  Ink RGB(12,12,12),0: Box 0,0,6,2
  Ink RGB(255,255,255),0: Box 1,1,5,1
  Get Image NumMissiles,0,0,7,3
  CLS RGB(135,183,84)
  Get Image MissileBlank,0,0,7,3
  Set Current Bitmap 0
 
  Rem Now Build Scene On Main Screen...
  Gosub BuildScreen
  Ink RGB(255,255,255),0
Return