DEFINT A-Z: CONST XDIM = 320&, YDIM = 200&, BPL = 80, PI = 3.141592653589793# SCREEN 13: RANDOMIZE TIMER hval = 128 'Square aspect is actually XDIM*.5, but I think 128 looks nicer 'Code originally from LABDEMO.BAS 'Modified on 10/14/1999 by Ken Silverman for rendering cleanliness OUT &H3C8, 0 'Make interesting palette FOR x = 0 TO 63: OUT &H3C9, x: OUT &H3C9, 0: OUT &H3C9, 0: NEXT x FOR x = 0 TO 63: OUT &H3C9, 0: OUT &H3C9, x: OUT &H3C9, 0: NEXT x FOR x = 0 TO 63: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, x: NEXT x FOR x = 0 TO 63: OUT &H3C9, x: OUT &H3C9, x: OUT &H3C9, x: NEXT x OUT &H3C4, &H4: OUT &H3C5, &H6 'Set Mode X (unchained mode) OUT &H3D4, &H14: OUT &H3D5, &H0 OUT &H3D4, &H17: OUT &H3D5, &HE3 DIM pic(64 * 64 * 4), board(64, 64) FOR y = 0 TO 63 'Generate interesting bitmaps (without loading a file) FOR x = 0 TO 63 pic(x * 64 + y + 0) = (x + y) \ 2 + 0 pic(x * 64 + y + 4096) = ((x XOR y) * .875 + RND * 64 * .125) * .5 + 64 pic(x * 64 + y + 8192) = ((x OR y) * .875 + RND * 64 * .125) * .5 + 128 pic(x * 64 + y + 12288) = (x * x + y * y) \ 128 + 192 NEXT x NEXT y FOR z = 0 TO 63 'Generate random board (0 is invisible, 1-4 are walls) board(z, 0) = INT(4 * RND) + 1 board(0, z) = INT(4 * RND) + 1 board(z, 63) = INT(4 * RND) + 1 board(63, z) = INT(4 * RND) + 1 NEXT z FOR z = 0 TO 1023 board(INT(62 * RND) + 1, INT(62 * RND) + 1) = INT(4 * RND) + 1 NEXT z 'The length of the side of a cube is 1 'Since the 2D board map is 64*64, posx# and posy# range from 0-64 'posz# ranges from -.5 to .5 (0 is the middle) DO 'Make sure starting position isn't inside a cube x = INT(62 * RND) + 2 y = INT(62 * RND) + 2 LOOP WHILE board(x, y) <> 0 posx# = x + .5#: posy# = y + .5#: posz# = 0#: ang = PI * 2 * RND pagoffs = 0: OUT &H3C4, &H2: OUT &H3D4, &HC DO cosang# = COS(ang#) sinang# = SIN(ang#) vxinc# = sinang# * -2# / XDIM: vx# = cosang# + sinang# + vxinc# * .5# vyinc# = cosang# * 2# / XDIM: vy# = sinang# - cosang# + vyinc# * .5# FOR sx = 0 TO XDIM - 1 'Raytrace in 2D to see what block is hit, and where it gets hit xscan = INT(posx#): xdir = SGN(vx#): incx# = ABS(vx#) yscan = INT(posy#): ydir = SGN(vy#): incy# = ABS(vy#) xtemp# = posx# - xscan: IF xdir > 0 THEN xtemp# = 1 - xtemp# ytemp# = posy# - yscan: IF ydir > 0 THEN ytemp# = 1 - ytemp# d# = xtemp# * incy# - ytemp# * incx# DO IF d# < 0 THEN xscan = xscan + xdir IF board(xscan, yscan) THEN hx# = xscan: IF xdir < 0 THEN hx# = hx# + 1 hy# = posy# + vy# * (hx# - posx#) / vx# bx = INT((hy# - INT(hy#)) * 64) IF xdir < 0 THEN bx = 63 - bx EXIT DO END IF d# = d# + incy# ELSE yscan = yscan + ydir IF board(xscan, yscan) THEN hy# = yscan: IF ydir < 0 THEN hy# = hy# + 1 hx# = posx# + vx# * (hy# - posy#) / vy# bx = INT((hx# - INT(hx#)) * 64) IF ydir > 0 THEN bx = 63 - bx EXIT DO END IF d# = d# - incx# END IF LOOP dist# = cosang# * (hx# - posx#) + sinang# * (hy# - posy#) 'Find the ceiling & floor borders, and the texture mapping equation IF dist# > 1# / 64# THEN sy1 = INT(YDIM \ 2 + (-posz# - .5) * hval / dist#) sy2 = INT(YDIM \ 2 + (-posz# + .5) * hval / dist#) IF sy1 < 0 THEN sy1 = 0 IF sy2 > YDIM THEN sy2 = YDIM byi& = INT(dist# * 65536# * 64# / hval) by& = (sy1 + 1 - YDIM \ 2) * byi& + (posz# + .5#) * 65536# * 64# - 1 by& = by& + ((board(xscan, yscan) - 1) * 4096& + bx * 64&) * 65536 ELSE sy1 = YDIM \ 2: sy2 = sy1 END IF 'Draw vertical line at column sx: OUT &H3C5, 2 ^ (sx AND 3): DEF SEG = &HA000 + pagoffs * 16 p = sx \ 4: pe = sy1 * BPL DO WHILE p < pe: POKE p, 176: p = p + BPL: LOOP 'Ceilings pe = sy2 * BPL 'Walls DO WHILE p < pe POKE p, pic(by& \ 65536): p = p + BPL: by& = by& + byi& LOOP pe = YDIM * BPL DO WHILE p < pe: POKE p, 80: p = p + BPL: LOOP 'Floors vx# = vx# + vxinc# vy# = vy# + vyinc# NEXT sx 'Flip page OUT &H3D5, pagoffs: pagoffs = (pagoffs + 64) AND 255 'Keyboard control code DO z$ = INKEY$ IF z$ = CHR$(0) + CHR$(75) THEN ang# = ang# - .1# IF z$ = CHR$(0) + CHR$(77) THEN ang# = ang# + .1# IF z$ = "<" OR z$ = "," THEN posx# = posx# + sinang# * .25# posy# = posy# - cosang# * .25# END IF IF z$ = ">" OR z$ = "." THEN posx# = posx# - sinang# * .25# posy# = posy# + cosang# * .25# END IF IF z$ = CHR$(0) + CHR$(72) THEN posx# = posx# + cosang# * .25# posy# = posy# + sinang# * .25# END IF IF z$ = CHR$(0) + CHR$(80) THEN posx# = posx# - cosang# * .25# posy# = posy# - sinang# * .25# END IF IF UCASE$(z$) = "A" THEN posz# = posz# - .05# IF UCASE$(z$) = "Z" THEN posz# = posz# + .05# IF z$ = CHR$(27) THEN SCREEN 0: END LOOP WHILE z$ <> "" 'Mouse control code (enable this, unless you're stuck using QBasic!) regs%(0) = 5: CALL int86old(&H33, regs%(), regs%()): bstatus% = regs%(0) regs%(0) = 11: CALL int86old(&H33, regs%(), regs%()) IF (bstatus% AND 2) = 0 THEN ang# = ang# + regs%(2) * .01# ELSE posx# = posx# + sinang# * regs%(2) * -.02# posy# = posy# - cosang# * regs%(2) * -.02# END IF IF (bstatus% AND 1) = 0 THEN posx# = posx# + cosang# * regs%(3) * -.02# posy# = posy# + sinang# * regs%(3) * -.02# ELSE posz# = posz# + regs%(3) * .02# END IF 'Don't let your view escape the board IF posx# < 1.25# THEN posx# = 1.25# IF posy# < 1.25# THEN posy# = 1.25# IF posx# > 62.75# THEN posx# = 62.75# IF posy# > 62.75# THEN posy# = 62.75# IF posz# < -.5# THEN posz# = -.5# IF posz# > .5# THEN posz# = .5# LOOP