Hello, I tried to do this a little while ago. I think we both used same tutorial as a starting point.
I added distance shading and doom-style side stepping.
You need some 64x64 textures for this one. Keys 1-7 change the mode in demo. Read my comments for some speed-up.
Code: Select all
/*
************************************************************
**
** Created by: CodeBench 0.13 (16.02.2010)
**
** Project: Raycaster
**
** File:
**
** Date: 19-09-2010 19:09:22
**
************************************************************
*/
;
; Based on this tutorial: http://www.student.kuleuven.be/~m0216922/CG/raycasting.html
;
; Simple raycaster in Hollywood. There is some room for improvement in speed.
; For example I'm currently dividing the color RGB value of y-side walls by 2 to
; make them appear darker. Better way off course would be to use two separate textures
; lighter version for x-walls and darker version for y-walls. Distance and intensity
; values for floor casting could also be pre-calculated and put in to tables.
;
; By the way DisplayBrushPart() can do scaling, so you could draw textured
; wall slice with it to save quite a lot pixel plotting function calls.
;
; Distance shaded floor and ceiling without texturing could also simply
; be drawn with Box() function filled with gradient.
;
;
@DISPLAY {Mode = "Windowed", Height = 240, Width = 360, Title = "Hollywood Raycaster"}
@BRUSH 1, "pics\\redbrick.png", {LoadAlpha = False}
@BRUSH 3, "pics\\greystone.png", {LoadAlpha = False}
@BRUSH 2, "pics\\mossy.png", {LoadAlpha = False}
Const #MAPWIDHT = 24
Const #MAPHEIGHT = 24
Const #ROTSPEED = 0.10
Const #MOVESPEED = 0.25
Const #TW = 63
Const #TH = 63
Const #DISTFACTOR = 1/24
map = {}
map[0] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
map[1] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}
map[2] = {1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}
map[3] = {1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}
map[4] = {1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,0,1}
map[5] = {1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1}
map[6] = {1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,0,0,0,3,1,0,0,1}
map[7] = {1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1}
map[8] = {1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,1,1,0,1,0,0,1}
map[9] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1}
map[10] = {1,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,1,1,0,1}
map[11] = {1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1}
map[12] = {1,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,1}
map[13] = {1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1}
map[14] = {1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1}
map[15] = {1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1}
map[16] = {1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1}
map[17] = {1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,1,0,0,0,0,1}
map[18] = {1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1}
map[19] = {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1}
map[20] = {1,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1}
map[21] = {1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1}
map[22] = {1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1}
map[23] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
w, h = 359, 239
mode = 1
posX = 22
posY = 22
dirX = -1
dirY = 0
planeX = 0
planeY = 0.66
optionkeydown = False
; Textures from brushes to tables
Function p_InitTexture()
walltexture = {}
SelectBrush(1)
For Local x = 0 To #TW
walltexture[x] = {}
For Local y = 0 To #TH
walltexture[x][y] = ReadPixel(x, y)
Next
Next
EndSelect
floortexture = {}
SelectBrush(2)
For Local x = 0 To #TW
floortexture[x] = {}
For Local y = 0 To #TH
floortexture[x][y] = ReadPixel(x, y)
Next
Next
EndSelect
ceilingtexture = {}
SelectBrush(3)
For Local x = 0 To #TW
ceilingtexture[x] = {}
For Local y = 0 To #TH
ceilingtexture[x][y] = ReadPixel(x, y)
Next
Next
EndSelect
EndFunction
; Filled walls and filled floor and ceiling.
Function p_CastRays1()
SetFillStyle(#FILLCOLOR)
Box(0, #TOP, w + 1, (h + 1)/2, #MAROON)
Box(0, #BOTTOM, w + 1, (h + 1)/2, #YELLOW)
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
If drawStart < 0 Then drawStart = 0
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local color = #SILVER
If side = 1 Then color = color * 0.5
Line(x, drawStart, x, drawEnd, color)
Next
EndFunction
; Filled distance shaded walls, filled floor and ceiling.
Function p_CastRays2()
SetFillStyle(#FILLCOLOR)
Box(0, #TOP, w + 1, (h + 1)/2, #MAROON)
Box(0, #BOTTOM, w + 1, (h + 1)/2, #YELLOW)
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local intensity = #DISTFACTOR * (24 - perpWallDist)
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
If drawStart < 0 Then drawStart = 0
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local color = #SILVER
If side = 1 Then color = color * 0.5
Local R = Int(Red(color) * intensity)
Local G = Int(Green(color) * intensity)
Local B = Int(Blue(color) * intensity)
color = RGB(R,G,B)
Line(x, drawStart, x, drawEnd, color)
Next
EndFunction
; Filled walls, floor and ceiling. All distance shaded.
Function p_CastRays3()
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local intensity = #DISTFACTOR * (24 - perpWallDist)
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
If drawStart < 0 Then drawStart = 0
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local color = #SILVER
If side = 1 Then color = color * 0.5
Local R = Int(Red(color) * intensity)
Local G = Int(Green(color) * intensity)
Local B = Int(Blue(color) * intensity)
color = RGB(R,G,B)
Line(x, drawStart, x, drawEnd, color)
; Floor casting
Local floorXWall
Local FloorYWall
If side = 0 And rayDirX > 0
floorXWall = mapX
floorYWall = mapY + wallX
ElseIf side = 0 And rayDirX < 0
floorXWall = mapX + 1.0
floorYWall = mapY + wallX
ElseIf side = 1 And rayDirY > 0
floorXWall = mapX + wallX
floorYWall = mapY
Else
floorXWall = mapX + wallX
floorYWall = mapY + 1.0
EndIf
If drawEnd < 0 Then drawEnd = h
For y = drawEnd + 1 To h + 1
Local currentDist = h / (2.0 * y - h + 1)
intensity = 1/currentDist
Local fcolor = #YELLOW
R = Int(Red(fcolor) * intensity)
G = Int(Green(fcolor) * intensity)
B = Int(Blue(fcolor) * intensity)
fcolor = RGB(R,G,B)
Local ccolor = #MAROON
R = Int(Red(ccolor) * intensity)
G = Int(Green(ccolor) * intensity)
B = Int(Blue(ccolor) * intensity)
ccolor = RGB(R,G,B)
Plot(x, y, (fcolor >> 1) & 8355711) ; Floor
Plot(x, h - y, ccolor) ; Ceiling (symmetrical)
Next
Next
EndFunction
; Textured walls, filled floor and ceiling.
Function p_CastRays4()
SetFillStyle(#FILLCOLOR)
Box(0, #TOP, w + 1, (h + 1)/2, #MAROON)
Box(0, #BOTTOM, w + 1, (h + 1)/2, #YELLOW)
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
Local texYScale = #TH / lineHeight
If drawStart < 0
texY = -drawStart * texYScale
drawStart = 0
Else
texY = 0
EndIf
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local wallX
If side = 1
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) * 0.5) / rayDirY) * rayDirX
Else
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) * 0.5) / rayDirX) * rayDirY
EndIf
wallX = wallX - Floor(wallX)
Local texX = Int(wallX * #TW)
For Local y = drawStart To drawEnd
Local color = walltexture[texX][Int(texY)]
If side = 0
Plot(x, y, color)
Else
Plot(x, y, (color >> 1) & 8355711)
EndIf
texY = texY + texYScale
Next
Next
EndFunction
; Textured distance shaded walls. Filled floor and ceiling.
Function p_CastRays5()
SetFillStyle(#FILLCOLOR)
Box(0, #TOP, w + 1, (h + 1)/2, #MAROON)
Box(0, #BOTTOM, w + 1, (h + 1)/2, #YELLOW)
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local intensity = #DISTFACTOR * (24 - perpWallDist)
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
Local texYScale = #TH / lineHeight
If drawStart < 0
texY = -drawStart * texYScale
drawStart = 0
Else
texY = 0
EndIf
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local wallX
If side = 1
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) * 0.5) / rayDirY) * rayDirX
Else
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) * 0.5) / rayDirX) * rayDirY
EndIf
wallX = wallX - Floor(wallX)
Local texX = Int(wallX * #TW)
For Local y = drawStart To drawEnd
Local color = walltexture[texX][Int(texY)]
Local R = Int(Red(color) * intensity)
Local G = Int(Green(color) * intensity)
Local B = Int(Blue(color) * intensity)
color = RGB(R,G,B)
If side = 0
Plot(x, y, color)
Else
Plot(x, y, (color >> 1) & 8355711)
EndIf
texY = texY + texYScale
Next
Next
EndFunction
; Textured walls, floor and ceiling.
Function p_CastRays6()
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
Local texYScale = #TH / lineHeight
If drawStart < 0
texY = -drawStart * texYScale
drawStart = 0
Else
texY = 0
EndIf
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local wallX
If side = 1
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) * 0.5) / rayDirY) * rayDirX
Else
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) * 0.5) / rayDirX) * rayDirY
EndIf
wallX = wallX - Floor(wallX)
Local texX = Int(wallX * #TW)
For Local y = drawStart To drawEnd
Local color = walltexture[texX][Int(texY)]
If side = 0
Plot(x, y, color)
Else
Plot(x, y, (color >> 1) & 8355711)
EndIf
texY = texY + texYScale
Next
; Floor casting
Local floorXWall
Local FloorYWall
If side = 0 And rayDirX > 0
floorXWall = mapX
floorYWall = mapY + wallX
ElseIf side = 0 And rayDirX < 0
floorXWall = mapX + 1.0
floorYWall = mapY + wallX
ElseIf side = 1 And rayDirY > 0
floorXWall = mapX + wallX
floorYWall = mapY
Else
floorXWall = mapX + wallX
floorYWall = mapY + 1.0
EndIf
Local distWall = perpWallDist
If drawEnd < 0 Then drawEnd = h
For y = drawEnd + 1 To h + 1
Local currentDist = h / (2.0 * y - h + 1)
Local weight = currentDist / distWall
Local currentFloorX = weight * floorXWall + (1.0 - weight) * posX
Local currentFloorY = weight * floorYWall + (1.0 - weight) * posY
Local floorTexX = Int(currentFloorX * #TW) % #TW
Local floorTexY = Int(currentFloorY * #TH) % #TH
Local fcolor = floortexture[floorTexX][floorTexY]
Local ccolor = ceilingtexture[floorTexX][floorTexY]
Plot(x, y, (fcolor >> 1) & 8355711) ; Floor
Plot(x, h - y, ccolor) ; Ceiling (symmetrical)
Next
Next
EndFunction
; Textured walls, floor and ceiling. All distance shaded.
Function p_CastRays7()
For Local x = 0 To w
Local cameraX = 2 * x / w - 1
Local rayPosX = posX
Local rayPosY = PosY
Local rayDirX = dirX + planeX * cameraX
Local rayDirY = dirY + planeY * cameraX
Local mapX = Int(rayPosX)
Local mapY = Int(rayPosY)
Local deltaDistX = Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Local deltaDistY = Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Local hit = 0
Local stepX
Local stepY
Local sideDistX
Local sideDistY
Local side
If rayDirX < 0
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
EndIf
If rayDirY < 0
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
EndIf
While hit = 0
If sideDistX < sideDistY
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
Else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
EndIf
If map[mapX][mapY] > 0 Then hit = 1
Wend
Local perpWallDist
If side = 0
perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
Else
perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
EndIf
If perpWallDist = 0 Then perpWallDist = 1 ; Make sure no divide by zero is possible
Local intensity = #DISTFACTOR * (24 - perpWallDist)
Local lineHeight = Abs(Int(h / perpWallDist))
Local drawStart = -lineHeight * 0.5 + h * 0.5
Local texYScale = #TH / lineHeight
If drawStart < 0
texY = -drawStart * texYScale
drawStart = 0
Else
texY = 0
EndIf
Local drawEnd = lineHeight * 0.5 + h * 0.5
If drawEnd > h Then drawEnd = h
Local wallX
If side = 1
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) * 0.5) / rayDirY) * rayDirX
Else
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) * 0.5) / rayDirX) * rayDirY
EndIf
wallX = wallX - Floor(wallX)
Local texX = Int(wallX * #TW)
For Local y = drawStart To drawEnd
Local color = walltexture[texX][Int(texY)]
Local R = Int(Red(color) * intensity)
Local G = Int(Green(color) * intensity)
Local B = Int(Blue(color) * intensity)
color = RGB(R,G,B)
If side = 0
Plot(x, y, color)
Else
Plot(x, y, (color >> 1) & 8355711)
EndIf
texY = texY + texYScale
Next
; Floor casting
Local floorXWall
Local FloorYWall
If side = 0 And rayDirX > 0
floorXWall = mapX
floorYWall = mapY + wallX
ElseIf side = 0 And rayDirX < 0
floorXWall = mapX + 1.0
floorYWall = mapY + wallX
ElseIf side = 1 And rayDirY > 0
floorXWall = mapX + wallX
floorYWall = mapY
Else
floorXWall = mapX + wallX
floorYWall = mapY + 1.0
EndIf
Local distWall = perpWallDist
If drawEnd < 0 Then drawEnd = h
For y = drawEnd + 1 To h + 1
Local currentDist = h / (2.0 * y - h + 1)
intensity = 1/currentDist
Local weight = currentDist / distWall
Local currentFloorX = weight * floorXWall + (1.0 - weight) * posX
Local currentFloorY = weight * floorYWall + (1.0 - weight) * posY
Local floorTexX = Int(currentFloorX * #TW) % #TW
Local floorTexY = Int(currentFloorY * #TH) % #TH
Local fcolor = floortexture[floorTexX][floorTexY]
R = Int(Red(fcolor) * intensity)
G = Int(Green(fcolor) * intensity)
B = Int(Blue(fcolor) * intensity)
fcolor = RGB(R,G,B)
Local ccolor = ceilingtexture[floorTexX][floorTexY]
R = Int(Red(ccolor) * intensity)
G = Int(Green(ccolor) * intensity)
B = Int(Blue(ccolor) * intensity)
ccolor = RGB(R,G,B)
Plot(x, y, (fcolor >> 1) & 8355711) ; Floor
Plot(x, h - y, ccolor) ; Ceiling (symmetrical)
Next
Next
EndFunction
Function p_MainLoop()
Local oldDirX
Local oldDirY
Local oldPlaneX
If IsKeyDown("1")
If optionkeydown = False
mode = 1
optionkeydown = True
EndIf
ElseIf IsKeyDown("2")
If optionkeydown = False
mode = 2
optionkeydown = True
EndIf
ElseIf IsKeyDown("3")
If optionkeydown = False
mode = 3
optionkeydown = True
EndIf
ElseIf IsKeyDown("4")
If optionkeydown = False
mode = 4
optionkeydown = True
EndIf
ElseIf IsKeyDown("5")
If optionkeydown = False
mode = 5
optionkeydown = True
EndIf
ElseIf IsKeyDown("6")
If optionkeydown = False
mode = 6
optionkeydown = True
EndIf
ElseIf IsKeyDown("7")
If optionkeydown = False
mode = 7
optionkeydown = True
EndIf
Else
optionkeydown = False
EndIf
If IsKeyDown("LEFT")
If IsKeyDown("LALT")
oldDirX = dirX
oldDirY = dirY
dirX = dirX * Cos(Rad(90)) - dirY * Sin(Rad(90))
dirY = oldDirX * Sin(Rad(90)) + dirY * Cos(Rad(90))
If map[Int(posX + dirX * #MOVESPEED)][Int(posY)] = 0 Then posX = posX + dirX * #MOVESPEED
If map[Int(posX)][Int(posY + dirY * #MOVESPEED)] = 0 Then posY = posY + dirY * #MOVESPEED
dirX = oldDirX
dirY = oldDirY
Else
oldDirX = dirX
dirX = dirX * Cos(#ROTSPEED) - dirY * Sin(#ROTSPEED)
dirY = oldDirX * Sin(#ROTSPEED) + dirY * Cos(#ROTSPEED)
oldPlaneX = planeX
planeX = planeX * Cos(#ROTSPEED) - planeY * Sin(#ROTSPEED);
planeY = oldPlaneX * Sin(#ROTSPEED) + planeY * Cos(#ROTSPEED)
EndIf
ElseIf IsKeyDown("RIGHT")
If IsKeyDown("LALT")
oldDirX = dirX
oldDirY = dirY
dirX = dirX * Cos(Rad(-90)) - dirY * Sin(Rad(-90))
dirY = oldDirX * Sin(Rad(-90)) + dirY * Cos(Rad(-90))
If map[Int(posX + dirX * #MOVESPEED)][Int(posY)] = 0 Then posX = posX + dirX * #MOVESPEED
If map[Int(posX)][Int(posY + dirY * #MOVESPEED)] = 0 Then posY = posY + dirY * #MOVESPEED
dirX = oldDirX
dirY = oldDirY
Else
oldDirX = dirX
dirX = dirX * Cos(-#ROTSPEED) - dirY * Sin(-#ROTSPEED)
dirY = oldDirX * Sin(-#ROTSPEED) + dirY * Cos(-#ROTSPEED)
oldPlaneX = planeX
planeX = planeX * Cos(-#ROTSPEED) - planeY * Sin(-#ROTSPEED)
planeY = oldPlaneX * Sin(-#ROTSPEED) + planeY * Cos(-#ROTSPEED)
EndIf
EndIf
If IsKeyDown("UP")
If map[Int(posX + dirX * #MOVESPEED)][Int(posY)] = 0 Then posX = posX + dirX * #MOVESPEED
If map[Int(posX)][Int(posY + dirY * #MOVESPEED)] = 0 Then posY = posY + dirY * #MOVESPEED
ElseIf IsKeyDown("DOWN")
If map[Int(posX - dirX * #MOVESPEED)][Int(posY)] = 0 Then posX = posX - dirX * #MOVESPEED
If map[Int(posX)][Int(posY - dirY * #MOVESPEED)] = 0 Then posY = posY - dirY * #MOVESPEED
EndIf
Switch mode
Case 1:
p_CastRays1()
Case 2:
p_CastRays2()
Case 3:
p_CastRays3()
Case 4:
p_CastRays4()
Case 5:
p_CastRays5()
Case 6:
p_CastRays6()
Case 7:
p_CastRays7()
Default:
p_CastRays1()
EndSwitch
Flip
EndFunction
p_initTexture()
BeginDoubleBuffer()
SetInterval(1, p_MainLoop, 1000/50) ; 50fps
Repeat
WaitEvent
Forever