Made in about an hour, in QB64

'(c) 2021, @_sorceress

' wasd + mouse to move.

' mouse control doesn't seem to work on linux. this is a bug in QB64.

SCREEN _NEWIMAGE(640, 480, 256)

_TITLE "Basic Raycatter"

'generate random test map

RANDOMIZE TIMER

DIM g(15, 15)

FOR x = 0 TO 15: FOR y = 0 TO 15

IF RND < .3 THEN gv = 1 ELSE gv = 0

IF x MOD 15 = 0 OR y MOD 15 = 0 THEN gv = 1

IF ABS(x - 5) + ABS(y - 5) < 3 THEN gv = 0

g(x, y) = gv

NEXT: NEXT

'player behaviour

px = 5: py = 5: pa = 0: pelev = 0

turnspeed = 5: walkspeed = 2.5

FPS = 30: dt = 1 / FPS

DO

'### input

fv = 0: sv = 0

IF ScanKey%(17) THEN fv = fv + walkspeed

IF ScanKey%(31) THEN fv = fv - walkspeed

IF ScanKey%(30) THEN sv = sv + walkspeed

IF ScanKey%(32) THEN sv = sv - walkspeed

WHILE _MOUSEINPUT

pa = pa + turnspeed * (_MOUSEMOVEMENTX / 1000)

pelev = pelev + turnspeed * (_MOUSEMOVEMENTY / 1000)

IF ABS(pelev) > 1 THEN pelev = SGN(pelev)

WEND

'### physics

pacos = COS(pa): pasin = SIN(pa)

xvt = fv * pacos + sv * pasin

yvt = fv * pasin - sv * pacos

xv = xv + (xvt - xv) * 4 * dt

yv = yv + (yvt - yv) * 4 * dt

px1 = px + xv * dt: py1 = py + yv * dt

x1 = px1: y1 = py: GOSUB cbox: IF ok = 0 THEN px = px1

x1 = px: y1 = py1: GOSUB cbox: IF ok = 0 THEN py = py1

'### raycatter

h0 = 240 - 240 * pelev

LINE (0, 0)-(639, h0), 11, BF

LINE (0, h0)-(639, 479), 8, BF

x = 320 * (1 - TAN(pa - 3.141 / 2)): y = h0 - 320

IF pasin > 0 THEN CIRCLE (x, y), 32, 14: PAINT (x, y + 30), 14, 14

FOR sx = 0 TO 639: e = sx / 320 - 1 'x-fov

x = px: y = py 'ray origin

rx = pacos - e * pasin: ry = pasin + e * pacos 'ray vector

d = 0: dd = .01 'terribly inefficient way of catting rays

WHILE g(INT(x), INT(y)) = 0

x = x + rx * dd: y = y + ry * dd: d = d + dd: dd = dd * 1.005

WEND

h = 100 / d 'draw column

LINE (sx, h0 - h)-(sx, h0 + h), (3 * INT(x) + INT(y)) MOD 7 + 1

NEXT

'### draw minimap

m = 8

FOR x = 0 TO 15: FOR y = 0 TO 15

LINE (x * m, y * m)-(x * m + m, y * m + m), g(x, y) * 8, BF

NEXT: NEXT

x = m * px: y = m * py: ux = m * pacos: uy = m * pasin

LINE (x - ux, y - uy)-(x + ux, y + uy), 3: LINE -(x - uy, y + ux), 3: LINE -(x + uy, y - ux), 3: LINE -(x + ux, y + uy), 3

'### text feedback

LOCATE 1, 20: PRINT px; py; pa; pelev

_DISPLAY: _LIMIT FPS

LOOP

'################################################################################

'collision box test. a must be smaller than 0.5 to work properly.

cbox:

a = .2

ok = g(INT(x1 - a), INT(y1 - a)) + g(INT(x1 + a), INT(y1 - a)) + g(INT(x1 - a), INT(y1 + a)) + g(INT(x1 + a), INT(y1 + a))

RETURN

'is key down?

FUNCTION ScanKey% (scancode%)

STATIC Ready%, keyflags%()

IF NOT Ready% THEN REDIM keyflags%(0 TO 127): Ready% = -1

i% = INP(&H60)

IF (i% AND 128) THEN keyflags%(i% XOR 128) = 0

IF (i% AND 128) = 0 THEN keyflags%(i%) = -1

K$ = INKEY$

ScanKey% = keyflags%(scancode%)

END FUNCTION

You made this in an hour? I can hardly *type* that fast :-D Very impressive.

QBasic, now that's a name I haven't heard in a long time. Neat that there're people out there still updating some kind of version of it!

You probably know this already (and also the least important thing ever), but; sometimes an inwards corner is missing a small sliver.

For anyone running Linux, you can put in some keyboard controls for view-direction by adding this to the source, between the other key handling (Q, E, R, F keys are used … the numbers seem to be the order in which they are on the keyboard, so maybe it's other keys in other layouts):

```
IF ScanKey%(16) THEN pa = pa - turnspeed / 50
IF ScanKey%(18) THEN pa = pa + turnspeed / 50
IF ScanKey%(19) THEN pelev = pelev - turnspeed / 100
IF ScanKey%(33) THEN pelev = pelev + turnspeed / 100
IF ABS(pelev) > 1 THEN pelev = SGN(pelev)
```

Otherwise it would seem I'm a bit too tired right now to mess with source code :-D

P.S. I'm with toasty, where's the cats?

Login to comment

sorceress

The code

isthe manual. So cool B-)This is really cool, @sorceress: not just that you built a raycaster in basic, and in so few lines, but in under an hour. Wow! I expect this would fit right in in a demoscene event.

The mipmap is a nice touch too. What more could we ask for? Well, perhaps a cat, given the name :P