![]() |
Forum Index : Microcontroller and PC projects : Colour MM Ray trace example
Author | Message | ||||
joeb11666 Newbie ![]() Joined: 30/07/2019 Location: United StatesPosts: 1 |
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: AustraliaPosts: 6283 |
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: AustraliaPosts: 6283 |
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 |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |