Posts: 144
Threads: 10
Joined: Apr 2022
Reputation:
5
09-27-2022, 07:54 PM
(This post was last modified: 09-27-2022, 07:57 PM by johnno56.
Edit Reason: "Would" not "wold"
)
James,
So 'that' is what the beastie is supposed to look like? Could I impose upon you for yet another favour and provide an "in game" screen shot? I have been experimenting with different 'characters'... My characters put the "ug" in ugly... lol
By the way... am I permitted to add a little colour? (I like the 'green' / 'light gray' text of the old monitors)
Please correct me if I am wrong... would not 'inkey' provide a quicker response than 'inkey$'? Reason: When changing directions, there is a momentary pause, before the ship moves... unless 'that' is the desired effect... If so, just ignore the suggestion... Now... Let us talk about sound... Nah. Kidding. "Text" sound effects are great!
Looking forward to your next creation... Do you take requests? If so, I think a Text Version of Doom, would be awesome... But Donkey Kong or a Lunar Lander may be slightly easier... lol
May your journey be free of incident. Live long and prosper.
Posts: 545
Threads: 116
Joined: Apr 2022
Reputation:
39
09-27-2022, 08:09 PM
(This post was last modified: 09-27-2022, 08:10 PM by James D Jarvis.)
Colorize away ! I tried to keep it as simple as I could, so I didn't do much that was fancy with the code. I've still got the shield feature to add. Here's a screen shot from level 5.
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
(09-27-2022, 07:54 PM)johnno56 Wrote: Please correct me if I am wrong... would not 'inkey' provide a quicker response than 'inkey$'? Reason: When changing directions, there is a momentary pause, before the ship moves... unless 'that' is the desired effect... If so, just ignore the suggestion... Now... Let us talk about sound... Nah. Kidding. "Text" sound effects are great! Perhaps you meant "_KEYDOWN()" instead of the first "inkey"? Response to user input is difficult to get right in a game, and in a programming tool for hobbyists this is noticed most easily. In QB64PE is because "_DELAY" or "_LIMIT" must be used to free CPU cycles and to wait a little bit to give the user some time to react to the bad guys. The "FOR... NEXT" loops that had to be used in ancient BASIC's also held up keyboard input.
I've tried to set up a loop of, say 10 iterations doing "_DELAY 0.01" and polling for a key each time but the response was a bit less sluggish than the "simple" method of only one "_DELAY", or a "_LIMIT" controlling the main loop of the program. I created a game that I will post on these forums in the near future, which illustrates the problem with reacting to user input quickly. I almost forgot to mention that the time has to be taken into account processing how the bad guys move and, in addition, if the game board is to react to what the user does (for example going from one room to another in a dungeon). M$QB had the "KEY() ON/OFF/STOP" crew but that was a dangerous way to program and, for an EXE file, it required a compiler switch which added overhead. "Dangerous" because if the screen was drawn slowly and it had to update everytime the characters moved in the game, pressing a key would have revealed a visual glitch or else worse.
The OS has to cooperate for "delay" requests 20ms or even smaller, which is another thing to try to beat.
Another thing is that I noticed the QB64PE IDE is sadder on Linux than on Windows with user input, especially holding down a key for a few seconds. Sometimes on Linux (doesn't matter which distro) the input is late. It must be the reliance on the ancient terminal and graphics code borrowed from Unix and the difficulty of providing an input method which is more efficient, for the fear that it makes things incompatible. I don't know how is it with you guys able to spend thousands of USD on quad-core CPU with 8GB+ RAM and so on.
On Ubuntu for example it might be better to disable key-repeat globally in the OS, only for the sake of keeping some sanity using the QB64PE IDE. But some people don't like punching the same key more than 20 times if not the space bar in a first-person shooter...
(09-27-2022, 07:54 PM)johnno56 Wrote: By the way... am I permitted to add a little colour? (I like the 'green' / 'light gray' text of the old monitors) I agree with you as long as the background is green and the ALL UPPERCASE text is black, like my Color Computer.
https://colorcomputerarchive.com/xroar-online/
Posts: 1,616
Threads: 157
Joined: Apr 2022
Reputation:
77
INKEY$ will move fast enough for this game. INP(96) is faster, but harder to control. I seldom use the QB64 key input methods. You can also make routines to clear the keyboard buffer and control the repeat rate, if needed.
Pete
Posts: 144
Threads: 10
Joined: Apr 2022
Reputation:
5
Thanks for the images (time to remove the ugly bits... lol) and the 'key' tips... Much appreciated.
Pete,
TRS80 CoCo... Nice... Perhaps Black text of green background for 'daytime' coding and reversed for 'night' coding? Oh... How about a routine that will modify background and text based on system time? I digress. Thank you for the suggestion... Cool...
May your journey be free of incident. Live long and prosper.
Posts: 545
Threads: 116
Joined: Apr 2022
Reputation:
39
Added shields. Not 100% thrilled with them but they mostly work.
Code: (Select All) 'Tvaders 1b
'by James D. Jarvis , you are of course free to modiyt and share this code as you like
'
'a text-mode qb64 retro-shooter
'
'$dynamic
Screen _NewImage(100, 35, 0)
_Title "Tvaders 1"
Type spritetype
s As String
w As Integer 'i wanted to make this a byte but i want to be a tiny bit backwards compatible for folks with different versions
sx As Integer
sy As Integer
hdg As Integer
End Type
Dim Shared a(16) As spritetype
Dim Shared ps As spritetype
Dim Shared ss(10) As spritetype
Dim Shared b(100) As spritetype
Dim Shared aspace(100, 35)
Dim Shared shieldrow(100)
Dim Shared a$, gflag$
Dim Shared shotmax, shotspeed, shottimer, aliencount, aliendelay, alientimer, alive, level, score
Dim Shared boltmax, bolttimer, boltspeed, alienfire, shields, shieldy, shieldcounter
_ControlChr Off
Randomize Timer
Read a$
Read ship$
Read bolt$
Read shot$
ps.s = ship$
ps.w = 8
ps.sx = 32
ps.sy = 31
a(1).s = a$
a(1).w = 8
a(1).sx = 1
a(1).sy = 3
a(1).hdg = 1
For n = 1 To 100
b(n).s = bolt$
b(n).w = 1
b(n).sx = 0
b(n).sy = 0
Next n
For n = 1 To 10
ss(n).s = shot$
ss(n).w = 2
ss(n).sx = 0
ss(n).sy = 0
Next n
For n = 1 To 100
shieldrow(n) = 0
Next n
gflag$ = "GAMEON"
shotmax = 3
shotspeed = 10
shottimer = 0
aliencount = 1
aliendelay = 20
alientimer = 0
alive = aliencounter
level = 1
boltmax = 100
bolttimer = 0
boltspeed = 9
shieldy = 29
startlevel level
Do
_Limit 60
handleshots
handlealiens
handlezaps
handleshields
Cls
Locate 1, 1
Print "LEVEL : "; level
Locate 1, 40
Print "Shields : "; shields
Locate 1, 70
Print "SCORE : "; score
Locate 2, 1
Print "ALive "; alive
If gflag$ = "BOOM" Then doboom
For bc = 1 To 100
If b(bc).sx > 0 Then splat b(bc).s, b(bc).w, b(bc).sx, b(bc).sy
Next bc
For sr = 1 To 100
If shieldrow(sr) > 0 Then
_PrintString (sr, shieldy), "*"
End If
Next sr
For ac = 1 To aliencount
If a(ac).sx > 0 Then
splat a(ac).s, a(ac).w, a(ac).sx, a(ac).sy
End If
Next ac
splat ps.s, ps.w, ps.sx, ps.sy
For s = 1 To shotmax
If ss(s).sx <> 0 Then splat ss(s).s, ss(s).w, ss(s).sx, ss(s).sy
Next s
kk$ = InKey$
If LCase$(kk$) = "a" Or kk$ = "," Or kk$ = "<" Then ps.sx = ps.sx - 1
If LCase$(kk$) = "d" Or kk$ = "." Or kk$ = ">" Then ps.sx = ps.sx + 1
If LCase$(kk$) = "s" Then shieldon ps.sx
If kk$ = " " Then fire ps.sx + 3
If ps.sx < 1 Then ps.sx = 1
If ps.sx > 92 Then ps.sx = 92
If alive < 1 Then nextlevel level
_Display
Loop Until kk$ = Chr$(27) Or gflag$ = "GAMEOVER"
System
'sprites were orignally drawn in ascii tilemaker and stripped out of the data file without the color data for use here
Data "ÛÛÛÛÛÛÛÛ Û0 0Û ÛÛÛÛÛÛÛÛ ^ ^^ ^ "
Data " ²² ÎÎ ²²²² ²²^²²^²²"
Data "/\/"
Data "##^^"
Sub fire (fx)
shotfound = 0
noshots = 0
If shieldrow(fx) <= 0 Or shieldrow(fx + 2) <= 0 Then
Do
noshots = noshots + 1
If ss(noshots).sx = 0 Then shotfound = noshots
Loop Until shotfound > 0 Or noshots = shotmax
If shotfound > 0 Then
ss(shotfound).sx = fx
ss(shotfound).sy = ps.sy - 2
End If
End If
End Sub
Sub shieldon (sxx)
If shields > 0 Then
shields = shields - 1
For so = sxx To sxx + 7
shieldrow(so) = shieldrow(so) + 3
Next so
End If
End Sub
Sub zap (zx, zy)
zapfound = 0
zapcount = 0
Do
zapcount = zapcount + 1
If b(zapcount).sx = 0 Then zapfound = zapcount
Loop Until zapfound > 1 Or zapcount = boltmax
If zapcount > 0 Then
b(zapcount).sx = zx + 4
b(zapcount).sy = zy + 3
End If
End Sub
Sub handleshields
shieldcounter = shieldcounter + 1
For sr = 1 To 100
If shieldrow(sr) < 0 Then shieldrow(sr) = 0
If shieldcounter = 200 Then
shieldrow(sr) = shieldrow(sr) - 1
End If
Next sr
If shieldcounter = 200 Then shieldcounter = 0
End Sub
Sub handlezaps
bolttimer = bolttimer + 1
If bolttimer = boltspeed Then
bolttimer = 0
For n = 1 To 100
If b(n).sx > 0 Then
b(n).sy = b(n).sy + 1
If b(n).sy = 33 Then
b(n).sx = 0
b(n).sy = 0
End If
If b(n).sy = 27 And shieldrow(b(n).sx) > 0 Then
b(n).sy = 0: b(n).sx = 0
shieldrow(b(n).sx) = shieldrow(b(n).sx) - 1
End If
If b(n).sy = 31 Then
For xx = ps.sx To ps.sx + 7
If b(n).sx = xx Then playerhit$ = "BOOM"
If playerhit$ = "BOOM" Then
For rr = 1 To 20
_Limit 150
For d = 1 To 300
_PrintString (2 + Int(Rnd * 98), 5 + Int(Rnd * 30)), "*"
Next d
_PrintString (b(n).sx + Int(Rnd * 3), b(n).sy + Int(Rnd * 3)), "BOOM!"
gflag$ = "BOOM"
_Display
Next rr
End If
Next xx
End If
End If
Next n
End If
End Sub
Sub handleshots
shottimer = shottimer + 1
If shottimer = shotspeed Then
hittag$ = "miss"
For s = 1 To shotmax
For aa = 1 To aliencount
If a(aa).sx > 0 Then
sl = Len(a(aa).s)
sh = sl / a(aa).w
For y = 1 To sh
For x = 1 To a(aa).w
If a(aa).sx + x - 1 = ss(s).sx And a(aa).sy + y - 1 = ss(s).sy And hittag$ = "miss" Then hittag$ = "hit"
Next x
Next
End If
If hittag$ = "hit" Then
ss(s).sx = 0
a(aa).sx = 0
alive = alive - 1
hittag$ = "miss"
score = score + 100
Beep
End If
Next aa
ss(s).sy = ss(s).sy - 2
If ss(s).sy < 1 Then
ss(s).sx = 0
ss(s).sy = 0
End If
Next s
shottimer = 0
End If
End Sub
Sub handlealiens
alientimer = alientimer + 1
If alientimer > 32000 Then alientimer = 1
For n = 1 To aliencount
If a(n).sx > 0 And (alientimer Mod aliendelay = 0) Then
a(n).sx = a(n).sx + a(n).hdg
If a(n).sx > 92 Then
a(n).sx = 92
a(n).sy = a(n).sy + 2
a(n).hdg = a(n).hdg * -1
End If
If a(n).sx < 1 Then
a(n).sx = 1
a(n).sy = a(n).sy + 2
a(n).hdg = a(n).hdg * -1
End If
If 1 + Int(Rnd * 100) <= alienfire Then zap a(n).sx, a(n).sy
If a(n).sy = 31 Then
For xx = ps.sx To ps.sx + 7
If a(n).sx = xx Then playerhit$ = "BOOM"
If playerhit$ = "BOOM" Then
For rr = 1 To 20
_Limit 150
For d = 1 To 300
_PrintString (2 + Int(Rnd * 98), 5 + Int(Rnd * 30)), "*"
Next d
_PrintString (a(n).sx + Int(Rnd * 3), a(n).sy + Int(Rnd * 3)), "BOOM!"
gflag$ = "BOOM"
_Display
Next rr
End If
Next xx
End If
End If
Next
End Sub
Sub splat (SA$, ww As Integer, sx As Integer, sy As Integer)
sl = Len(SA$)
sh = sl / ww
For y = 1 To sh
_PrintString (sx, sy - 1 + y), Mid$(SA$, (y - 1) * ww + 1, ww)
Next
End Sub
Sub startlevel (level)
For bb = 1 To 100
b(bb).sx = 0
b(bb).sy = 0
Next bb
For n = 1 To 10
ss(n).sx = 0
ss(n).sy = 0
Next n
For sr = 1 To 100
shieldrow(sr) = 0
Next sr
shieldcounter = 0
Select Case level
Case 1
aliencount = 1
alive = 1
aliendelay = 20
a(1).s = a$
a(1).w = 8
a(1).sx = 46
a(1).sy = 3
a(1).hdg = 1
shields = 0
score = 0
alienfire = 0
Case 2
aliencount = 3
alive = 3
aliendelay = 20
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).sx = n * 12 + 30
a(n).sy = 3
a(n).hdg = 1
Next n
shields = 3
alienfire = 2
Case 3
aliencount = 5
alive = 5
aliendelay = 19
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).sx = n * 11 + 20
a(n).sy = 4
a(n).hdg = 1
Next n
shields = shields + 2
alienfire = 4
Case 4
aliencount = 6
alive = 6
aliendelay = 19
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).sx = n * 15
a(n).sy = 5
a(n).hdg = 1
Next n
shields = shields + 2
alienfire = 6
Case 5
aliencount = 7
alive = 7
aliendelay = 18
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = 1
Next n
For n = 1 To 5
a(n).sx = n * 15
a(n).sy = 1
Next n
For n = 6 To 7
a(n).sx = (n - 5) * 35
a(n).sy = 5
Next n
shields = shields + 2
alienfire = 6
Case 6
aliencount = 8
alive = 8
aliendelay = 18
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = 1
Next n
For n = 1 To 3
a(n).sx = n * 25
a(n).sy = 3
Next n
For n = 4 To aliencount
a(n).sx = (n - 3) * 12
a(n).sy = 7
Next n
shields = shields + 2
alienfire = 8
Case 7
aliencount = 9
alive = 9
aliendelay = 17
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = 1
Next n
For n = 1 To 3
a(n).sx = n * 12
a(n).sy = 3
Next n
For n = 4 To 6
a(n).sx = (n - 3) * 12 + 30
a(n).sy = 7
a(n).hdg = -1
Next n
For n = 7 To 9
a(n).sx = (n - 6) * 12
a(n).sy = 11
Next n
shields = shields + 2
alienfire = 8
Case 8
aliencount = 10
alive = 10
aliendelay = 17
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = Int(Rnd * 2) - 1
If a(n).hdg = 0 Then a(n).hdg = 1
a(n).sx = 12 + Int(Rnd * 8) * 8
a(n).sy = 1 + Int(Rnd * 3) * 4
Next n
shields = shields + 2
alienfire = 9
Case 9
aliencount = 11
alive = 11
aliendelay = 16
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = -2
Next n
For n = 1 To 5
a(n).sx = n * 12 + 12
a(n).sy = 3
Next n
For n = 6 To aliencount
a(n).sx = (n - 5) * 8
a(n).sy = 7
Next n
shields = shields + 2
alienfire = 9
Case 10
aliencount = 12
alive = 12
aliendelay = 16
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = Int(Rnd * 4) - 2
If a(n).hdg = 0 Then a(n).hdg = 1
a(n).sx = 12 + Int(Rnd * 8) * 8
a(n).sy = 1 + Int(Rnd * 3) * 4
Next n
shields = shields + 1
alienfire = 10
Case 11
aliencount = 13
alive = 13
aliendelay = 15
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = -2
Next n
For n = 1 To 7
a(n).sx = n * 12
a(n).sy = 1 + Int(Rnd * 3) * 4
Next n
For n = 8 To aliencount
a(n).sx = (n - 7) * 12
a(n).sy = 13
Next n
shields = shields + 1
alienfire = 1
Case 12
aliencount = 14
alive = 14
aliendelay = 14
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
Next n
For n = 1 To 7
a(n).sx = n * 9
a(n).sy = 1
a(n).hdg = -2
Next n
For n = 8 To aliencount
a(n).sx = (n - 7) * 9
a(n).sy = 11
a(n).hdg = 2
Next n
shields = shields + 1
alienfire = 11
Case 13
aliencount = 15
alive = 15
aliendelay = 13
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
Next n
For n = 1 To 10
a(n).sx = (n * 9) - 8
a(n).sy = 2
a(n).hdg = -2
Next n
For n = 11 To aliencount
a(n).sx = (n - 10) * 9
a(n).sy = 9
a(n).hdg = 3
Next n
shields = shields + 1
alienfire = 12
Case 14
aliencount = 16
alive = 16
aliendelay = 12
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
Next n
For n = 1 To 8
a(n).sx = (n * 9) - 8
a(n).sy = 2
a(n).hdg = -3
Next n
For n = 9 To aliencount
a(n).sx = (n - 8) * 9
a(n).sy = 11
a(n).hdg = 3
Next n
shields = shields + 1
alienfire = 13
Case 15
aliencount = 16
alive = 16
aliendelay = 10
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
Next n
For n = 1 To 9
a(n).sx = (n * 9) - 8
a(n).sy = 4
a(n).hdg = -3
Next n
For n = 10 To 14
a(n).sx = (n - 9) * 9 + 4
a(n).sy = 9
a(n).hdg = 3
Next n
For n = 15 To aliencount
a(n).sx = (n - 14) * 20 + 40
a(n).sy = 13
a(n).hdg = 4
Next n
shields = shields + 1
alienfire = 14
Case 16
aliencount = 16
alive = 16
aliendelay = 8
For n = 1 To aliencount
a(n).s = a$
a(n).w = 8
a(n).hdg = Int(Rnd * 8) - 4
If a(n).hdg = 0 Then a(n).hdg = 4
Next n
For x = 0 To 3
For y = 1 To 4
a(x * 4 + y).sx = x * 20
a(x * 4 + y).sy = y * 5
Next y
Next x
shields = shields + 1
alienfire = 15
End Select
End Sub
Sub nextlevel (level)
If level < 17 Then
score = score + level * 1000
Locate 10, 10
Cls
_KeyClear
Print "*********************************************************"
Print "* *"
Print "* COMPLETED LEVEL *"
Print "* *"
Print "* PRESS ANY KEY *"
Print "* *"
Print "* TO START NEXT LEVEL *"
Print "* *"
Print "* *"
Print "*********************************************************"
_Display
any$ = Input$(1)
level = level + 1
If level < 17 Then startlevel level
If level = 17 Then gameflag$ = "GAMEOVER"
End If
If level = 17 Or gameflag$ = "GAMEOVER" Then
Cls
Locate 10, 10
_KeyClear
Print "*********************************************************"
Print "* *"
Print " CONGRATULATIONS ! "
Print "* *"
Print " You Have Defeated the ALIENs! "
Print "* *"
Print
Print " FINAL SCORE : "; score
Print
Print "* PRESS Y to Play again *"
Print " "
Print "* *"
Print "*********************************************************"
_Display
any$ = Input$(1)
If any$ = "y" Or any$ = "Y" Then
gfla$ = "GAMEON"
startlevel 1
Else
Cls
gflag$ = "GAMEOVER"
End If
End If
End Sub
Sub doboom
_KeyClear
Locate 10, 10: Print "*********************************************************"
Locate 11, 10: Print "* ÛÛÛÛÛÛÛÛ *"
Locate 12, 10: Print " Û0 0Û B O O M ! "
Locate 13, 10: Print "* ÛÛÛÛÛÛÛÛ *"
Locate 14, 10: Print " ^ ^^ ^ You Were Defeated by the ALIENs! "
Locate 15, 10: Print "* *"
Locate 16, 10: Print
Locate 17, 10: Print " FINAL SCORE : "; score
Locate 18, 10: Print
Locate 19, 10: Print "* PRESS Y to Play again ÛÛÛÛÛÛÛÛ *"
Locate 20, 10: Print " ÛÛÛÛÛÛÛÛ Û0 0Û "
Locate 21, 10: Print "* Û0 0Û ÛÛÛÛÛÛÛÛ *"
Locate 22, 10: Print "*********************************************************"
_Display
any$ = Input$(1)
If any$ = "y" Or any$ = "Y" Then
gflag$ = "GAMEON"
startlevel 1
Else
Cls
gflag$ = "GAMEOVER"
End If
End Sub
|