Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tank Battle - One or Two Player
#1
I originally wrote this program in assembly for the commodore pet in 1979-80ish.
Revised 9/2/25 - Bullets reflect off brown walls, 2 active bullets on the screen per tank at same time.
Revised 9/4/25 - Now utilizes attached controllers and/or keyboard, full screen and a windows font versus the dos font.
Revised 9/9/25 - Biggest revision - Now has AI tank to battle for single player, info screen and full screen is a toggle + other fixes or improvements.
Final Revision 9/14/25 - Third tank added - Use P F and I during game play for interesting toggles.
Revise (lol) 9/21/25 - Now with Two Computer Tanks (Can battle each other) and adjustable speed.
Download the zip file for all supporting files.

Code: (Select All)
$ExeIcon:'./\data\favicon.ico'
'
'
'                      *****  Tank Battle By David Coterel - September 2025  *****
'
' After first coding this game in basic for the Commodore Pet in 1978 and then realizing it was very slow
' I picked up a book and learned assembly and reprogrammed a very basic version of this game in assembly
'    A neighbor friend and I play this game for hours, learning QB64PE I was encouraged to rewrite
'  This game from the old days, it"s been a great trip in the past for me and with the power of qb64PE
'      and today's modern computers, I have added alot of extras, I hope you enjoy playing this game.
'
'
'






$Resize:Smooth
_Title "Tank Battle"

DefInt A-Z
Dim Shared dh, dw
Dim colo As _Unsigned Long
Randomize (-Timer)

dw = _DesktopWidth
dh = _DesktopHeight

If dw < 1024 Or dh < 768 Then Cls: Print "A minimum Screen Resolution of 1024 x 768 is required to play": End
If InStr(_Device$(1), "KEYBOARD") = 0 Then Print "A Keyboard is required": End
If InStr(_Device$(2), "MOUSE") = 0 Then Print "A Mouse is required": End

dw = 1024: dh = 768: fps! = 60

fir& = _SndOpen("data\gun.wav")
ex& = _SndOpen("data\explosion.wav")
tm1& = _SndOpen("data\tm1.wav")
tm2& = _SndOpen("data\tm2.wav")
bu& = _LoadImage("data\bush.png", 32)
br& = _LoadImage("data\brick.png", 32)
bru& = _LoadImage("data\bricku.png", 32)
las& = _SndOpen("data\laser.wav")

Const wh& = _RGB32(255, 255, 255)
Const bl& = _RGB32(0, 0, 0)
Const bor& = _RGB32(155, 100, 255)
Const t1& = _RGB32(255, 255, 0)
Const t2& = _RGB32(0, 255, 0)
Const t3& = _RGB32(11, 55, 194)
Const t31& = _RGB32(175, 0, 0)
Const mi& = _RGB32(255, 0, 0)
Const red& = _RGB32(255, 15, 15)
Const bro& = _RGB32(133, 72, 11)
Const gre& = _RGB32(50, 150, 50)
Const gra& = _RGB32(100, 100, 100)

pls& = _NewImage(dw, dh, 32): _Dest pls&: Cls
Line (15, 15)-(dw - 16, dh - 16), bor&, B: Paint (3, 3), bor&, bor&
Line (59, 59)-(dw - 60, dh - 60), bro&, B: Line (79, 79)-(dw - 79, dh - 79), bro&, B: Paint (61, 61), bro&, bro&
Line (20, 139)-(dw - 20, dh - 140), bl&, BF: Line (139, 20)-(dw - 140, dh - 21), bl&, BF
Line (206, 192)-(306, 242), bro&, BF: Line (226, 192)-(286, 222), bl&, BF
Line (dw - 307, 192)-(dw - 207, 242), bro&, BF: Line (dw - 287, 192)-(dw - 227, 222), bl&, BF
Line (206, dh - 243)-(306, dh - 193), bro&, BF: Line (226, dh - 223)-(286, dh - 193), bl&, BF
Line (dw - 307, dh - 243)-(dw - 207, dh - 193), bro&, BF: Line (dw - 287, dh - 223)-(dw - 227, dh - 193), bl&, BF
_PutImage (dw * .5 - 100, 59), br&: _PutImage (dw * .5 - 100, dh - 109), br&: _PutImage (59, dh * .5 - 100), bru&: _PutImage (dw - 109, dh * .5 - 100), bru&
Line (dw * .5 - 200, dh * .5 - 100)-(dw * .5 + 200, dh * .5 + 100), gre&, BF: Line (dw * .5 - 180, dh * .5 - 80)-(dw * .5 + 180, dh * .5 + 80), bl&, BF
Line (dw * .5 - 80, dh * .5 - 100)-(dw * .5 + 80, dh * .5 + 100), bl&, BF: Line (dw * .5 - 200, dh * .5 - 30)-(dw * .5 + 200, dh * .5 + 30), bl&, BF
ctx = dw * .5: cty = dh * .5: Circle (ctx, cty), 30, t3&: Paint (ctx, cty), t3&, t3&: Circle (ctx, cty), 15, bl&: Circle (ctx, cty), 14, bl&: Circle (ctx, cty), 16, bl&
Line (ctx - 1, cty - 40)-(ctx + 1, cty + 40), t31&, BF: Line (ctx - 40, cty - 1)-(ctx + 40, cty + 1), t31&, BF: Circle (ctx, cty), 6, wh&: Paint (ctx, cty), bl&, wh&
f& = _LoadFont("data/font2.ttf", 16): _Font f&
Color bl&, bor&: a$ = "Press +/- for Speed / 1 or 2 for Tank AI / I for Info Screen / F to toggle Fullscreen": w1 = _PrintWidth(a$) * .5: Locate 48, dw * .5 - w1: Print a$;
Screen _NewImage(dw, dh, 32): dc = _Devices: _CapsLock Off

f& = _LoadFont("data/font2.ttf", 16): _Font f&: _PutImage , pls&
dio = 1: cloc = dw * .5 - 100: loc1 = dw * .5 - 198: loc2 = dw * .5 + 8: step1 = 1: x = 100: y = 100: a = dw - 101: b = dh - 101

Circle (x, y), 6, t1&: Paint (x, y), t1&, t1&: Circle (x, y), 3, bl&: Line (x, y)-(x + 12, y), red&
Circle (a, b), 6, t2&: Paint (a, b), t2&, t2&: Circle (a, b), 3, bl&: Line (a, b)-(a - 12, b), red&
Line (dw * .5 - 210, dh * .5 - 110)-(dw * .5 + 210, dh * .5 + 110), bor&, BF
Line (dw * .5 - 200, dh * .5 - 100)-(dw * .5 + 200, dh * .5 + 100), t2&, BF
Color bl&, t2&
PrintScreen "Thanks for playing Tank Battle By David Coterel", -5
PrintScreen "Tanks can be controlled with the keyboard or", -4
PrintScreen "Controllers, the Keyboard uses A,S,D,W and Space", -3
PrintScreen "for the Yellow Tank and the Cursor Keys and", -2
PrintScreen "Right CNTRL for the Green Tank, Tanks can fire", -1
PrintScreen "two bullets at a time, bullets will reflect if", 0
PrintScreen "they hit a brown wall and can be recaptured", 1
PrintScreen "by the tank that fired them but are deadly to", 2
PrintScreen "the other tank. 10 Kills wins the game.", 3
PrintScreen "If the center tank hits you you will loose 1 kill", 4
PrintScreen "I>Info F>Fullscreen 1-2 for AI Tank & ESC>Ends", 5
Do: _Limit 120: Locate dh / 32 + 6, cloc: Print " PRESS ENTER TO START ";: cloc = cloc + step1
    If cloc = loc2 Then step1 = -1: Sound 100, .5: Else If cloc = loc1 Then step1 = 1: Sound 100, .5
    _Display: i$ = InKey$: If i$ = "f" Then If _FullScreen = 0 Then _FullScreen Else _FullScreen _Off
Loop Until _KeyDown(13) Or _KeyDown(27): If _KeyDown(27) GoTo Gameover
_SndVol las&, .3

Start:

a2 = -1: b2 = 0: x2 = 1: y2 = 0: f1 = 0: f2 = 0: f3 = 0: f4 = 0: x = 100: y = 100
a = dw - 101: b = dh - 101: fx1 = 0: fy1 = 0: fa1 = 0: fb1 = 0


Do
    _Limit fps!: _PutImage , pls&
    d = 12 - (((Abs(x2) + Abs(y2)) - 1) * 4): Circle (x, y), 6, t1&: Paint (x, y), t1&, t1&: Circle (x, y), 3, bl&: Line (x, y)-(x + x2 * d, y + y2 * d), red&
    d = 12 - (((Abs(a2) + Abs(b2)) - 1) * 4): Circle (a, b), 6, t2&: Paint (a, b), t2&, t2&: Circle (a, b), 3, bl&: Line (a, b)-(a + a2 * d, b + b2 * d), red&
    If dt$ <> Time$ Then dt = 1 - dt: dt$ = Time$: If dt = 1 Then las = 0
    If dt = 1 Then Paint (ctx, cty), gre&, wh&
    If las = 0 Then _SndPlay las&: las = 1


    If ply1 <> -1 Then x1 = 0: y1 = 0
    If ply2 <> -1 Then a1 = 0: b1 = 0

    If f5 = 0 And dt = 1 Then
        For t = 43 To (dw * .5) - 16 Step 3
            PSet (ctx + t, cty - 1), gra&: PSet (ctx - t, cty - 1), gra&
            If (ply1 = 0 And Point(ctx + t, cty) = t1&) Or (ply2 = 0 And Point(ctx + t, cty) = t2&) Then ctx1 = 1: cty1 = 0: fire3 = 1
            If (ply1 = 0 And Point(ctx - t, cty) = t1&) Or (ply2 = 0 And Point(ctx - t, cty) = t2&) Then ctx1 = -1: cty1 = 0: fire3 = 1
        Next t

        For t = 43 To (dh * .5) - 16 Step 3
            PSet (ctx - 1, cty + t), gra&: PSet (ctx - 1, cty - t), gra&
            If (ply1 = 0 And Point(ctx, cty + t) = t1&) Or (ply2 = 0 And Point(ctx, cty + t) = t2&) Then ctx1 = 0: cty1 = 1: fire3 = 1
            If (ply1 = 0 And Point(ctx, cty - t) = t1&) Or (ply2 = 0 And Point(ctx, cty - t) = t2&) Then ctx1 = 0: cty1 = -1: fire3 = 1
        Next t
    End If


    If inf = -1 Then
        Color bl&, bor&: a$ = Str$(Int(_Hypot(x - a, y - b))): a$ = "Distance: " + Right$(a$, Len(a$) - 1): Locate 1, dw * .25 - 70: Print a$;
        Locate 1, dw * .75 - 60: Print Using "### ###"; x, y;: Locate 1, dw * .75 + 10: Print Using "### ###"; a, b;
        Locate 1, 16: Print "FPS:"; cfps: fps = fps + 1
        If t$ <> Time$ Then t$ = Time$: cfps = fps: fps = 0
        a$ = "Shots:" + Str$(sh): w1 = _PrintWidth(a$) + 16: Locate 1, dw - w1: Print a$;
    End If

    If f1 = 0 Then f1travel = 0
    If f2 = 0 Then f2travel = 0
    If f3 = 0 Then f3travel = 0
    If f4 = 0 Then f4travel = 0

    If f1 = 1 Then
        Circle (fx, fy), 2, mi&: Circle (fx + fx1, fy + fy1), 2, mi&: Circle (fx + fx1 * 2, fy + fy1 * 2), 2, mi&
        fx = fx + fx1 * 3: fy = fy + fy1 * 3: f1travel = f1travel + 1
        If f1travel = 200 Then f1 = 0
    End If

    If f2 = 1 Then
        Circle (fa, fb), 2, mi&: Circle (fa + fa1, fb + fb1), 2, mi&: Circle (fa + fa1 * 2, fb + fb1 * 2), 2, mi&
        fa = fa + fa1 * 3: fb = fb + fb1 * 3: f2travel = f2travel + 1
        If f2travel = 200 Then f2 = 0
    End If

    If f3 = 1 Then
        Circle (fc, fd), 2, mi&: Circle (fc + fc1, fd + fd1), 2, mi&: Circle (fc + fc1 * 2, fd + fd1 * 2), 2, mi&
        fc = fc + fc1 * 3: fd = fd + fd1 * 3: f3travel = f3travel + 1
        If f3travel = 200 Then f3 = 0
    End If

    If f4 = 1 Then
        Circle (fe, ff), 2, mi&: Circle (fe + fe1, ff + ff1), 2, mi&: Circle (fe + fe1 * 2, ff + ff1 * 2), 2, mi&
        fe = fe + fe1 * 3: ff = ff + ff1 * 3: f4travel = f4travel + 1
        If f4travel = 200 Then f4 = 0
    End If

    If f5 = 1 Then
        Circle (ctfx, ctfy), 2, mi&: Circle (ctfx + ctx1 * 2, ctfy + cty1 * 2), 2, mi&: Circle (ctfx + ctx1 * 4, ctfy + cty1 * 4), 2, mi&
        Circle (ctfx + ctx1 * 6, ctfy + cty1 * 6), 2, mi&: Circle (ctfx + ctx1 * 8, ctfy + cty1 * 8), 2, mi&
        ctfx = ctfx + ctx1 * 10: ctfy = ctfy + cty1 * 10
    End If

    If ply1 <> -1 Then
        If dc > 3 Then While _DeviceInput(4): Wend: x1 = _Axis(1): y1 = _Axis(2): fire1 = _Button(2)
        If x1 < -.5 Then x1 = -1 Else If x1 > .5 Then x1 = 1 Else x1 = 0
        If y1 < -.5 Then y1 = -1 Else If y1 > .5 Then y1 = 1 Else y1 = 0
        If _KeyDown(100) Then x1 = 1 Else If _KeyDown(97) Then x1 = -1
        If _KeyDown(115) Then y1 = 1 Else If _KeyDown(119) Then y1 = -1
    End If

    If ply2 <> -1 Then
        If dc > 2 Then While _DeviceInput(3): Wend: a1 = _Axis(1): b1 = _Axis(2): fire2 = _Button(2)
        If a1 < -.5 Then a1 = -1 Else If a1 > .5 Then a1 = 1 Else a1 = 0
        If b1 < -.5 Then b1 = -1 Else If b1 > .5 Then b1 = 1 Else b1 = 0
        If _KeyDown(19200) Then a1 = -1 Else If _KeyDown(19712) Then a1 = 1
        If _KeyDown(18432) Then b1 = -1 Else If _KeyDown(20480) Then b1 = 1
    End If


    If ply1 <> -1 And _KeyDown(32) And f1$ <> Time$ Then: fire1 = 1: f1$ = Time$
    If ply2 <> -1 And _KeyDown(100305) And f2$ <> Time$ Then fire2 = 1: f2$ = Time$





    If ply1 = -1 Then
        'AI1 Tank Moves
        If fu1$ <> Time$ And ob1$ <> Time$ Then
            x1 = 0: y1 = 0
            If _Hypot(x - a, y - b) > 40 Then
                If x < a - 3 Then x1 = 1 Else If x > a + 3 Then x1 = -1
                If y < b - 3 Then y1 = 1 Else If y > b + 3 Then y1 = -1
            End If
        End If

        'AI1 Tank encounters an obstacle
        colo = Point(x + x1 * 13, y + y1 * 13)
        If colo <> bl& And colo <> mi& And colo <> gra& And ob1$ <> Time$ Then
            ob1$ = Time$: px1 = x1: py1 = y1
            Recalc1: x1 = 1 - Int(Rnd(1) * 3): y1 = 1 - Int(Rnd(1) * 3)
            If Point(x + x1 * 20, y + y1 * 20) <> bl& GoTo Recalc1
            If px1 = x1 And py1 = y1 GoTo Recalc1
        End If

        'AI1 Tank fires
        t = 12: Do: t = t + 1: colo = Point(x + x2 * t, y + y2 * t): Loop Until (colo <> bl& And colo <> gra&) Or t > 300
        If (colo = t2& Or colo = red&) And ftime1$ <> Time$ Then fire1 = 1: ftime1$ = Time$

        'AI1 Tank is fired upon (retreats)
        If (f2 = 1 Or f4 = 1) And fu1$ <> Time$ And (_Hypot(x - fa, y - fb) < 200 Or _Hypot(x - fe, y - ff) < 200) Then
            px1 = x1: py1 = y1: fu1$ = Time$
            Recalc2: x1 = 1 - Int(Rnd(1) * 3): y1 = 1 - Int(Rnd(1) * 3)
            If Point(x + x1 * 20, y + y1 * 20) <> bl& GoTo Recalc2
            If x1 = px1 And y1 = py1 GoTo Recalc2
            If x1 = px1 * -1 And y1 = py1 * -1 GoTo Recalc2
        End If
    End If


    If ply2 = -1 Then
        'AI2 Tank Moves
        If fu2$ <> Time$ And ob2$ <> Time$ Then
            a1 = 0: b1 = 0
            If _Hypot(a - x, b - y) > 40 Then
                If a < x - 3 Then a1 = 1 Else If a > x + 3 Then a1 = -1
                If b < y - 3 Then b1 = 1 Else If b > y + 3 Then b1 = -1
            End If
        End If

        'AI2 Tank encounters an obstacle
        colo = Point(a + a1 * 13, b + b1 * 13)
        If colo <> bl& And colo <> mi& And colo <> gra& And ob2$ <> Time$ Then
            ob2$ = Time$: pa1 = a1: pb1 = b1
            Recalc3: a1 = 1 - Int(Rnd(1) * 3): b1 = 1 - Int(Rnd(1) * 3)
            If Point(a + a1 * 20, b + b1 * 20) <> bl& GoTo Recalc3
            If pa1 = a1 And pb1 = b1 GoTo Recalc3
        End If

        'AI2 Tank fires
        t = 12: Do: t = t + 1: colo = Point(a + a2 * t, b + b2 * t): Loop Until (colo <> bl& And colo <> gra&) Or t > 300
        If (colo = t1& Or colo = red&) And ftime2$ <> Time$ Then fire2 = 1: ftime2$ = Time$

        'AI2 Tank is fired upon (retreats)
        If (f1 = 1 Or f3 = 1) And fu2$ <> Time$ And (_Hypot(a - fc, b - fd) < 200 Or _Hypot(a - fx, b - fy) < 200) Then
            pa1 = a1: pb1 = b1: fu2$ = Time$
            Recalc4: a1 = 1 - Int(Rnd(1) * 3): b1 = 1 - Int(Rnd(1) * 3)
            If Point(a + a1 * 20, b + b1 * 20) <> bl& GoTo Recalc4
            If a1 = pa1 And b1 = pb1 GoTo Recalc4
            If a1 = pa1 * -1 And b1 = pb1 * -1 GoTo Recalc4
        End If
    End If





    If x1 <> 0 Or y1 <> 0 Then x2 = x1: y2 = y1
    If a1 <> 0 Or b1 <> 0 Then a2 = a1: b2 = b1

    If fire1 <> 0 Then GoSub fire1 Else ss1 = 0
    If fire2 <> 0 Then GoSub fire2 Else ss2 = 0
    If fire3 <> 0 Then GoSub fire3

    If Point(x + x1 * 13, y + y1 * 13) <> bl& And Point(x + x1 * 13, y + y1 * 13) <> gra& Then x1 = 0: y1 = 0
    If Point(a + a1 * 13, b + b1 * 13) <> bl& And Point(a + a1 * 13, b + b1 * 13) <> gra& Then a1 = 0: b1 = 0

    x = x + x1: y = y + y1: a = a + a1: b = b + b1

    If x1 <> 0 Or y1 <> 0 Then _SndLoop tm1& Else _SndStop tm1&
    If a1 <> 0 Or b1 <> 0 Then _SndLoop tm2& Else _SndStop tm2&

    If f1 = 1 And _Hypot(a - fx, b - fy) < 10 Then s1 = s1 + 1: f1 = 0: thit = 2: GoTo tahit
    If f2 = 1 And _Hypot(x - fa, y - fb) < 10 Then s2 = s2 + 1: f2 = 0: thit = 1: GoTo tahit
    If f3 = 1 And _Hypot(a - fc, b - fd) < 10 Then s1 = s1 + 1: f3 = 0: thit = 2: GoTo tahit
    If f4 = 1 And _Hypot(x - fe, y - ff) < 10 Then s2 = s2 + 1: f4 = 0: thit = 1: GoTo tahit
    If f5 = 1 And ply1 = 0 And _Hypot(ctfx - x, ctfy - y) < 10 Then f5 = 0: s1 = s1 - 1: thit = 1: GoTo tahit
    If f5 = 1 And ply2 = 0 And _Hypot(ctfx - a, ctfy - b) < 10 Then f5 = 0: s2 = s2 - 1: thit = 2: GoTo tahit

    If f1 = 1 And Point(fx + fx1 * 3, fy + fy1 * 3) = bro& Then p1 = 1: Reflect fx, fy, fx1, fy1: Else p1 = 0
    If f2 = 1 And Point(fa + fa1 * 3, fb + fb1 * 3) = bro& Then p2 = 1: Reflect fa, fb, fa1, fb1: Else p2 = 0
    If f3 = 1 And Point(fc + fc1 * 3, fd + fd1 * 3) = bro& Then p3 = 1: Reflect fc, fd, fc1, fd1: Else p3 = 0
    If f4 = 1 And Point(fe + fe1 * 3, ff + ff1 * 3) = bro& Then p4 = 1: Reflect fe, ff, fe1, ff1: Else p4 = 0

    If f1 = 1 And Point(fx + fx1 * 2, fy + fy1 * 2) <> bl& And Point(fx + fx1 * 2, fy + fy1 * 2) <> red& And Point(fx + fx1 * 2, fy + fy1 * 2) <> gra& Then f1 = 0
    If f2 = 1 And Point(fa + fa1 * 2, fb + fb1 * 2) <> bl& And Point(fa + fa1 * 2, fb + fb1 * 2) <> red& And Point(fa + fa1 * 2, fb + fb1 * 2) <> gra& Then f2 = 0
    If f3 = 1 And Point(fc + fc1 * 2, fd + fd1 * 2) <> bl& And Point(fc + fc1 * 2, fd + fd1 * 2) <> red& And Point(fc + fc1 * 2, fd + fd1 * 2) <> gra& Then f3 = 0
    If f4 = 1 And Point(fe + fe1 * 2, ff + ff1 * 2) <> bl& And Point(fe + fe1 * 2, ff + ff1 * 2) <> red& And Point(fe + fe1 * 2, ff + ff1 * 2) <> gra& Then f4 = 0
    If f5 = 1 And Point(ctfx + ctx1 * 2, ctfy + cty1 * 2) = bor& Then f5 = 0



    Color bl&, bor&: a$ = "Yellow ###  -  Green ###": w1 = _PrintWidth(a$) * .5: Locate 1, dw * .5 - w1
    Print Using a$; s1; s2;: Color bl&, bl&: _Display
    i$ = InKey$: If i$ = "i" Then inf = Not (inf)
    If i$ = "1" Then ply1 = Not (ply1)
    If i$ = "2" Then ply2 = Not (ply2)
    If i$ = "f" Then If _FullScreen = 0 Then _FullScreen Else _FullScreen _Off
    If i$ = "+" Then fps! = fps! + 5: If fps! = 125 Then fps! = 120
    If i$ = "-" Then fps! = fps! - 5: If fps! = 15 Then fps! = 20
Loop Until _KeyDown(27): GoTo Gameover


tahit:
_SndStop tm1&: _SndStop tm2&: Color bl&, bor&: a$ = "Yellow ###  -  Green ###": w1 = _PrintWidth(a$) * .5
Locate 1, dw * .5 - w1: Print Using a$; s1; s2;: If thit = 2 Then x = a: y = b
_SndPlay ex&: For a = 1 To 3: For b = 1 To 17: _Limit 20
        Circle (x, y), b, wh&: Circle (x, y), b - 1, bl&
_Display: Next b, a
If ply1 = -1 And ply2 = -1 GoTo Start
If s1 < 10 And s2 < 10 GoTo Start


Gameover:
_SndStop tm1&: _SndStop tm2&: Do While _KeyDown(27): _Limit 60: Loop
Line (dw * .5 - 210, dh * .5 - 110)-(dw * .5 + 210, dh * .5 + 110), bor&, BF
Line (dw * .5 - 200, dh * .5 - 100)-(dw * .5 + 200, dh * .5 + 100), t2&, BF
Color bl&, t2&
PrintScreen "Thanks for playing Tank Battle By David Coterel", -2
If s1 > s2 Then PrintScreen "Player 1 (Yellow) is the Winner", 0
If s2 > s1 Then PrintScreen "Player 2 (Green) Wins the game", 0
If s2 = s1 Then PrintScreen "Player 1 ->  Tie Game  <- Player 2", 0
PrintScreen "Press ESC to end", 2: _Display
Do: _Limit 60: Loop Until _KeyDown(27)
_FreeImage pls&: _Font 16: _FreeFont f&: _AutoDisplay: System


fire1:
fire1 = 0
If f1 = 0 And (x2 <> 0 Or y2 <> 0) And Point(x + x2 * 18, y + y2 * 18) = bl& Then
    f1 = 1: sh = sh + 1: fx1 = x2: fy1 = y2: fx = x + fx1 * 13: fy = y + fy1 * 13: _SndPlay fir&: ss1 = 1
End If

If ss1 = 0 And f1 = 1 And f3 = 0 And (x2 <> 0 Or y2 <> 0) And Point(x + x2 * 18, y + y2 * 18) = bl& Then
    f3 = 1: sh = sh + 1: fc1 = x2: fd1 = y2: fc = x + fc1 * 13: fd = y + fd1 * 13: _SndPlay fir&
End If
Return


fire2:
fire2 = 0
If f2 = 0 And (a2 <> 0 Or b2 <> 0) And Point(a + a2 * 18, b + b2 * 18) = bl& Then
    f2 = 1: sh = sh + 1: fa1 = a2: fb1 = b2: fa = a + fa1 * 14: fb = b + fb1 * 14: _SndPlay fir&: ss2 = 1
End If

If ss2 = 0 And f2 = 1 And f4 = 0 And (a2 <> 0 Or b2 <> 0) And Point(a + a2 * 18, b + b2 * 18) = bl& Then
    f4 = 1: sh = sh + 1: fe1 = a2: ff1 = b2: fe = a + fe1 * 13: ff = b + ff1 * 13: _SndPlay fir&
End If
Return


fire3:
fire3 = 0: sh = sh + 1: f5 = 1:: ctfx = ctx + ctx1 * 40: ctfy = cty + cty1 * 40: _SndPlay fir&
Return


Sub Reflect (a, b, e, f)
    If Point(a, b + 3) = bro& Or Point(a, b - 3) = bro& Then f = f * -1
    If Point(a + 3, b) = bro& Or Point(a - 3, b) = bro& Then e = e * -1
End Sub


Sub PrintScreen (a$, voff)
    w1 = _PrintWidth(a$) * .5: Locate dh / 32 + voff, dw * .5 - w1: Print a$: _Display
End Sub


Attached Files
.zip   Tank.zip (Size: 4.03 MB / Downloads: 52)
Reply
#2
I can't wait to try this. I wrote a tank battle game in VB6 in 2005, that I've been meaning to port over to QB64PE, this might be the inspiration I need. 

Much respect to anyone programming assembly on the C= PET in 1979 :-) !

I'm curious - How would you compare programming this in QB64PE in 2025 with 6502(?) assembly in the late '70s?
Reply
#3
(09-02-2025, 01:35 AM)madscijr Wrote: I can't wait to try this. I wrote a tank battle game in VB6 in 2005, that I've been meaning to port over to QB64PE, this might be the inspiration I need. 

Much respect to anyone programming assembly on the C= PET in 1979 :-) !

I'm curious - How would you compare programming this in QB64PE in 2025 with 6502(?) assembly in the late '70s?

I learned basic programming on an IBM 5100 at my uncles business, my family saw my interest and bought me a Pet for my 14th birthday (78), it instantly consumed all my spare time, I wrote a tank battle game in basic using peeks and pokes where both tanks could move at the same time and fire at the same time while maintaining movement with the tanks but it was extremely slow, I needed to make it faster so I picked up a book on the 6502 assembly language which was as close to machine level programming I could get (that I knew of then) and slowly moved my game over, my neighbor and I spent many hours playing... fast forward 45 years, I have always had a computer in my life and have always programmed simple games and various programs, started with C=Pet, C64, C128 (a couple radio shacks) and then finally after graduating college the IBM XT, I never did attempt to program in assembly again because the languages were just able to do things so much faster, now with QB64PE I'm back to programming again and it continues to consume my extra time, I am currently going through the tutorial just to make sure I'm not missing any of it. As you can tell by my programming structure I come from the old days (goto's and gosub's), learning now how to declare variables, use sub's and functions, etc. in order to program in a much more modern way... I still remember assembly but would not know where to begin today, the commodore was an 8 bit machine that barely ran at 1 Mhz (I think it's speed was measured in kb's/second), but that's where it all began for me...
Reply
#4
Quote:I originally wrote this program in assembly
We bow down to your greatness! I did ASM at UNI and even with my love of coding, damn that stuff makes no sense! 

Unseen
Reply
#5
(09-02-2025, 08:50 PM)dcoterel Wrote: I learned basic programming on an IBM 5100 at my uncles business, my family saw my interest and bought me a Pet for my 14th birthday (78), it instantly consumed all my spare time, I wrote a tank battle game in basic using peeks and pokes where both tanks could move at the same time and fire at the same time while maintaining movement with the tanks but it was extremely slow, I needed to make it faster so I picked up a book on the 6502 assembly language...

Your story sounds a lot like mine!

I started out on a TRS-80 Model 1 at school, learning the basics of BASIC. Then got my own computers - Texas Instruments TI99/4A, Commodore 64 (taught myself how to program with all the PEEKs and POKEs, and rudimentary 6502 assembly language). Eventually I wound up in Windows and spent years in different languages but always preferred BASIC. Microsoft had QuickBasic and VB6 which I used, but those got discontinued and .NET just kept changing and getting too damn complicated. All my programs kept becoming obsolete because they kept deprecating everything! Finally I found QB64 which is nice and simple, but still has all the cool structured programming features I first saw in Pascal. And for the most part it has stayed backwards-compatible in the 5 years since I started. Yay!
Reply
#6
My experience started on my hand me down pc (an IBM 286 with 1mb of ram and 20mb hard disk)...hardware im sure you guys would have drooled over! And later on in life the having to edit the config file in order to get enough ram to run commander keen and then discovering (pds qb 7.1) I was hooked...now having learned what other languages/engines offer i have made it my mission to add as many of these features as i can to to QB64...

You guys make me feel like a spring chicken though!

Thanks!

Unseen
Reply
#7
(09-02-2025, 11:22 PM)Unseen Machine Wrote: My experience started on my hand me down pc (an IBM 286 with 1mb of ram and 20mb hard disk)...hardware im sure you guys would have drooled over! 

We would have! I still remember getting my first 3.5" floppy drive, the Commodore 1581, which held a whopping 700k per disk! "What am I going to do with all this storage??" LoL, little did we know. My first IBM compatible was a 286 running DOS with 640 MB RAM (10x as much as the C64!) and a 20 MB HDD (I think it was RLL? Whatever they used before IDE and E-IDE and SCSI and SATA, etc.) 20 MB back then was a lot! I upgraded the motherboard to a 386 and managed to fit Windows 3.1 on it, though I had to use some trickery and delete the DOS files (which were loaded into memory) during the installation, to make enough room for it. Needless to say, with Windows you needed a whole other level of hardware.

(09-02-2025, 11:22 PM)Unseen Machine Wrote: You guys make me feel like a spring chicken though!

It's all relative! Kids turning 18 this year never lived in a world without the iPhone - how's that for a little perspective?? Wink
Reply
#8
(09-02-2025, 08:50 PM)dcoterel Wrote: As you can tell by my programming structure I come from the old days (goto's and gosub's), learning now how to declare variables, use sub's and functions, etc. in order to program in a much more modern way...
Well at least you managed to avoid using line numbers, LOL!

I edited your program to be a little less "spaghetti code" (see below)
  • Break up multi-statement lines - other people here use them, and I try to use them judiciously, but if I want to make code easier to follow, one statement per line helps.

  • Make all IF statements have a matching END IF, so QB64PE's editor auto-indents which makes it easier to follow the flow of logic.

  • Do ... Loop statements are a lot easier to follow when everything is on a separate line and indented.

  • Avoid cute "space saving" tricks like " Next b, a" - for me at least, it's easier to follow logic where each block has a matching end or next statement.

  • Add in some horizontal line comments to help visually break up the sections.

That's just the beginning. Next I would
  • Add comments at the top of each section, that describe what the code is doing.

  • Use longer more descriptive variable names -
    I know back in the old days many computers (like the C64) only let you use 2-letter variable names.
    Thankfully modern programming languages let you name your variables in a way that makes it easier to follow the code.
    e.g., instead of fir& name it GunSound&, instead of bl& name it black&

  • Move the "GOSUB" routine and anything reusable inside a Sub or a Function
    (if you need to return a value, use a Function, else use a Sub).
    Giving each routine a name that describes what it's doing.

  • Get rid of GOTO statements and rewrite the logic using structured programming.

This is just how I try to approach it, but there's more than one way to cook an egg, and sometimes I break my own rules when it makes sense. 
I think you'll find that everyone here has their own personal preferences. 
I tend to use a lot of comments and stuff that tends to give some of the guys a headache (right, Steve?   Wink LOL)

Anyway, I hope this helps. Thanks again for sharing your game! 

BTW, it might be fun to add other features like 
  • computer-controlled tanks
  • weapon and shield "powerups"
  • limited ammo and fuel (players have to return to base to reload?)
  • a screen editor to change the terrain, walls, etc.
  • maybe a way to edit the tanks and other graphics
  • etc.

Here is the cleaned up code:

Code: (Select All)
' Tank Battle - Two Player
' https://qb64phoenix.com/forum/showthread.php?tid=3899

' #1 dcoterel
' 08-31-2025, 09:07 PM (This post was last modified: 6 hours ago by dcoterel.)
' I originally wrote this program in assembly for the commodore pet in 1979-80ish.
' Revised 9/2/25 - Bullets reflect off brown walls, 2 active bullets on the screen per tank at same time.
' Download the zip file for all supporting files

' Some code cleanup by MadSciJr 9/2/2025

'$ExeIcon:'./\data\favicon.ico'

$Resize:Smooth
_Title "Tank Battle"

DefInt A-Z

dw = _DesktopWidth
dh = _DesktopHeight
If dw < 1024 Or dh < 768 Then
    Cls
    Print "A minimum Screen Resolution of 1024 x 768 is required to play"
    End
End If

' DISABLED FULLSCREEN BY DEFAULT. MAYBE AT STARTUP PROMPT THE USER "FULLSCREEN? (Y/N)"
If dw = 1024 And dh = 768 Then
    '_FullScreen
End If

Const wh& = _RGB32(255, 255, 255)
Const bl& = _RGB32(0, 0, 0)
Const bor& = _RGB32(155, 100, 255)
Const t1& = _RGB32(255, 255, 0)
Const t2& = _RGB32(0, 255, 0)
Const mi& = _RGB32(255, 0, 0)
Const bro& = _RGB32(133, 72, 11)

fir& = _SndOpen("data\gun.wav")
ex& = _SndOpen("data\explosion.wav")
tm1& = _SndOpen("data\tm1.wav")
tm2& = _SndOpen("data\tm2.wav")
bu& = _LoadImage("data\bush.png", 32)
br& = _LoadImage("data\brick.png", 32)
bru& = _LoadImage("data\bricku.png", 32)

pls& = _NewImage(1024, 768, 32)
_Dest pls&
Cls

Line (15, 15)-(1009, 753), bor&, B
Paint (3, 3), bor&, bor&
Line (59, 59)-(965, 709), bro&, B
Line (69, 69)-(954, 698), bro&, B
Paint (61, 61), bro&, bro&
Line (20, 99)-(1004, 669), bl&, BF
Line (99, 20)-(925, 748), bl&, BF
Line (206, 192)-(306, 242), bro&, BF
Line (216, 192)-(296, 232), bl&, BF
Line (718, 192)-(818, 242), bro&, BF
Line (728, 192)-(808, 232), bl&, BF
Line (206, 526)-(306, 576), bro&, BF
Line (216, 536)-(296, 576), bl&, BF
Line (718, 526)-(818, 576), bro&, BF
Line (728, 536)-(808, 576), bl&, BF
_PutImage (412, 59), br&
_PutImage (412, 660), br&
_PutImage (59, 284), bru&
_PutImage (916, 284), bru&
_PutImage (413, 326), bu&

' =============================================================================
Start:

a2 = -1
b2 = 0
x2 = 1
y2 = 0
f1 = 0
f2 = 0
f3 = 0
f4 = 0
x = 100
y = 100
a = 924
b = 668
fx1 = 0
fy1 = 0
fa1 = 0
fb1 = 0

Screen _NewImage(1024, 768, 32)
_ScreenMove dw * .5 - 512, dh * .5 - 384

If dio = 0 Then
    GoSub GameStart
End If

Do
    _Limit 60
    _PutImage , pls&

    d = 12 - (((Abs(x2) + Abs(y2)) - 1) * 4)
    Circle (x, y), 6, t1&
    Paint (x, y), t1&, t1&
    Circle (x, y), 3, bl&
    Line (x, y)-(x + x2 * d, y + y2 * d), mi&

    d = 12 - (((Abs(a2) + Abs(b2)) - 1) * 4)
    Circle (a, b), 6, t2&
    Paint (a, b), t2&, t2&
    Circle (a, b), 3, bl&
    Line (a, b)-(a + a2 * d, b + b2 * d), mi&

    x1 = 0
    y1 = 0
    a1 = 0
    b1 = 0

    If f1 = 1 Then
        Circle (fx, fy), 2, mi&
        Circle (fx + fx1, fy + fy1), 2, mi&
        Circle (fx + fx1 * 2, fy + fy1 * 2), 2, mi&
        fx = fx + fx1 * 3
        fy = fy + fy1 * 3
    End If

    If f2 = 1 Then
        Circle (fa, fb), 2, mi&
        Circle (fa + fa1, fb + fb1), 2, mi&
        Circle (fa + fa1 * 2, fb + fb1 * 2), 2, mi&
        fa = fa + fa1 * 3
        fb = fb + fb1 * 3
    End If

    If f3 = 1 Then
        Circle (fc, fd), 2, mi&
        Circle (fc + fc1, fd + fd1), 2, mi&
        Circle (fc + fc1 * 2, fd + fd1 * 2), 2, mi&
        fc = fc + fc1 * 3
        fd = fd + fd1 * 3
    End If

    If f4 = 1 Then
        Circle (fe, ff), 2, mi&
        Circle (fe + fe1, ff + ff1), 2, mi&
        Circle (fe + fe1 * 2, ff + ff1 * 2), 2, mi&
        fe = fe + fe1 * 3
        ff = ff + ff1 * 3
    End If

    If _KeyDown(100) Then
        x1 = 1
    ElseIf _KeyDown(97) Then
        x1 = -1
    End If

    If _KeyDown(115) Then
        y1 = 1
    ElseIf _KeyDown(119) Then
        y1 = -1
    End If

    If _KeyDown(19200) Then
        a1 = -1
    ElseIf _KeyDown(19712) Then
        a1 = 1
    End If

    If _KeyDown(18432) Then
        b1 = -1
    ElseIf _KeyDown(20480) Then
        b1 = 1
    End If

    If x1 <> 0 Or y1 <> 0 Then
        x2 = x1
        y2 = y1
    End If

    If a1 <> 0 Or b1 <> 0 Then
        a2 = a1
        b2 = b1
    End If

    If _KeyDown(32) Then
        GoSub fire1
    Else
        ss1 = 0
    End If

    If _KeyDown(100305) Then
        GoSub fire2
    Else
        ss2 = 0
    End If

    If Point(x + x1 * 13, y + y1 * 13) <> bl& Then
        x1 = 0
        y1 = 0
    End If

    If Point(a + a1 * 13, b + b1 * 13) <> bl& Then
        a1 = 0
        b1 = 0
    End If

    x = x + x1
    y = y + y1
    a = a + a1
    b = b + b1

    If x1 <> 0 Or y1 <> 0 Then
        _SndLoop tm1&
    Else
        _SndStop tm1&
    End If

    If a1 <> 0 Or b1 <> 0 Then
        _SndLoop tm2&
    Else
        _SndStop tm2&
    End If


    If f1 = 1 And Point(fx + fx1 * 2, fy + fy1 * 2) = t2& Then
        s1 = s1 + 1
        f1 = 0
        thit = 2
        GoTo tahit
    End If

    If f2 = 1 And Point(fa + fa1 * 2, fb + fb1 * 2) = t1& Then
        s2 = s2 + 1
        f2 = 0
        thit = 1
        GoTo tahit
    End If

    If f3 = 1 And Point(fc + fc1 * 2, fd + fd1 * 2) = t2& Then
        s1 = s1 + 1
        f3 = 0
        thit = 2
        GoTo tahit
    End If

    If f4 = 1 And Point(fe + fe1 * 2, ff + ff1 * 2) = t1& Then
        s2 = s2 + 1
        f4 = 0
        thit = 1
        GoTo tahit
    End If



    If f1 = 1 And Point(fx + fx1 * 3, fy + fy1 * 3) = bro& Then
        p1 = 1
        Reflect fx, fy, fx1, fy1
    Else
        p1 = 0
    End If

    If f2 = 1 And Point(fa + fa1 * 3, fb + fb1 * 3) = bro& Then
        p2 = 1
        Reflect fa, fb, fa1, fb1
    Else
        p2 = 0
    End If

    If f3 = 1 And Point(fc + fc1 * 3, fd + fd1 * 3) = bro& Then
        p3 = 1
        Reflect fc, fd, fc1, fd1
    Else
        p3 = 0
    End If

    If f4 = 1 And Point(fe + fe1 * 3, ff + ff1 * 3) = bro& Then
        p4 = 1
        Reflect fe, ff, fe1, ff1
    Else
        p4 = 0
    End If


    If f1 = 1 And Point(fx + fx1 * 2, fy + fy1 * 2) <> bl& Then
        f1 = 0
    End If

    If f2 = 1 And Point(fa + fa1 * 2, fb + fb1 * 2) <> bl& Then
        f2 = 0
    End If

    If f3 = 1 And Point(fc + fc1 * 2, fd + fd1 * 2) <> bl& Then
        f3 = 0
    End If

    If f4 = 1 And Point(fe + fe1 * 2, ff + ff1 * 2) <> bl& Then
        f4 = 0
    End If


    Color bl&, bor&
    Locate 1, 54
    Print Using "Yellow ## - Green ##"; s1; s2;
    Color bl&, bl&

    _Display
Loop Until _KeyDown(27)
GoTo Gameover

' =============================================================================
tahit:

_SndStop tm1&
_SndStop tm2&
Color bl&, bor&
Locate 1, 54
Print Using "Yellow ## - Green ##"; s1; s2;
Color bl&, bl&
If thit = 2 Then
    x = a
    y = b
End If

_SndPlay ex&
For a = 1 To 3
    For b = 1 To 17
        _Limit 20
        Circle (x, y), b, wh&
        Circle (x, y), b - 1, bl&
        _Display
    Next b
Next a

If s1 = 10 Or s2 = 10 Then
    GoTo Gameover
Else
    GoTo Start
End If

' =============================================================================
Gameover:

_SndStop tm1&
_SndStop tm2&

Do While _KeyDown(27)
    _Limit 60
Loop

_AutoDisplay

Line (302, 274)-(722, 494), bor&, BF
Line (312, 284)-(712, 484), t2&, BF

Color bl&, t2&
Locate 23, 41
Print "Thanks for playing Tank Battle  By David Coterel"

Locate 25, 41
If s1 > s2 Then
    Print "            Player 1 is the Winner"
End If
If s2 > s1 Then
    Print "            Player 2 Wins the game"
End If
If s2 = s1 Then
    Print "        Player 1  Tie Game  Player 2"
End If

Locate 27, 41
Print "                Press ESC to end"

Do
    _Limit 60
Loop Until _KeyDown(27)

_FreeImage pls&
System

' =============================================================================
GameStart:

_PutImage , pls&
dio = 1
loc1 = 40
step1 = 1

Circle (x, y), 6, t1&
Paint (x, y), t1&, t1&
Circle (x, y), 3, bl&
Line (x, y)-(x + 12, y), mi&
Circle (a, b), 6, t2&
Paint (a, b), t2&, t2&
Circle (a, b), 3, bl&
Line (a, b)-(a - 12, b), mi&
Line (302, 274)-(722, 494), bor&, BF
Line (312, 284)-(712, 484), t2&, BF

Color bl&, t2&
Locate 20, 41: Print "Thanks for playing Tank Battle  By David Coterel"

Locate 25, 41
Locate 22, 41: Print " Player 1 is the yellow tank and uses a,s,d & w"
Locate 23, 41: Print "            to move, space to fire"
Locate 25, 41: Print " Player 2 is the green tank and uses the cursor"
Locate 26, 41: Print "  keys to move,  the right cntrl key to fire"
Locate 28, 41: Print "      First player to reach  10 kills wins"

Do
    _Limit 10
    Locate 30, loc1
    Print " Press Enter to Start ";
    Sound 150, .1
    loc1 = loc1 + step1
    If loc1 = 68 Then
        step1 = -1
    ElseIf loc1 = 40 Then
        step1 = 1
    End If
    _Display
Loop Until _KeyDown(13)

Return

' =============================================================================
fire1:

If f1 = 0 And (x2 <> 0 Or y2 <> 0) And Point(x + x2 * 18, y + y2 * 18) = bl& Then
    f1 = 1
    fx1 = x2
    fy1 = y2
    fx = x + fx1 * 13
    fy = y + fy1 * 13
    _SndPlay fir&
    ss1 = 1
End If

If ss1 = 0 And f1 = 1 And f3 = 0 And (x2 <> 0 Or y2 <> 0) And Point(x + x2 * 18, y + y2 * 18) = bl& Then
    f3 = 1
    fc1 = x2
    fd1 = y2
    fc = x + fc1 * 13
    fd = y + fd1 * 13
    _SndPlay fir&
End If

Return

' =============================================================================
fire2:

If f2 = 0 And (a2 <> 0 Or b2 <> 0) And Point(a + a2 * 18, b + b2 * 18) = bl& Then
    f2 = 1
    fa1 = a2
    fb1 = b2
    fa = a + fa1 * 14
    fb = b + fb1 * 14
    _SndPlay fir&
    ss2 = 1
End If

If ss2 = 0 And f2 = 1 And f4 = 0 And (a2 <> 0 Or b2 <> 0) And Point(a + a2 * 18, b + b2 * 18) = bl& Then
    f4 = 1
    fe1 = a2
    ff1 = b2
    fe = a + fe1 * 13
    ff = b + ff1 * 13
    _SndPlay fir&
End If

Return

' =============================================================================
Sub Reflect (a, b, e, f)
    If Point(a, b + 3) = bro& Then
        f = f * -1
    End If
    If Point(a, b - 3) = bro& Then
        f = f * -1
    End If
    If Point(a + 3, b) = bro& Then
        e = e * -1
    End If
    If Point(a - 3, b) = bro& Then
        e = e * -1
    End If
End Sub ' Reflect
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Mouse Tank SierraKen 31 4,522 01-30-2025, 08:11 PM
Last Post: SierraKen

Forum Jump:


Users browsing this thread: 1 Guest(s)