Mini Space Invaders - Pete - 09-11-2025
Inspired by Mark (bplus) I decided to come out of retirement to fiddle with this...
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16: bit = 1: TopRow = 4: a$ = "A A A A A A A A A A A A": For i = 0 To 4: a$(i) = a$: Next
trail = _Width \ 2 - Len(a$) \ 2: ms = .05: lag = .35: xbase = _Width \ 2: RowHeight = 5: terminate = _Height
Do
Cls: Locate 1, 1: Print " Altitude ="; _Height * 1000 - (TopRow - 1 + RowHeight) * 1000; " Score ="; Score;
Locate _Height, xbase: Print Chr$(234);: z1 = Timer: zenith = 0
For i = 0 To RowHeight - 1
Locate TopRow + i, trail + l: Print RTrim$(Mid$(a$(i), l + 1));
If Len(LTrim$(a$(i))) And zenith = 0 Then zenith = TopRow + i
Next
Sound 500, .1
Do
If yfire Then
If Abs(z2 - Timer) > ms Then
z2 = Timer
If Screen(yfire, xfire) = 24 Then Locate yfire, xfire: Print " ";: yfire = yfire - 1
If Screen(yfire, xfire) = 65 Then
RowCheck = 0: l = 0: r = 0: Score = Score + 2500
Mid$(a$(yfire - TopRow), xfire - trail + 1, 1) = " ": Sound 1000, .5: yfire = 0
For i = 4 To 0 Step -1
If Len(LTrim$(a$(i))) And RowCheck = 0 Then RowHeight = i + 1: RowCheck = 1
If Len(RTrim$(a$(i))) > r Then r = Len(RTrim$(a$(i)))
If Len(LTrim$(a$(i))) > l Then l = Len(LTrim$(a$(i)))
Next
r = Len(a$) - r: l = Len(a$) - l
Else
If yfire < zenith Then yfire = 0 Else Locate yfire, xfire: Print Chr$(24);
End If
End If
End If
Select Case _KeyHit
Case 19200
If xbase > 1 And restrict = 0 Then xbase = xbase - 1: restrict = 1
Case 19712
If xbase < _Width And restrict = 0 Then xbase = xbase + 1: restrict = 1
Case -19200, -19712
restrict = 0: _KeyClear
Case 32
If yfire = 0 Then yfire = _Height: xfire = xbase
End Select
If Abs(z1 - Timer) > lag Then z1 = Timer: Exit Do
Loop
If LTrim$(a$(0) + a$(1) + a$(2) + a$(3) + a$(4)) = "" Then
View Print 1 To _Height - 1: Cls 2: Print " Altitude ="; _Height * 1000 - (TopRow - 1 + RowHeight) * 1000; " Score ="; Score;
Locate 3, 2: Print "GAME OVER - YOU WON!": _Delay 5: Exit Do
End If
If TopRow - 1 + RowHeight = terminate Then Locate 3, 2: Print "GAME OVER - YOU LOST!": _Delay 5: Exit Do
If trail + Len(a$) - r > _Width And bit = 1 Or trail = 1 - l And bit = -1 Then
bit = -bit: TopRow = TopRow + 1: lag = lag - .02
If lag < .1 Then lag = .1: ms = .025
Else
trail = trail + bit
End If
Loop
It's beatable, but it's not easy!
Tap lt/rt arrow keys repeatedly to move. Holding down keys is death!
Press space bar to fire. Another missile is ready when previous missile either hits a target or vanishes. Missiles vanish when they are past the uppermost line of ships.
It has some good points and bad point like it is scalable but if you messed a lot with the repeat rates, you'd see that the structure is dependent on the timing of events. It could be made better if events were totally independent. Also, for a bigger version, it would be better to have subroutines for the aliens, base, missiles, and scoring.
Pete
RE: Mini Space Invaders - Pete - 09-12-2025
Okay, pretty much the same thing, but now with more independence and in sub procedures...
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16
s$ = "A A A A A A A A A A A A": For i = 0 To 4: a$(i) = s$: Next
bit = 1
TopRow = 4
RowHeight = 5
terminate = _Height
trail = _Width \ 2 - Len(s$) \ 2
ms = .05
lag = .35
xbase = _Width \ 2
Refresh TopRow, RowHeight, trail, l, zenith, xbase, a$()
Do
scoreKeeper score
If yfire <> 0 And Abs(z2 - Timer) > ms Then MissileAction z2, yfire, xfire, xbase, TopRow, RowHeight, trail, zenith, l, r, outcome, score, s$, a$()
poll xbase, BaseActive, yfire
If Abs(z1 - Timer) > lag Then MoveAliens z1, xbase, TopRow, RowHeight, trail, zenith, l, r, terminate, outcome, ms, bit, lag, s$, a$()
If BaseActive Then BaseAction xbase, BaseActive, yfire, xfire
If outcome Then finish outcome: _Delay 5: Exit Do
Loop
Sub scoreKeeper (score)
Locate 1, 1: Print " Altitude ="; _Height * 1000 - (TopRow - 1 + RowHeight) * 1000; " Score ="; score;
End Sub
Sub poll (xbase, BaseActive, yfire)
Static restrict
Select Case _KeyHit
Case 19200: If xbase > 1 And restrict = 0 Then xbase = xbase - 1: restrict = 1: BaseActive = -1
Case 19712: If xbase < _Width And restrict = 0 Then xbase = xbase + 1: restrict = 1: BaseActive = -1
Case -19200, -19712: restrict = 0: _KeyClear:: BaseActive = 0
Case 32: If yfire = 0 Then BaseActive = 1
End Select
End Sub
Sub MissileAction (z2, yfire, xfire, xbase, TopRow, RowHeight, trail, zenith, l, r, outcome, score, s$, a$())
z2 = Timer
If Screen(yfire, xfire) = 24 Then Locate yfire, xfire: Print " ";
yfire = yfire - 1
If Screen(yfire, xfire) = 65 Then
RowCheck = 0: l = 0: r = 0: score = score + 2500
Locate yfire, xfire: Print Chr$(15);: _Delay .1: Locate yfire, xfire: Print " ";
Mid$(a$(yfire - TopRow), xfire - trail + 1, 1) = " ": yfire = 0: Sound 1000, .5
For i = 4 To 0 Step -1
If Len(LTrim$(a$(i))) And RowCheck = 0 Then RowHeight = i + 1: RowCheck = 1
If Len(RTrim$(a$(i))) > r Then r = Len(RTrim$(a$(i)))
If Len(LTrim$(a$(i))) > l Then l = Len(LTrim$(a$(i)))
Next
r = Len(s$) - r: l = Len(s$) - l
Refresh TopRow, RowHeight, trail, l, zenith, xbase, a$()
If LTrim$(a$(0) + a$(1) + a$(2) + a$(3) + a$(4)) = "" Then outcome = 1 ' You won!
Else
If yfire < zenith Then yfire = 0 Else Locate yfire, xfire: Print Chr$(24);
End If
End Sub
Sub MoveAliens (z1, xbase, TopRow, RowHeight, trail, zenith, l, r, terminate, outcome, ms, bit, lag, s$, a$())
z1 = Timer
If TopRow - 1 + RowHeight = terminate Then
outcome = -1
Else
If trail + Len(s$) - r > _Width And bit = 1 Or trail = 1 - l And bit = -1 Then
bit = -bit: TopRow = TopRow + 1: lag = lag - .02
If lag < .1 Then lag = .1: ms = .025
Else
trail = trail + bit
End If
End If
Refresh TopRow, RowHeight, trail, l, zenith, xbase, a$()
Sound 500, .1
End Sub
Sub Refresh (TopRow, RowHeight, trail, l, zenith, xbase, a$())
View Print TopRow - 1 To TopRow + RowHeight - 1: zenith = 0: Cls 2
For i = 0 To RowHeight - 1
Locate TopRow + i, trail + l
Print RTrim$(Mid$(a$(i), l + 1));
If Len(LTrim$(a$(i))) And zenith = 0 Then zenith = TopRow + i
Next
View Print
Locate _Height, xbase: Print Chr$(234);
End Sub
Sub BaseAction (xbase, BaseActive, yfire, xfire)
Select Case BaseActive
Case -1
Locate _Height, 1: Print Space$(_Width);
Locate _Height, xbase: Print Chr$(234);
Case 1
yfire = _Height: xfire = xbase
End Select
BaseActive = 0
End Sub
Sub finish (outcome)
Select Case outcome
Case -1
Locate 3, 2: Print "GAME OVER - YOU LOST!"
Case 1
View Print 1 To _Height - 1: Cls 2: Print " Altitude ="; _Height * 1000 - (TopRow - 1 + RowHeight) * 1000; " Score ="; score;
Locate 3, 2: Print "GAME OVER - YOU WON!"
End Select
End Sub
RE: Mini Space Invaders - Pete - 09-12-2025
And now with TYPE variables...
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16
Type invaders
bit As Integer
TopRow As Integer
RowHeight As Integer
terminate As Integer
trail As Integer
ms As Single
lag As Single
xbase As Integer
BaseActive As Integer
zenith As Integer
l As Integer
r As Integer
z1 As Single
z2 As Single
yfire As Integer
xfire As Integer
outcome As Integer
score As _Integer64
array As String
End Type
Dim si As invaders
si.array = "A A A A A A A A A A A A": For i = 0 To 4: a$(i) = si.array: Next
si.bit = 1
si.TopRow = 4
si.RowHeight = 5
si.terminate = _Height
si.trail = _Width \ 2 - Len(si.array) \ 2
si.ms = .05
si.lag = .35
si.xbase = _Width \ 2
Refresh si, a$()
Do
ScoreKeeper si
If si.yfire <> 0 And Abs(si.z2 - Timer) > si.ms Then MissileAction si, a$()
poll si
If Abs(si.z1 - Timer) > si.lag Then MoveAliens si, a$()
If si.BaseActive Then BaseAction si
If si.outcome Then finish si: _Delay 5: Exit Do
Loop
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$;
Locate 1, 2: Print "Altitude:"; _Height * 1000 - (si.TopRow - 1 + si.RowHeight) * 1000; "Ft ";
Locate 1, _Width - 15: Print "Score:"; si.score;
End Sub
Sub poll (si As invaders)
Static restrict
Select Case _KeyHit
Case 19200: If si.xbase > 1 And restrict = 0 Then si.xbase = si.xbase - 1: restrict = 1: si.BaseActive = -1
Case 19712: If si.xbase < _Width And restrict = 0 Then si.xbase = si.xbase + 1: restrict = 1: si.BaseActive = -1
Case -19200, -19712: restrict = 0: _KeyClear: si.BaseActive = 0
Case 32: If si.yfire = 0 Then si.BaseActive = 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.l = 0: si.r = 0: si.score = si.score + 2500
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.trail + 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.r Then si.r = Len(RTrim$(a$(i)))
If Len(LTrim$(a$(i))) > si.l Then si.l = Len(LTrim$(a$(i)))
Next
si.r = Len(si.array) - si.r: si.l = Len(si.array) - si.l
Refresh si, a$()
If LTrim$(a$(0) + a$(1) + a$(2) + a$(3) + a$(4)) = "" Then si.outcome = 1 ' You won!
Else
If si.yfire < si.zenith 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.TopRow - 1 + si.RowHeight = si.terminate Then
si.outcome = -1
Else
If si.trail + Len(si.array) - si.r > _Width And si.bit = 1 Or si.trail = 1 - si.l And si.bit = -1 Then
si.bit = -si.bit: si.TopRow = si.TopRow + 1: si.lag = si.lag - .02
If si.lag < .1 Then si.lag = .1: si.ms = .025
Else
si.trail = si.trail + si.bit
End If
End If
Refresh si, a$()
Sound 500, .1
End Sub
Sub Refresh (si As invaders, a$())
View Print si.TopRow - 1 To si.TopRow + si.RowHeight - 1: si.zenith = 0: Cls 2
For i = 0 To si.RowHeight - 1
Locate si.TopRow + i, si.trail + si.l
Print RTrim$(Mid$(a$(i), si.l + 1));
If Len(LTrim$(a$(i))) And si.zenith = 0 Then si.zenith = si.TopRow + i
Next
View Print
Locate _Height, si.xbase: Print Chr$(234);
End Sub
Sub BaseAction (si As invaders)
Select Case si.BaseActive
Case -1
Locate _Height, 1: Print Space$(_Width);
Locate _Height, si.xbase: Print Chr$(234);
Case 1
si.yfire = _Height: si.xfire = si.xbase
End Select
si.BaseActive = 0
End Sub
Sub finish (si As invaders)
Select Case si.outcome
Case -1
Locate 3, 2: Print "GAME OVER - YOU LOST!"
Case 1
ScoreKeeper si: Locate 3, 2: Print "GAME OVER - YOU WON!"
End Select
End Sub
This got me thinking how using TYPE variables lengthens the code of a short routine, but if you were to substantially add to a project, it would pay off in the end.
I wonder if we have coders here who are so meticulous they try or actually achieve separate type variables so only those needed in a sub get passed to the sub? The IDE will give warnings if you pass variables that are not used, but this is not the case when using TYPE variables.
Pete
RE: Mini Space Invaders - Pete - 09-12-2025
And what I usually do to finish up a stage of a project, improve the names and make a few minor changes...
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16
Type invaders
Direction As Integer
TopRow As Integer
RowHeight As Integer
BaseLine As Integer
TrailColumn As Integer
MissileSpeed As Single
AlienSpeed As Single
HomeBase As Integer
BaseAction As Integer
TrailRow As Integer
LtColReduce As Integer
RtColReduce As Integer
z1 As Single
z2 As Single
yfire As Integer
xfire As Integer
Outcome As Integer
Score As _Integer64
Array As String
End Type
Dim si As invaders
si.Array = "A A A A A A A A A A A A": For i = 0 To 4: a$(i) = si.Array: Next
si.Direction = 1
si.TopRow = 4
si.RowHeight = 5
si.BaseLine = _Height
si.TrailColumn = _Width \ 2 - Len(si.Array) \ 2
si.MissileSpeed = .05
si.AlienSpeed = .325
si.HomeBase = _Width \ 2
Refresh si, a$(): _Delay 1
Do
ScoreKeeper si
If si.yfire <> 0 And Abs(si.z2 - Timer) > si.MissileSpeed Then MissileAction si, a$()
If si.Outcome = 0 Then
KeyBoard si
If Abs(si.z1 - Timer) > si.AlienSpeed Then MoveAliens si, a$()
If si.BaseAction Then BaseAction si
Else
Finish si
End If
Loop
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
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 + 2500
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$()
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.TopRow - 1 + si.RowHeight = si.BaseLine Then
si.Outcome = -1
Else
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.AlienSpeed = si.AlienSpeed - .02
If si.AlienSpeed < .1 Then si.AlienSpeed = .1: si.MissileSpeed = .025
Else
si.TrailColumn = si.TrailColumn + si.Direction
End If
End If
Refresh si, a$()
Sound 500, .1
End Sub
Sub Refresh (si As invaders, a$())
View Print si.TopRow - 1 To si.TopRow + si.RowHeight - 1: si.TrailRow = 0: 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
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 Finish (si As invaders)
ScoreKeeper si: Locate 3, 2
Select Case si.Outcome
Case -1: x$ = "GAME OVER - YOU LOST!": Locate 3, _Width / 2 - Len(x$) / 2
Case 1: x$ = "GAME OVER - YOU WON!": Locate 3, _Width / 2 - Len(x$) / 2
End Select
Print x$;: x$ = "Replay? Y/N": Locate 5, _Width / 2 - Len(x$) / 2: Print x$;
Do: _Limit 10: b$ = InKey$
If UCase$(b$) = "Y" Then Cls: Run
If UCase$(b$) = "N" Then _Delay .5: Cls: Print " Bye!": _Delay 1.5: System
Loop
End Sub
Beta testing was actually fun on this one. It's fairly addictive. Now that this stage is done, I wonder if I'll get around to adding returned fire, saucer fly overs, and levels.
Pete
RE: Mini Space Invaders - Pete - 09-12-2025
You want the aliens to shoot back. Okay, here you go...
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16
Type invaders
Direction As Integer
TopRow As Integer
RowHeight As Integer
BaseLine As Integer
TrailColumn As Integer
MissileSpeed As Single
AlienSpeed 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
Outcome As Integer
Score As _Integer64
Array As String
End Type
Dim si As invaders
si.Array = "A A A A A A A A A A A A": For i = 0 To 4: a$(i) = si.Array: Next
si.Direction = 1
si.TopRow = 4
si.RowHeight = 5
si.BaseLine = _Height
si.TrailColumn = _Width \ 2 - Len(si.Array) \ 2
si.MissileSpeed = .04
si.AlienSpeed = .375
si.HomeBase = _Width \ 2
Refresh si, a$(): _Delay 1
Do
ScoreKeeper si
If si.yfire <> 0 And Abs(si.z2 - Timer) > si.MissileSpeed Then MissileAction si, a$()
If si.Outcome = 0 Then
KeyBoard si
If Abs(si.z1 - Timer) > si.AlienSpeed Then MoveAliens si, a$()
If Abs(si.z3 - Timer) > 1 Or si.ybomb And Abs(si.z3 - Timer) > .15 Then AlienBomb si, a$()
If si.BaseAction Then BaseAction si
Else
Finish si, a$()
End If
Loop
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
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 + 2500
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$()
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.TopRow - 1 + si.RowHeight = si.BaseLine Then
si.Outcome = -1: si.HomeBase = 0
Else
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.AlienSpeed = si.AlienSpeed - .0225
If si.AlienSpeed < .1 Then si.AlienSpeed = .1: si.MissileSpeed = .025
Else
si.TrailColumn = si.TrailColumn + si.Direction
End If
End If
Refresh si, a$()
Sound 500, .1
End Sub
Sub AlienBomb (si As invaders, a$())
si.z3 = Timer
If si.TopRow + si.RowHeight < _Height - 3 Then
If si.ybomb = 0 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
Else
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 If
End Sub
Sub Refresh (si As invaders, a$())
View Print si.TopRow - 1 To si.TopRow + si.RowHeight - 1: si.TrailRow = 0: 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
x$ = "GAME OVER - "
Select Case si.Outcome
Case -1: x$ = x$ + "YOU LOST!"
Case -2: x$ = x$ + "YOU LOST!": AlienBlitz si, a$()
Case 1: x$ = "YOU WON!"
End Select
Locate 3, _Width / 2 - Len(x$) / 2: Print x$;
x$ = "Replay? Y/N": Locate 5, _Width / 2 - Len(x$) / 2: Print x$;
Do
_Limit 10
b$ = InKey$
Select Case UCase$(b$)
Case "Y", Chr$(13): Cls: Run
Case "N", Chr$(27)
_Delay .5: x$ = "Bye!"
Locate 7, _Width / 2 - Len(x$) / 2
Print x$;: _Delay 1.5: System
End Select
Loop
End Sub
Edit: Made two small optimizations and added red color to ship that drops a bomb.
RE: Mini Space Invaders - Pete - 09-13-2025
And due to the OVERWHELMING interest in this thread, I decided to add 3 levels!
Code: (Select All)
_Title "Pete's Mini Space Invaders"
Width 40, 20: _Font 16
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
AlienSpeed 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
Outcome As Integer
Score As _Integer64
Array As String
End Type
Dim si As invaders: ReDim a$(4)
Do
Levels si, a$()
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.AlienSpeed Then
MoveAliens si, a$(): If si.Outcome Then Exit Do
End If
If Abs(si.z3 - Timer) > si.BombFreq 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
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 = .04
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"
si.AlienSpeed = .325
si.BombSpeed = .125
si.BombFreq = 1
Case 2
si.Array = "A A A A A A A A A A"
si.AlienSpeed = .35
si.BombSpeed = .1
si.BombFreq = .85
Case 3
si.Array = "A A A A A A A A A A A"
si.AlienSpeed = .375
si.BombSpeed = .075
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 + 625
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.TopRow - 1 + si.RowHeight = si.BaseLine Then
si.Outcome = -1
Else
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.AlienSpeed = si.AlienSpeed - .0225
If si.AlienSpeed < .1 Then si.AlienSpeed = .1: si.MissileSpeed = .025
Else
si.TrailColumn = si.TrailColumn + si.Direction
End If
Refresh si, a$()
Sound 500, .1
End If
End Sub
Sub AlienBomb (si As invaders, a$())
si.z3 = Timer
If si.TopRow + si.RowHeight < _Height - 3 Then
If si.ybomb = 0 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
Else
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 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, _Width / 2 - Len(x$) / 2: 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
RE: Mini Space Invaders - Pete - 09-18-2025
Sometimes to better manage the time to code and run a new routine in an existing project, I'll, instead, just make a separate stand alone routine to test out the effects.
If line 2 works for your system to make the screen larger, you can unremark it. That's right, just like most of my routines, it's unremarkable.
So here's just the saucer part without player interaction. I think it's a nice effect for under 100 lines of code.
Code: (Select All)
Width 60, 20
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)
Locate 7, 20: Print "A A A A A A A A A A A A"
Locate 8, 20: Print "A A A A A A A A A A A A"
Locate 9, 20: Print "A A A A A A A A A A A A"
Locate _Height, _Width \ 2: Print Chr$(234);
Do
If Abs(z4 - Timer) > .015 Then
z4 = Timer: If SaucerAttack = 0 Then i = Int(Rnd * 20): If i = 7 Then SaucerAttack = 1
End If
If SaucerAttack Then
If Abs(z - Timer) > spd Then
saucer Obj, z, lm, rm, xsaucer, sbomb, sbomboff, sbomby(), sbombx(), OffScrn
End If
If OffScrn = 1 Then SaucerAttack = 0: xsaucer = -1: OffScrn = -1
End If
If sbomb Then SaucerBombs sbomb, sbomboff, sbomby(), sbombx()
Loop
Sub saucer (obj As String, z, lm, rm, xsaucer, sbomb, sbomboff, sbomby(), sbombx(), OffScrn)
Static way, oldway, nodc
If sbomboff = 0 And xsaucer = 0 Then ReDim sbomby(10), sbombx(10)
If xsaucer < 0 Then way = 1: xsaucer = 0: nodc = 0
If way < 0 Then rebound = 1 Else rebound = 0
MarqueeLIB obj, lm, rm, way, 3, xsaucer, wrapper, rebound, 1, OffScrn: z = Timer
Sound 1000, .1, .3, 1: Sound 300, .2, .1, 1, 7
If nodc < 4 And xsaucer > lm + 5 And 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 sbomb < 10 Then
If xsaucer - way * 2 >= lm And xsaucer - way * 2 <= rm Then
sbomb = sbomb + 1: sbomboff = sbomboff + 1
sbomby(sbomb) = 4: sbombx(sbomb) = xsaucer - way * 2
Locate sbomby(sbomb), sbombx(sbomb)
End If
End If
End Sub
Sub SaucerBombs (sbomb, sbomboff, sbomby(), sbombx())
Static z5
If Abs(z5 - Timer) > .075 Then
For i = 1 To 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 End
sbomboff = sbomboff - 1: sbomby(i) = 0: If sbomboff = 0 Then 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
RE: Mini Space Invaders - Pete - 09-19-2025
Getting close, but hit a snag...
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
RE: Mini Space Invaders - bplus - 09-20-2025
+1 Man you really got into this! Hopefully your personal attention and interest is worth more than a point.
There is a point where a graphics screen starts to make sense for making enhancements, maybe 150-200 LOC even for old dogs that dont like learning new tricks. 
Here take my spaceship out for a spin:
Code: (Select All) Screen _NewImage(1024, 700, 32)
_Delay .25
_ScreenMove _Middle
Dim sc As _Unsigned Long ' ship color
sc = _RGB32(Rnd * 215 + 40, Rnd * 255, Rnd * 255)
_MouseHide
Do
Cls
lc = lc + 1 'loop counter
If lc > 3 * 60 Then sc = _RGB32(Rnd * 215 + 40, Rnd * 255, Rnd * 255): lc = 0 'every 3 secs change ship color
While _MouseInput: Wend
drawShip _MouseX, _MouseY, sc ' here is how to call drawShip easier than using circle
'drawShip _WIDTH / 2, _HEIGHT / 2, sc
_Display
_Limit 60
Loop Until _KeyDown(27)
Sub drawShip (x, y, colr As _Unsigned Long) 'shipType collisions same as circle x, y radius = 30
Static ls
Dim light As Long, r As Long, g As Long, b As Long
r = _Red32(colr): g = _Green32(colr): b = _Blue32(colr)
fellipse x, y, 6, 15, _RGB32(r, g - 120, b - 100)
fellipse x, y, 18, 11, _RGB32(r, g - 60, b - 50)
fellipse x, y, 30, 7, _RGB32(r, g, b)
For light = 0 To 5
fcirc x - 30 + 11 * light + ls, y, 1, _RGB32(ls * 50, ls * 50, ls * 50)
Next
ls = ls + 1
If ls > 5 Then ls = 0
End Sub
' ======== helper subs for drawShip that you can use for other things specially fcirc = fill_circle x, y, radius, color
Sub fellipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
If xr = 0 Or yr = 0 Then Exit Sub
Dim h2 As _Integer64, w2 As _Integer64, h2w2 As _Integer64
Dim x As Long, y As Long
w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
Line (CX - xr, CY)-(CX + xr, CY), C, BF
Do While y < yr
y = y + 1
x = Sqr((h2w2 - y * y * w2) \ h2)
Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
Loop
End Sub
Sub fcirc (x As Long, y As Long, R As Long, C As _Unsigned Long) 'vince version fill circle x, y, radius, color
Dim x0 As Long, y0 As Long, e As Long
x0 = R: y0 = 0: e = 0
Do While y0 < x0
If e <= 0 Then
y0 = y0 + 1
Line (x - x0, y + y0)-(x + x0, y + y0), C, BF
Line (x - x0, y - y0)-(x + x0, y - y0), C, BF
e = e + 2 * y0
Else
Line (x - y0, y - x0)-(x + y0, y - x0), C, BF
Line (x - y0, y + x0)-(x + y0, y + x0), C, BF
x0 = x0 - 1: e = e - 2 * x0
End If
Loop
Line (x - R, y)-(x + R, y), C, BF
End Sub
RE: Mini Space Invaders - NakedApe - 09-20-2025
Very cool, Pete. +1
I want to be able to hold down the arrow keys to move around instead of having to keep pressing them. Why did you limit the motion, to make it harder for the poor players?
|