Anyone remember the 1980's arcade game (and later home computer / console game) Qix ?
I was thinking about how to re-create the "line monster" (the Qix) from this game. Basically it is an array of lines (ie: (x1,y1) and (x2,y2) coordinates). A line is drawn, then the color is dimmed a little, and the next line is drawn. This produces a fade out effect. The coordinates of the first line are changed each time the monster moves. Each remaining line is a copy of the one before it in the array. The code would be something like this:
for q = last_line to 2 step -1
line(q) = line(q-1)
next q
update_coords line(1)
In the 1980's game, the array contained only a handful of lines, maybe a dozen or so at most. This was likely done because of hardware limitations (both CPU speeds, and screen resolution). Today, with our high-res screens and faster CPUs, we can make the array much longer...
Below is my first attempt at doing this. It is not the most elegant code, but it works. The array is 135 lines long (const cnqlen, ie: Qix Length). It doesn't look exactly like the arcade. It sort of reminds me of the old "Mystify" screen saver for Windows... The line will change colors every few seconds, or you can press 1-7 to change colors.
I was thinking about how to re-create the "line monster" (the Qix) from this game. Basically it is an array of lines (ie: (x1,y1) and (x2,y2) coordinates). A line is drawn, then the color is dimmed a little, and the next line is drawn. This produces a fade out effect. The coordinates of the first line are changed each time the monster moves. Each remaining line is a copy of the one before it in the array. The code would be something like this:
for q = last_line to 2 step -1
line(q) = line(q-1)
next q
update_coords line(1)
In the 1980's game, the array contained only a handful of lines, maybe a dozen or so at most. This was likely done because of hardware limitations (both CPU speeds, and screen resolution). Today, with our high-res screens and faster CPUs, we can make the array much longer...
Below is my first attempt at doing this. It is not the most elegant code, but it works. The array is 135 lines long (const cnqlen, ie: Qix Length). It doesn't look exactly like the arcade. It sort of reminds me of the old "Mystify" screen saver for Windows... The line will change colors every few seconds, or you can press 1-7 to change colors.
Code: (Select All)
'' Qix line experiment 1 (first attempt at reproducing the "line monster" from the 1980's game Qix)
'' by Abazek 2025-Jan-19
''
'' Future plans:
'' 1. Optimize the code (there are parts of this I could do differently/better)
'' 2. Greater variety of movement (perhaps RND, or SIN and COS, so cx/cy can be more than just 1, 0, or -1)
'' 3. Qix size limits (ie: if qixA and qixB get too far apart, change cx/cy to bring them closer together)
Const cnqlen = 135
Const cnfade = 2
Const cnSPD = 0.05
Const cnResX = 1280
Const cnResY = 960
Const cnMinChg = 25
Const cnMaxChg = 100
Const defx1 = 620
Const defy1 = 460
Const defx2 = 660
Const defy2 = 500
Type coord
x As Integer
y As Integer
c As Integer
End Type
Dim qixA(cnqlen) As coord
Dim qixB(cnqlen) As coord
Dim scn&, pixcolr&
Dim a$, qq, d1, d2, colr, fw, flag, cl, clrchg, whenclr
Dim showc
Dim Shared cx, cy, chgdirA, chgdirB, whenChgA, whenChgB
Randomize Timer
scn& = _NewImage(cnResX, cnResY, 32)
Screen scn&
Cls 0, _RGB(0, 0, 0)
_Title "Qix Experiment 1"
For qq = 1 To cnqlen
qixA(qq).x = defx1
qixA(qq).y = defy1
qixA(qq).c = 7
qixB(qq).x = defx2
qixB(qq).y = defy2
qixB(qq).c = 7
Next qq
GoSub changedirA
GoSub changedirB
chgdirA = 0
chgdirB = 0
clrchg = 0
whenclr = cnMaxChg
showc = 0
flag = 0
While flag = 0
GoSub MoveQix
If showc = 1 Then GoSub ShowCoords
GoSub DrawQix
Color _RGB32(128, 128, 128)
Locate 1, 1
Print "ESC or SPACE to exit. S to show coordintates. D to hide coordintates. 1-7 manually change color."
''GoSub framewait
_Delay cnSPD
''GoSub WaitKey
a$ = InKey$
If a$ = Chr$(27) Then flag = 1
If a$ = Chr$(32) Then flag = 1
If a$ = "S" Or a$ = "s" Then showc = 1: Cls
If a$ = "D" Or a$ = "d" Then showc = 0: Cls
If a$ = "1" Then cl = 1: GoSub ManualClr
If a$ = "2" Then cl = 2: GoSub ManualClr
If a$ = "3" Then cl = 3: GoSub ManualClr
If a$ = "4" Then cl = 4: GoSub ManualClr
If a$ = "5" Then cl = 5: GoSub ManualClr
If a$ = "6" Then cl = 6: GoSub ManualClr
If a$ = "7" Then cl = 7: GoSub ManualClr
Wend
End
WaitKey:
a$ = InKey$
If a$ = "" Then GoTo WaitKey
If a$ = Chr$(27) Then flag = 1
Return
framewait:
fw = Timer
While (Abs(Timer - fw) < cnSPD)
Wend
Return
ShowCoords:
For qq = 1 To cnqlen
If qq < 51 Then
Locate (qq + 1), 1
ElseIf qq < 101 Then
Locate (qq - 49), 50
ElseIf qq < 151 Then
Locate (qq - 99), 100
Else
Locate 51, 100
End If
Color _RGB32(128, 128, 128)
Print "Coords "; qq; " = ("; qixA(qq).x; ","; qixA(qq).y; ") - ("; qixB(qq).x; ","; qixB(qq).y; ")"
Next qq
Locate 52, 1
Print "Timer = "; Timer; " Delay="; cnSPD; " ChgdirA="; chgdirA; "/"; whenChgA; " ChgdirB="; chgdirB; "/"; whenChgB;
colr = 128
GoSub setColor
Color pixcolr&
Print " Color "; clrchg; "/"; whenclr; " "
Return
DrawQix:
colr = 1
For qq = cnqlen To 1 Step -1
cl = qixA(qq).c
GoSub setColor
Color pixcolr&
Line (qixA(qq).x, qixA(qq).y)-(qixB(qq).x, qixB(qq).y), pixcolr&
colr = colr + cnfade
If colr > 255 Then colr = 255
Next qq
Color _RGB32(1, 1, 1)
Return
MoveQix:
For qq = cnqlen To 2 Step -1
qixA(qq).x = qixA(qq - 1).x
qixA(qq).y = qixA(qq - 1).y
qixA(qq).c = qixA(qq - 1).c
qixB(qq).x = qixB(qq - 1).x
qixB(qq).y = qixB(qq - 1).y
qixB(qq).c = qixB(qq - 1).c
Next qq
qq = 1
chgdirA = chgdirA + 1
chgdirB = chgdirB + 1
clrchg = clrchg + 1
If chgdirA > whenChgA Then
GoSub changedirA
End If
If chgdirB > whenChgB Then
GoSub changedirB
End If
If clrchg > whenclr Then
GoSub changeClr
qixA(qq).c = cl
qixB(qq).c = cl
End If
SetMoveDir d1
cx = cx * 2
cy = cy * 2
qixA(qq).x = qixA(qq).x + cx
qixA(qq).y = qixA(qq).y + cy
If qixA(qq).x < 1 Then qixA(qq).x = 1: GoSub changedirA
If qixA(qq).x > cnResX Then qixA(qq).x = cnResX: GoSub changedirA
If qixA(qq).y < 1 Then qixA(qq).y = 1: GoSub changedirA
If qixA(qq).y > cnResY Then qixA(qq).y = cnResY: GoSub changedirA
SetMoveDir d2
cx = cx * 2
cy = cy * 2
qixB(qq).x = qixB(qq).x + cx
qixB(qq).y = qixB(qq).y + cy
If qixB(qq).x < 1 Then qixB(qq).x = 1: GoSub changedirB
If qixB(qq).x > cnResX Then qixB(qq).x = cnResX: GoSub changedirB
If qixB(qq).y < 1 Then qixB(qq).y = 1: GoSub changedirB
If qixB(qq).y > cnResY Then qixB(qq).y = cnResY: GoSub changedirB
Return
changedirA:
d1 = Int(Rnd * 8) + 1
cl = cnMaxChg - cnMinChg
whenChgA = Int(Rnd * cl) + cnMinChg
chgdirA = 0
Return
changedirB:
d2 = Int(Rnd * 8) + 1
cl = cnMaxChg - cnMinChg
whenChgB = Int(Rnd * cl) + cnMinChg
chgdirB = 0
Return
changeClr:
cl = Int(Rnd * 7) + 1
clrchg = 0
Return
ManualClr:
qixA(1).c = cl
qixB(1).c = cl
clrchg = 0
Return
setColor:
Select Case cl
Case 1
pixcolr& = _RGB32(colr, 0, 0)
Case 2
pixcolr& = _RGB32(0, colr, 0)
Case 3
pixcolr& = _RGB32(colr, colr, 0)
Case 4
pixcolr& = _RGB32(0, 0, colr)
Case 5
pixcolr& = _RGB32(colr, 0, colr)
Case 6
pixcolr& = _RGB32(0, colr, colr)
Case Else
pixcolr& = _RGB32(colr, colr, colr)
End Select
Return
Sub SetMoveDir (dir)
Select Case dir
Case 1
cx = 1: cy = 0
Case 2
cx = 0: cy = 1
Case 3
cx = -1: cy = 0
Case 4
cx = 0: cy = -1
Case 5
cx = 1: cy = -1
Case 6
cx = -1: cy = 1
Case 7
cx = -1: cy = -1
Case Else
cx = 1: cy = 1
End Select
End Sub