Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 11:17 01 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Colour MM Ray trace example

Author Message
joeb11666
Newbie

Joined: 30/07/2019
Location: United States
Posts: 1
Posted: 03:51am 07 Aug 2019
Copy link to clipboard 
Print this post

Hi all, 1st post here.

I just got my Colour Maximite and been playing around with some examples from other BASIC. Love this thing.
1st one here, Ray trace example original code on Microsoft Small Basic. Pretty amazing this thing can run with a few modifications. Small Basic is free if you want to see the diffences in execution and code difference.
The code is heavily commented and could use some cleanup. It should works in all modes but is fastest in mode 4.


' Adapted code from Microsoft Small Basic Example
' smallbasic.com
' smallbasic.com/program/?LZW978
'
' original upload code:- ?BRS931
' new uploda code LZW978
' Raycaster maze
' uses a simple ray casting technique (see lodev.org for tutorial) to draw
' vertical stripes down the graphics window.
' Each stripe is drawn to a size dependent upon the distance of the wall from the viewer.
' "Rays" are cast across a viewing plane in front of the viewer, from left to right.
' the height of the wall stripe depends on the distance of the wall from the viewer.

InitialSetUp:
' set up screen width and height
' values also used to determine the width and height of the "viewing plane"
' "size" is used to determine the width of each vertical line drawn.
' a smaller value makes the walls sharper, but draws slower (there are more lines)
' a larger value makes the walls blockier, but draws more quickly
'w = 511
'h = 384
Mode 4
w = MM.HRes
h = MM.VRes
size = 8
'intensity of light source. The lower the number the further you can see.
intensity = 50
'
' set up the player's start position and direction
' these are the x/y co-ordinates of the world map
' nb absolute values place the player at grid intersections!!
posX = 5.5
posY = 10.5
dirX = 1
dirY = 1
planeX = 0
'
' plane y is the size of the viewing plane in degrees
' (altering this gives different perspective views)
planeY = 0.66
completed = 1
'
' movespeed is how far forward you move each step.
' bigger values create bigger steps, lower values mean smaller (smoother) steps
' rotspeed is how much you rotate left/right when you turn
' a value of 1/3 of rotspeed seems about right
moveSpeed = 0.2
rotSpeed = 0.07

' call the setupmap subroutine to draw the initial map view
setupmap()
main()

Do
Movement

Loop Until KeyDown=27


Sub Movement
keypress = KeyDown
If keypress > 0 Then
'ensures that will not try to draw, when previous frame is still drawing
moveX = dirX * movespeed
moveY = dirY * movespeed
' checks that nothing is in front then moves forward
If keypress = 128 Then
If worldMap(Int(posX + moveX),Int(posy)) = 0 Then
posX = posX + moveX
EndIf
If worldMap(Int(posx),Int(posY + moveY)) = 0 Then
posY = posY + moveY
EndIf
EndIf
' checks that nothing is in behind then moves backwards
If keypress = 129 Then
If worldMap(Int(posX - dirX * moveX,Int(posy)) = 0 Then
posX = posX - moveX
EndIf
If worldMap(Int(posx),Int(posY - moveY)) = 0 Then
posY = posY - moveY
EndIf
EndIf
' rotate the view anticlockwise if turning left
If keypress = 130 Then
oldDirx = dirX
CosrotspeedL = Cos(-1 * rotspeed)
SinrotspeedL = Sin(-1 * rotspeed)
dirX = dirX * CosrotspeedL - dirY * SinrotspeedL
dirY = oldDirX * SinrotspeedL + dirY * CosrotspeedL
oldPlanex = planeX
planeX = planeX * CosrotspeedL - planeY * SinrotspeedL
planeY = oldPlaneX * SinrotspeedL + planeY * CosrotspeedL
'
'
EndIf
' rotate the view clockwise if turning right
If keypress = 131 Then
oldDirx = dirX
CosrotspeedR = Cos(rotspeed)
SinrotspeedR = Sin(rotspeed)
dirX = dirX * CosrotspeedR - dirY * SinrotspeedR
dirY = oldDirX * SinrotspeedR + dirY * CosrotspeedR
oldPlaneX = planeX
planeX = planeX * CosrotspeedR - planeY * SinrotspeedR
planeY = oldPlaneX * SinrotspeedR + planeY * CosrotspeedR
'
'
EndIf
'call main subroutine to draw the new frame/view
main()
EndIf
End Sub


Sub main
completed = 0
For x = 0 To w / size ' calculate ray position and direction
cameraX = (2*x)/(w/size) - 1 ' x-coordinate in camera space
rayPosX = posX
rayPosY = posY
rayDirX = dirX + planeX * cameraX
rayDirY = dirY + planeY * cameraX
'
'which box of the map we're in
mapX = Int(rayPosX)
mapY = Int(rayPosY)

' length of ray from current position to next x or y-side
sideDistX = 0
sideDistY = 0

' length of ray from one x or y-side to next x or y-side
deltaDistX = Sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
deltaDistY = Sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
perpWallDist = 0

'what direction to step in x or y-direction (either +1 or -1)
stepX = 0
stepY = 0
hit = 0 ' was there a wall hit?
side = 0 ' was a NS or a EW wall hit?

' calculate step and initial sideDist
If rayDirX < 0 Then
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0 Then
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf

' perform DDA
' trace a "ray" until it hits a wall, and determine if it's an "X" (horizontal) or "Y" (vertical) wall
Do
' jump to next map square, OR in x-direction, OR in y-direction
If sideDistX < sideDistY Then
sideDistX = sideDistX + deltaDistX
mapX = mapx + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapy + stepY
side = 1
EndIf

' Check if ray has hit a wall
If worldMap(mapX,mapY) > 0 Then
hit = 1
EndIf
Loop While hit=0

' Calculate distance projected on camera direction.
If side = 0 Then
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
' Calculate height of line to draw on screen
lineHeight = Int(Abs(h / perpWallDist))+1

'if height if line to be drawn is > than height of graphics window then limit height of line
If lineHeight > h Then
lineHeight = h
EndIf
'
' calculate lowest and highest pixel to fill in current stripe
drawStart = (lineHeight * -1) / 2 + h / 2
If drawStart < 0 Then
drawStart = 0
EndIf
drawEnd = lineHeight / 2 + h / 2
If drawEnd >= h Then
drawEnd = h - 1
EndIf


'draw the pixels of the stripe as a vertical line
'
' if the colour intensity is > 0 then draw the line,
Line (x*size,drawstart)-((x*size)+size,drawend),worldmap(mapx,mapy),bf
Line (x*size,0)-((x*size)+size,drawstart),0,bf
Line (x*size,drawend)-((x*size)+size,h),0,bf
Next
completed = 1
End Sub


Sub setupmap
Dim worldmap(22,22)
mapwidth = 21
mapheight = 21
'define the map in the mapline array as strings
Data 1,5,5,5,5,5,5,1,1,1,1,1,1,1,1,5,5,5,5,5,5
Data 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5
Data 6,0,0,0,0,0,0,0,2,0,0,0,0,0,5,0,0,0,0,5,1
Data 6,0,0,0,0,0,0,0,0,0,0,0,3,0,5,0,0,0,0,5,1
Data 6,0,0,0,0,0,0,0,2,6,0,0,3,0,5,0,2,2,2,0,1
Data 6,0,4,0,2,0,0,0,6,0,0,0,0,0,5,0,0,0,0,0,1
Data 6,0,4,0,3,1,0,0,6,0,1,6,6,0,4,4,4,4,4,4,1
Data 6,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,1
Data 6,0,0,2,3,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,3
Data 1,0,0,0,0,2,2,0,0,0,2,2,0,0,0,0,0,0,0,0,3
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3
Data 1,0,0,0,0,2,2,0,0,0,2,2,0,0,0,3,3,3,0,3,3
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,3,1
Data 1,0,3,3,3,3,3,1,1,1,1,1,1,1,1,0,1,1,0,1,1
Data 1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,2
Data 1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2
Data 1,0,0,2,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,2
Data 1,0,0,0,0,0,0,0,0,1,1,6,5,4,3,2,1,1,3,0,2
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3
Data 1,1,1,1,1,1,1,1,1,1,1,6,5,4,3,2,1,1,2,2,2

'
' define some parameters that state how big the map is
mapsizex = mapwidth
mapsizey = mapheight
'
'try to read this in and convert it into a two dimensional array
For yloop = 1 To mapheight
For xloop = 1 To mapwidth
Read worldmap(xloop,yloop)
Next
Next
End Sub
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 05:05am 07 Aug 2019
Copy link to clipboard 
Print this post

Hi Joe,
It is good to see the Colour Maximite getting so much attention again.
I might have to plug a monitor into mine...

Thanks for sharing.

Jim
VK7JH
MMedit
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 06:46am 07 Aug 2019
Copy link to clipboard 
Print this post

I had a cable handy so decided to fire up the CMM on a monitor.

There is a closing bracket missing on one line:
If worldMap(Int(posX - dirX * moveX,Int(posy)) = 0 Then


should be
If worldMap(Int(posX - dirX * moveX),Int(posy)) = 0 Then


The other change I made was replacing both KEYDOWN functions with ASC(INKEY$) so I could use the USB instead of a PS2 keyboard. KEYDOWN doesn't work on the USB console.
ASC(INKEY$) is not as responsive as KEYDOWN but it saved me going to the shed for a keyboard.

Jim
VK7JH
MMedit
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025