又是一个端午节,真的老了。坐在计算机边,打开VirtualBox,启动Windows 3.2, 再玩一把坦克对战游戏。
这是1996年端午节前后写的程序。当时备战高考,被题海战术弄得身心俱疲,模拟考试距离二本还差了十几分,终于病倒了。发烧烧了一个礼拜,硬撑着回到学校时,颇有些自暴自弃,躲到学校计算机房,写了这个东东。折腾了两天,老师把母亲叫来,母亲没有发火,而是带来了粽子,“端午节你发烧,给你留着呢,吃完了,好好学习”。回想着母亲把蜜枣一颗颗包进去的情景,实在自责,当时的心情依旧记忆犹新。
界面
程序是Qb45写的——当时学校里教学使用的就是386 SX 计算机+Qb45。先上代码,估计只能在DosBox或者虚拟机里运行了。
方向键:移动坦克
<> :转动炮塔
空格 :开火
坦克在靠近时,会自动扫射。注意在DOS里要把键盘的重复速率、重复等待设置为最低,这样连发比较容易操作。
己方是黄色,对方是蓝色。屏幕上下分别显示的是自己、对方的生命、弹药。生命越低,速度越慢。
代码
REM Main Function
DECLARE SUB gun ()
DECLARE SUB test ()
DECLARE SUB move ()
DECLARE SUB show ()
DIM SHARED ex AS SINGLE, ey AS SINGLE
DIM SHARED ax AS SINGLE, ay AS SINGLE
DIM SHARED towards AS SINGLE, eto AS SINGLE
DIM SHARED ppx(1 TO 500) AS SINGLE, ppy(1 TO 500) AS SINGLE, ppto(1 TO 500) AS SINGLE
DIM SHARED PURPOSEX AS SINGLE, PURPOSEY AS SINGLE
DIM SHARED ssddx(1 TO 50) AS SINGLE, ssddy(1 TO 50) AS SINGLE, ssddto(1 TO 50) AS SINGLE, efire AS SINGLE
DIM SHARED abb AS INTEGER, ebb AS INTEGER
REM bulletes
abb = 1500
ebb = 1500
DIM pleft AS STRING
DIM pright AS STRING
DIM pdown AS STRING
DIM pup AS STRING
DIM pfire AS STRING
DIM pexit AS STRING
DIM pturnleft AS STRING
DIM pturnright AS STRING
DIM SHARED fire AS SINGLE, ev AS SINGLE, av AS SINGLE
RANDOMIZE TIMER
ev = 4
av = 8
pleft = CHR$(0) + CHR$(75)
pright = CHR$(0) + CHR$(77)
pdown = CHR$(0) + CHR$(80)
pup = CHR$(0) + CHR$(72)
pfire = CHR$(32)
pexit = CHR$(27)
pturnleft = ","
pturnright = "."
ex = (RND(1) * 640) - 320
ey = (RND(1) * 480) - 240
eto = (RND(1) * 360)
ON ERROR GOTO er
ON TIMER(5) GOSUB effire
SCREEN 9, , 0, 1
WINDOW (-320, 240)-(320, -240)
CALL show
PCOPY 0, 1
TIMER ON
DO
CLS
CALL move
CALL show
CALL gun
CALL test
PCOPY 0, 1
a$ = INKEY$
SELECT CASE a$
CASE pturnleft
towards = towards + 5
IF towards >= 360 THEN
towards = 0
END IF
CASE pturnright
towards = towards - 5
IF towards <= 0 THEN
towards = 360
END IF
CASE pleft
ax = ax - av
IF ax <= -320 THEN
ax = -320
END IF
CASE pright
ax = ax + av
IF ax >= 320 THEN
ax = 320
END IF
CASE pdown
ay = ay - av
IF ay <= -240 THEN
ay = -240
END IF
CASE pup
ay = ay + av
IF ay >= 240 THEN
ay = 240
END IF
CASE pfire
IF (fire < 500) AND (abb > 0) THEN
fire = fire + 1
abb = abb - 1
ppx(fire) = ax
ppy(fire) = ay
ppto(fire) = towards + (RND(1) - .5)
END IF
FOR ff% = 200 TO 100 STEP -30
SOUND ff%, .1
NEXT ff%
CASE pexit
EXIT DO
CASE ELSE
END SELECT
IF towards > 360 THEN
towards = towards - 360
ELSEIF towards < 0 THEN
towards = towards + 360
END IF
LOOP
SCREEN 0, 1
END
er:
RESUME NEXT
effire:
COUNT = 0
WHILE (efire < 50) AND ebb > 0 AND COUNT < 5
COUNT = COUNT + 1
efire = efire + 1
ebb = ebb - 1
PURPOSEX = ax
PURPOSEY = ay
ssddx(efire) = ex
ssddy(efire) = ey
IF ex < ax THEN
ssddto(efire) = ATN((ay - ey) / (ax - ex))
ELSE
ssddto(efire) = 3.1415926# + ATN((ay - ey) / (ax - ex))
END IF
ssddto(efire) = ssddto(efire) + RND(1) * .1 - .05
WEND
FOR ff% = 200 TO 100 STEP -30
SOUND ff%, .1
NEXT ff%
RETURN
SUB gun
DIM sita1 AS SINGLE, sita2 AS SINGLE, r1 AS SINGLE, r2 AS SINGLE
IF ABS(ax - ex) <= av / 8 * 200 AND ABS(ay - ey) <= av / 8 * 200 THEN
ev = ev - .0025 * RND(1)
sita2 = RND(1) * 360
r2 = RND(1) * 10
CIRCLE (ex + r2 * COS(sita2), ey + r2 * SIN(sita2)), 1, 12
LINE (ex + r2 * COS(sita2), ey + r2 * SIN(sita2))-(ax, ay), 12, , &H71
LOCATE 2, 40
COLOR 12
PRINT "Gun!"
END IF
IF ABS(ax - ex) <= ev / 4 * 200 AND ABS(ay - ey) <= ev / 4 * 200 THEN
av = av - .005 * RND(1)
sita1 = RND(1) * 360
r1 = RND(1) * 10
CIRCLE (ax + r1 * COS(sita1), ay + r1 * SIN(sita1)), 1, 12
LINE (ax + r1 * COS(sita1), ay + r1 * SIN(sita1))-(ex, ey), 13, , &H71
LOCATE 23, 40
COLOR 14
PRINT "Gun!"
END IF
END SUB
SUB move
ex = ex + ev * COS(eto / 180 * 3.141593)
ey = ey + ev * SIN(eto / 180 * 3.141593)
IF ex <= -320 THEN
ex = -320
eto = (RND(1) * 360)
END IF
IF ex >= 320 THEN
ex = 320
eto = (RND(1) * 360)
END IF
IF ey <= -240 THEN
ey = -240
eto = (RND(1) * 360)
END IF
IF ey >= 240 THEN
ey = 240
eto = (RND(1) * 360)
END IF
IF fire > 0 THEN
FOR i = 1 TO fire
ppx(i) = ppx(i) + 8 * COS(ppto(i) / 180 * 3.141593)
ppy(i) = ppy(i) + 8 * SIN(ppto(i) / 180 * 3.141593)
IF (ppx(i) <= -320) OR (ppx(i) >= 320) OR (ppy(i) <= -240) OR (ppy(i) >= 240) THEN
FOR j = i TO fire - 1
ppx(j) = ppx(j + 1)
ppy(j) = ppy(j + 1)
ppto(j) = ppto(j + 1)
NEXT j
fire = fire - 1
END IF
NEXT i
END IF
IF efire > 0 THEN
FOR i = 1 TO efire
ssddx(i) = ssddx(i) + 5 * COS(ssddto(i))
ssddy(i) = ssddy(i) + 5 * SIN(ssddto(i))
IF (ssddx(i) <= -320) OR (ssddx(i) >= 320) OR (ssddy(i) <= -240) OR (ssddy(i) >= 240) THEN
FOR j = i TO efire - 1
ssddx(j) = ssddx(j + 1)
ssddy(j) = ssddy(j + 1)
ssddto(j) = ssddto(j + 1)
NEXT j
efire = efire - 1
END IF
NEXT i
END IF
END SUB
SUB show
IF fire > 0 THEN
FOR i = 1 TO fire
CIRCLE (ppx(i), ppy(i)), 2, 12
PAINT (ppx(i), ppy(i)), 12
CIRCLE (ppx(i), ppy(i)), 2, 4
NEXT i
COLOR 12
LOCATE 2, 60
PRINT "Fire..."
END IF
IF efire > 0 THEN
FOR i = 1 TO efire
CIRCLE (ssddx(i), ssddy(i)), 2, 15
PAINT (ssddx(i), ssddy(i)), 15
CIRCLE (ssddx(i), ssddy(i)), 3, 12
NEXT i
COLOR 13
LOCATE 23, 60
PRINT "Fire..."
END IF
IF ex < ax THEN
paoto = ATN((ay - ey) / (ax - ex))
ELSE
paoto = 3.1415926# + ATN((ay - ey) / (ax - ex))
END IF
LOCATE 2, 1
COLOR 7
PRINT "Yours Blood:"; FIX(av / 8 * 100 + .5); "%", "Bomb="; abb;
LOCATE 23, 1
PRINT "Enemy's Blood:"; FIX(ev / 4 * 100 + .5); "%", "Bomb="; ebb;
LINE (-320, 240)-(-320 + 640, 230), 4, BF
LINE (-320, 240)-(-320 + av * 640 / 8, 230), 2, BF
LINE (-320, -230)-(-320 + 640, -220), 4, BF
LINE (-320, -230)-(-320 + ev * 640 / 4, -220), 2, BF
LINE (ax - 10, ay - 10)-(ax + 10, ay + 10), 14, BF
s = towards / 180 * 3.1415926#
CIRCLE (ax, ay), 5, 12
PAINT (ax, ay), 12
LINE (ax - 2, ay - 2)-(ax + 20 * COS(s), ay + 20 * SIN(s)), 12
LINE (ax - 1, ay - 1)-(ax + 20 * COS(s), ay + 20 * SIN(s)), 12
LINE (ax, ay)-(ax + 20 * COS(s), ay + 20 * SIN(s)), 12
LINE (ax + 2, ay + 2)-(ax + 20 * COS(s), ay + 20 * SIN(s)), 12
LINE (ax + 1, ay + 1)-(ax + 20 * COS(s), ay + 20 * SIN(s)), 12
LINE (ex - 10, ey - 10)-(ex + 10, ey + 10), 9, BF
CIRCLE (ex, ey), 5, 11
PAINT (ex, ey), 11
LINE (ex - 2, ey - 2)-(ex + 20 * COS(paoto), ey + 20 * SIN(paoto)), 11
LINE (ex - 1, ey - 1)-(ex + 20 * COS(paoto), ey + 20 * SIN(paoto)), 11
LINE (ex, ey)-(ex + 20 * COS(paoto), ey + 20 * SIN(paoto)), 11
LINE (ex + 2, ey + 2)-(ex + 20 * COS(paoto), ey + 20 * SIN(paoto)), 11
LINE (ex + 1, ey + 1)-(ex + 20 * COS(paoto), ey + 20 * SIN(paoto)), 11
END SUB
SUB test
IF fire > 0 THEN
FOR gg = 1 TO fire
IF (ABS(ppx(gg) - ex) <= 10) AND (ABS(ppy(gg) - ey) <= 10) THEN
FOR i% = 1 TO 10
SITA = (RND(1) * 360)
R = (RND(1) * 30)
CIRCLE (ppx(gg) + R * COS(SITA), ppy(gg) + R * SIN(SITA)), 2, 12
NEXT i%
PCOPY 0, 1
ev = ev - RND(1) * .02 - .1
FOR j = gg TO fire - 1
ppx(j) = ppx(j + 1)
ppy(j) = ppy(j + 1)
ppto(j) = ppto(j + 1)
NEXT j
fire = fire - 1
FOR ff% = 400 TO 300 STEP -30
SOUND ff%, .1
NEXT ff%
END IF
NEXT gg
END IF
IF efire > 0 THEN
FOR gg = 1 TO efire
IF (ABS(ssddx(gg) - ax) <= 10) AND (ABS(ssddy(gg) - ay) <= 10) THEN
FOR i% = 1 TO 50
SITA = (RND(1) * 360)
R = (RND(1) * 30)
CIRCLE (ssddx(gg) + R * COS(SITA), ssddy(gg) + R * SIN(SITA)), 2, 12
NEXT i%
PCOPY 0, 1
av = av - RND(1) * .1 - .5
FOR j = gg TO efire - 1
ssddx(j) = ssddx(j + 1)
ssddy(j) = ssddy(j + 1)
ssddto(j) = ssddto(j + 1)
NEXT j
efire = efire - 1
FOR ff% = 400 TO 300 STEP -30
SOUND ff%, .1
NEXT ff%
END IF
NEXT gg
END IF
IF (ev < -.005) OR (av <= -.005) THEN
DO: LOOP WHILE INKEY$ = ""
SCREEN 0
END
END IF
END SUB
后记
二十多年过去了,早就不记得BASIC语言如何写程序。人生就是这样,白驹过隙,停也停不下来。每个人都有自己的路,能够坚持这么多年还在写代码的人,还有多少呢?