Getting close, but hit a snag...
So the snag part is what to do about shooting down the saucer? I've purposely kept the missile part as a single fire routine. That means the existing missile needs to hit an alien, or top out. I made all missiles top out at the highest row of invaders; however, to hit the saucer this top out level would need to be lifted to the saucer row, and that would slow play down too much.
My options:
Make the saucer always only one row above the aliens, which would mean only a slight flight extension over the present routine.
Speed up the missiles so the firing intervals are not too long.
Modify the missile routine to include multiple missiles in the air like the saucer bomb routine.
I'm not sure which method will work the best.
Pete
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Randomize Timer
Width 40, 20: _Font 16
Rem myfont& = _LoadFont(Environ$("SYSTEMROOT") + "\fonts\lucon.ttf", 21, "MONOSPACE"):_Font myfont&
Dim Obj As String: Obj = "-é-"
lm = 1: rm = _Width: spd = .05
ReDim sbomby(10), sbombx(10)
Type invaders
RenewVars As Integer
Level As Integer
Direction As Integer
TopRow As Integer
RowHeight As Integer
BaseLine As Integer
TrailColumn As Integer
MissileSpeed As Single
AlienIntSpeed As Single
AlienSpeedUp As Single
HomeBase As Integer
BaseAction As Integer
TrailRow As Integer
LtColReduce As Integer
RtColReduce As Integer
z1 As Single
z2 As Single
z3 As Single
yfire As Integer
xfire As Integer
ybomb As Integer
xbomb As Integer
BombSpeed As Single
BombFreq As Single
sbomb As Integer
sbomboff As Integer
Outcome As Integer
Score As _Integer64
Array As String
saucer As String
xsaucer As Single ''' Integer
End Type
Dim si As invaders: ReDim a$(4): si.saucer = "-é-"
Do
Levels si, a$(): _KeyClear
Do
ScoreKeeper si
If si.yfire <> 0 And Abs(si.z2 - Timer) > si.MissileSpeed Then MissileAction si, a$(): If si.Outcome Then Exit Do
If Abs(si.z1 - Timer) > si.AlienIntSpeed Then
MoveAliens si, a$(): If si.Outcome Then Exit Do
End If
If Abs(si.z3 - Timer) > si.BombFreq And si.ybomb = 0 Or si.ybomb And Abs(si.z3 - Timer) > si.BombSpeed Then
AlienBomb si, a$(): If si.Outcome Then Exit Do
End If
KeyBoard si
If si.BaseAction Then BaseAction si
If si.RenewVars Then si.RenewVars = 0
If Abs(z4 - Timer) > .015 Then
z4 = Timer: If SaucerAttack = 0 Then i = Int(Rnd * 100): If i = 7 Then SaucerAttack = 1
End If
If si.TopRow > _Height - 7 Then SaucerAttack = 0
If SaucerAttack Then
If Abs(z - Timer) > spd Then
saucer si, z, lm, rm, sbomby(), sbombx(), OffScrn
End If
If OffScrn = 1 Then SaucerAttack = 0: si.xsaucer = -1: OffScrn = -1
End If
If si.sbomb Then SaucerBombs si, sbomby(), sbombx()
Loop
If si.Level = 3 And si.Outcome = 1 Then si.Outcome = 2 ' Winner!
If si.Outcome <> 1 Then
Finish si, a$() ' Loser!
Else
View Print 2 To _Height - 1: Cls 2: View Print: _Delay 1.5 ' CLear any remaining bombs or missiles.
End If
Loop
Sub Levels (si As invaders, a$())
si.RenewVars = 1
si.Outcome = 0
si.LtColReduce = 0
si.RtColReduce = 0
si.Direction = 1
si.TopRow = 4
si.RowHeight = 5
si.BaseLine = _Height
si.MissileSpeed = .03
si.HomeBase = _Width \ 2
si.Level = si.Level + 1
Select Case si.Level
Case 1
si.Array = "A A A A A A A A A A A A"
si.AlienIntSpeed = .375
si.AlienSpeedUp = .02
si.BombSpeed = .1
si.BombFreq = 1
Case 2
si.Array = "A A A A A A A A A A A A"
si.AlienIntSpeed = .35
si.AlienSpeedUp = .05
si.BombSpeed = .1
si.BombFreq = .85
Case 3
si.Array = "A A A A A A A A A A A A"
si.AlienIntSpeed = .325
si.AlienSpeedUp = .08
si.BombSpeed = .07
si.BombFreq = .7
End Select
ReDim a$(4): For i = 0 To si.RowHeight - 1: a$(i) = si.Array: Next
si.TrailColumn = _Width \ 2 - Len(si.Array) \ 2
Cls
ScoreKeeper si
Refresh si, a$()
_Delay .5
Locate si.TopRow + si.RowHeight + 2: msg$ = "LEVEL 0" + LTrim$(Str$(si.Level)): CenterX msg$: _Delay 2.5
Locate si.TopRow + si.RowHeight + 2, 1: EraseRow
_Delay .5
End Sub
Sub CenterX (msg$)
Locate , _Width \ 2 - Len(msg$) \ 2: Print msg$;
End Sub
Sub EraseRow
Locate , 1: Print Space$(_Width);
End Sub
Sub ScoreKeeper (si As invaders)
info$ = Space$(_Width)
x$ = " Altitude:" + Str$(_Height * 1000 - (si.TopRow - 1 + si.RowHeight) * 1000) + " Ft Score:" + Str$(si.Score)
i = _Width / 2 - Len(x$) / 2
Mid$(info$, i) = x$
Locate 1, 1: Print info$;
End Sub
Sub KeyBoard (si As invaders)
Static restrict
If RenewVars Then restrict = 0
Select Case _KeyHit
Case 19200: If si.HomeBase > 1 And restrict = 0 Then si.HomeBase = si.HomeBase - 1: restrict = 1: si.BaseAction = -1
Case 19712: If si.HomeBase < _Width And restrict = 0 Then si.HomeBase = si.HomeBase + 1: restrict = 1: si.BaseAction = -1
Case -19200, -19712: restrict = 0: _KeyClear: si.BaseAction = 0
Case 32: If si.yfire = 0 Then si.BaseAction = 1
End Select
End Sub
Sub MissileAction (si As invaders, a$())
si.z2 = Timer
If Screen(si.yfire, si.xfire) = 24 Then Locate si.yfire, si.xfire: Print " ";
si.yfire = si.yfire - 1
If Screen(si.yfire, si.xfire) = 65 Then
RowCheck = 0: si.LtColReduce = 0: si.RtColReduce = 0: si.Score = si.Score + 500
Locate si.yfire, si.xfire: Print Chr$(15);: _Delay .1: Locate si.yfire, si.xfire: Print " ";
Mid$(a$(si.yfire - si.TopRow), si.xfire - si.TrailColumn + 1, 1) = " ": si.yfire = 0: Sound 1000, .5
For i = 4 To 0 Step -1
If Len(LTrim$(a$(i))) And RowCheck = 0 Then si.RowHeight = i + 1: RowCheck = 1
If Len(RTrim$(a$(i))) > si.RtColReduce Then si.RtColReduce = Len(RTrim$(a$(i)))
If Len(LTrim$(a$(i))) > si.LtColReduce Then si.LtColReduce = Len(LTrim$(a$(i)))
Next
si.RtColReduce = Len(si.Array) - si.RtColReduce: si.LtColReduce = Len(si.Array) - si.LtColReduce
If LTrim$(a$(0) + a$(1) + a$(2) + a$(3) + a$(4)) = "" Then
si.Outcome = 1
Else
Refresh si, a$()
End If
Else
If si.yfire < si.TrailRow Then si.yfire = 0 Else Locate si.yfire, si.xfire: Print Chr$(24);
End If
End Sub
Sub MoveAliens (si As invaders, a$())
si.z1 = Timer
If si.TrailColumn + Len(si.Array) - si.RtColReduce > _Width And si.Direction = 1 Or si.TrailColumn = 1 - si.LtColReduce And si.Direction = -1 Then
si.Direction = -si.Direction: si.TopRow = si.TopRow + 1: si.AlienIntSpeed = si.AlienIntSpeed - .0225
If si.AlienIntSpeed < .1 Then si.AlienIntSpeed = .1: si.MissileSpeed = .015
Else
si.TrailColumn = si.TrailColumn + si.Direction
End If
If si.TopRow - 1 + si.RowHeight = si.BaseLine Then si.Outcome = -1: si.HomeBase = 0
Refresh si, a$()
Sound 500, .1
End Sub
Sub AlienBomb (si As invaders, a$())
si.z3 = Timer
If si.ybomb = 0 And si.TopRow + si.RowHeight < _Height - 3 Then ' Designate alien ship.
i = si.RowHeight - 1
k = Int(Rnd * (Len(si.Array) \ 2 + 1)) * 2 + 1
Do
For j = 1 To Len(si.Array)
If Mid$(a$(i), k, 1) = "A" Then
g = k: row = i: Exit Do
Else
For h = i To 0 Step -1
If Mid$(a$(h), k, 1) = "A" Then g = k: row = h: Exit Do
Next
End If
k = k + 2: If k > Len(a$(i)) Then k = 1
Next
Exit Do
Loop
si.ybomb = row + si.TopRow + 1
si.xbomb = si.TrailColumn - 1 + g
Locate si.ybomb - 1, si.xbomb: Color 4: Print "A";: Color 7: Sound 200, 1
ElseIf si.ybomb Then
Locate si.ybomb, si.xbomb: Print " ";
If si.ybomb = _Height Then
si.ybomb = 0
Else
si.ybomb = si.ybomb + 1
If Screen(si.ybomb, si.xbomb) = 234 Then
Locate si.ybomb, si.xbomb: Color 4, 0: Print Chr$(236);: _Delay .15: Color 7, 0
Locate si.ybomb, si.xbomb
si.Outcome = -2
Else
Locate si.ybomb, si.xbomb: Print Chr$(249);
End If
End If
End If
End Sub
Sub Refresh (si As invaders, a$())
si.TrailRow = 0
View Print si.TopRow - 1 To si.TopRow + si.RowHeight - 1: Cls 2
For i = 0 To si.RowHeight - 1
Locate si.TopRow + i, si.TrailColumn + si.LtColReduce
Print RTrim$(Mid$(a$(i), si.LtColReduce + 1));
If Len(LTrim$(a$(i))) And si.TrailRow = 0 Then si.TrailRow = si.TopRow + i
Next
View Print
If si.HomeBase Then Locate _Height, si.HomeBase: Print Chr$(234);
End Sub
Sub BaseAction (si As invaders)
Select Case si.BaseAction
Case -1
Locate _Height, 1: Print Space$(_Width);
Locate _Height, si.HomeBase: Print Chr$(234);
Case 1
si.yfire = _Height: si.xfire = si.HomeBase
End Select
si.BaseAction = 0
End Sub
Sub AlienBlitz (si As invaders, a$())
Cls: si.HomeBase = 0
ScoreKeeper si
Do
si.TopRow = si.TopRow + 1
Refresh si, a$()
Sound 500, .1: _Delay .1
Loop Until si.TopRow + si.RowHeight > _Height
Sound 200, 1
End Sub
Sub Finish (si As invaders, a$())
ScoreKeeper si
msg$ = "GAME OVER - "
Select Case si.Outcome
Case -2: msg$ = msg$ + "YOU LOST!": AlienBlitz si, a$()
Case -1: msg$ = msg$ + "YOU LOST!"
Case 2: msg$ = msg$ + "YOU WON!"
End Select
Locate 3: CenterX msg$: msg$ = "Replay? Y/N": Locate 5: CenterX msg$
Do
_Limit 10
b$ = InKey$
Select Case UCase$(b$)
Case "Y", Chr$(13): Cls: Run
Case "N", Chr$(27): _Delay .5: msg$ = "Bye!": Locate 7: CenterX msg$: _Delay 1.5: System
End Select
Loop
End Sub
Sub saucer (si As invaders, z, lm, rm, sbomby(), sbombx(), OffScrn)
Static way, oldway, nodc, sounder
Dim obj As String: obj = "-é-"
If si.sbomboff = 0 And si.xsaucer = 0 Then ReDim sbomby(10), sbombx(10): sounder = 0
If si.xsaucer < 0 Then way = 1: si.xsaucer = 0: nodc = 0
If way < 0 Then rebound = 1 Else rebound = 0
MarqueeLIB obj, lm, rm, way, 3, si.xsaucer, wrapper, rebound, 1, OffScrn: z = Timer
sounder = sounder + 1: If sounder Mod 5 = 0 Then sounder = 0: Sound 300, .2, .5, 1, 9: Sound 0, 0, 1, 0, 1
If nodc < 4 And si.xsaucer > lm + 5 And si.xsaucer <= rm - Len(obj) Then
i = Int(Rnd * 30): If i = 1 Then way = -way
End If
If way <> oldway Then oldway = way: nodc = nodc + 1
If Int(Rnd * 10) = 1 And si.sbomb < 10 Then
If si.xsaucer - way * 2 >= lm And si.xsaucer - way * 2 <= rm Then
si.sbomb = si.sbomb + 1: si.sbomboff = si.sbomboff + 1
sbomby(si.sbomb) = 4: sbombx(si.sbomb) = si.xsaucer - way * 2
Locate sbomby(si.sbomb), sbombx(si.sbomb)
End If
End If
End Sub
Sub SaucerBombs (si As invaders, sbomby(), sbombx())
Static z5
If Abs(z5 - Timer) > .075 Then
For i = 1 To si.sbomb
If sbomby(i) Then
If Screen(sbomby(i), sbombx(i)) = 249 Then Locate sbomby(i), sbombx(i): Print " ";
If sbomby(i) < _Height Then
sbomby(i) = sbomby(i) + 1
If Screen(sbomby(i), sbombx(i)) = 32 Then Locate sbomby(i), sbombx(i): Print Chr$(249);
Else
If Screen(sbomby(i), sbombx(i)) = 234 Then
Locate sbomby(i), sbombx(i)
Color 4, 0: Print Chr$(236);: _Delay .15: Color 7, 0
si.Outcome = -2
Exit For
End If
si.sbomboff = si.sbomboff - 1: sbomby(i) = 0: If si.sbomboff = 0 Then si.sbomb = 0
End If
End If
Next
z5 = Timer
End If
End Sub
Sub MarqueeLIB (Object As String, LtMargin, RtMargin, way, y, x, wrapper, rebound, AllowOffScrn, OffScrn)
Static j, k, oldway
If wrapper Then AllowOffScrn = 0: rebound = 0
Dim a As String
If j = 0 Or OffScrn = -1 Then
j = Len(Object): oldway = 0: oldwrapper = wrapper
If way = 0 Then way = 1
If way > 0 Then x = LtMargin Else x = RtMargin
End If
If oldway And way <> oldway Then
If way < 0 Then If x = 1 Or x = 2 Then x = k - (2 - x) Else x = x - j - 1
If way > 0 Then If x = k Or x = k - 1 Then x = 2 - (k - x) Else x = x + j + 1
End If
oldway = way: OffScrn = 0
k = RtMargin + 1 - LtMargin
a = Space$(RtMargin + 1 - LtMargin)
If way > 0 Then
i = x - j + 1: If i < 1 Then i = 1
Mid$(a, i) = Mid$(Object, j + 1 - x)
If wrapper Then If x > k Then Mid$(a, 1) = Mid$(Object, j - (x - 1 - k)) Else Mid$(a, k - Len(Object) + x + 1) = Mid$(Object, 1, Len(Object) - x)
End If
If way < 0 Then
Mid$(a, x) = Mid$(Object, 1)
If wrapper Then If x < 0 Then Mid$(a, k + x) = Mid$(Object, 1, -x + 1) Else Mid$(a, 1) = Mid$(Object, k + 2 - x)
End If
Locate y, LtMargin: Print a;
If way > 0 Then
x = x + 1: If x > k + j Then If wrapper Then x = j Else x = LtMargin
Else
x = x - 1: If j + x = 1 Then If wrapper Then x = k + 1 - j Else x = k
End If
If rebound Then If x = 0 Or x > k Then way = -way
If AllowOffScrn Then If way > 0 And x = 1 Or way < 0 And x = k Then OffScrn = 1: Locate y, LtMargin: Print Space$(k);
End Sub
So the snag part is what to do about shooting down the saucer? I've purposely kept the missile part as a single fire routine. That means the existing missile needs to hit an alien, or top out. I made all missiles top out at the highest row of invaders; however, to hit the saucer this top out level would need to be lifted to the saucer row, and that would slow play down too much.
My options:
Make the saucer always only one row above the aliens, which would mean only a slight flight extension over the present routine.
Speed up the missiles so the firing intervals are not too long.
Modify the missile routine to include multiple missiles in the air like the saucer bomb routine.
I'm not sure which method will work the best.
Pete
Shoot first and shoot people who ask questions, later.

