Raycasting

Discuss any general programming issues here
Post Reply
ArtBlink
Posts: 484
Joined: Mon Nov 01, 2010 10:37 am
Location: Albert - France
Contact:

Raycasting

Post by ArtBlink »

Hi all

Try this code (some bug but i correct this later ;-) )

Code: Select all

@SCREEN {Mode = "ask", Width = 640, Height = 480}
;--Définition de la taille de la carte, un tableau de 24 colonnes/24 lignes
NombreDeLigne=24
NombreDeColonne=24
; 0 rien, >0 un mur, le numéro étant la couleur de se mur
map = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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},
{1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,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},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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},
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,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,1}
}
; Position du départ dans le tableau
PositionEnXSurCarte = 22 ; Ligne N°21
PositionEnYSurCarte = 12 ; Colonne N°11

; Définition des variables
DirectionEnX = 1
DirectionEnY = 0
planex = 0
planey = 0.66
Vitesse= 1
rotation = 0.1
TailleEcranEnX=640
TailleEcranEnY=480
Function prg()
For Local CoordonnesEnX = 1 To TailleEcranEnX
CameraEnX = 2*CoordonnesEnX/TailleEcranEnX
rayposx = PositionEnXSurCarte 
rayposy = PositionEnYSurCarte 
raydirx = DirectionEnX + planex*CameraEnX
raydiry = DirectionEnY + planey*CameraEnX
mapx = rayposx
mapy = rayposy
DistanceLateraleEnX = 0
DistanceLateraleEnY = 0
deltadistx = Sqrt(1+(raydiry*raydiry)/(raydirx*raydirx))
deltadisty = Sqrt(1+(raydirx*raydirx)/(raydiry*raydiry))
perp = 0
stepx = 0
stepy = 0
Touche = 0
Cote = 0
If raydirx < 0 
stepx = -1
DistanceLateraleEnX = (rayposx - mapx)*deltadistx
Else
stepx = 1
DistanceLateraleEnX = (mapx + 1 - rayposx)*deltadistx 
EndIf
If raydiry < 0 
stepy = -1
DistanceLateraleEnY = (rayposy - mapy)*deltadisty
Else 
stepy = 1
DistanceLateraleEnY = (mapy + 1 - rayposy)*deltadisty 
EndIf
While Touche = 0 
If DistanceLateraleEnX < DistanceLateraleEnY 
DistanceLateraleEnX = DistanceLateraleEnX + deltadistx
mapx = mapx + stepx
Cote = 0
Else
DistanceLateraleEnY = DistanceLateraleEnY + deltadisty
mapy = mapy + stepy
Cote = 1
EndIf
Tmapx=Round(mapx)
Tmapy=Round(mapy)
If map[tmapx][tmapy] > 0 Then Touche = 1 
Wend
If Cote = 0 
perp = Abs((mapx - rayposx + (1-stepx)/2)/raydirx)		
Else 		
perp = Abs((mapy - rayposy + (1-stepy)/2)/raydiry)
EndIf
	
If perp<>0 Then HauteurLigne = Round(Abs(TailleEcranEnY/perp))	
If perp=0 Then HauteurLigne = Round(Abs(TailleEcranEnY/10))
DepartLigne = Round(-HauteurLigne /2 + TailleEcranEnY*0.5)
If DepartLigne < 1 Then DepartLigne = 1 
FinLigne = Round(HauteurLigne /2 + TailleEcranEnY*0.5)
If FinLigne >= TailleEcranEnX Then FinLigne = TailleEcranEnX- 1 
		
Switch(Map[TmapX][TmapY])
      
Case 1:  Couleur = $AA2222 ; Rouge
Case 2:  Couleur = $22AA22 ; Vert
Case 3:  Couleur = $2222AA ; Bleu
Case 4:  Couleur = $AAAAAA ; Blanc
Default: Couleur = $AAAA22 ; Jaune
      
EndSwitch
	
CouleurSol = $444444
CouleurPlafond = $888888
CouleurBandes = $666666
If Cote = 1 
Couleur=Couleur/2
CouleurBandes = CouleurBandes /2 
EndIf

BandeHaut = TailleEcranEnY/2+FinLigne 
BandeBas = TailleEcranEnY/2+DepartLigne 
		
Line (CoordonnesEnX,DepartLigne,CoordonnesEnX,FinLigne,Couleur); Mur
Line (CoordonnesEnX,FinLigne,CoordonnesEnX,FinLigne+240,CouleurSol) ; Sol
Line (CoordonnesEnX,0,CoordonnesEnX,DepartLigne,CouleurPlafond) ; Plafond
Line (CoordonnesEnX,BandeHaut/2,CoordonnesEnX,BandeHaut/2,CouleurBandes) ; Trait haut des murs
Line (CoordonnesEnX,BandeBas/2,CoordonnesEnX,BandeBas/2,CouleurBandes) ; Trait bas des murs
Line (CoordonnesEnX,TailleEcranEnY/2,CoordonnesEnX,TailleEcranEnY/2,CouleurBandes); Trait du milieu des murs

Next
	
Flip

Cls

If IsKeyDown("Up")=True 
Local A=Round(PositionEnXSurCarte + DirectionEnX * Vitesse)-1
Local B=Round(PositionEnYSurCarte + DirectionEnY * Vitesse)-1
Local Tposy=Round(PositionEnYSurCarte)
If map[A][Tposy] = 0 Then PositionEnXSurCarte = PositionEnXSurCarte + DirectionEnX * Vitesse
Local Tposx=Round(PositionEnXSurCarte)
If map[Tposx][B] = 0 Then PositionEnYSurCarte = PositionEnYSurCarte + DirectionEnY * Vitesse
EndIf

If IsKeyDown("Down")=True 
Local A=Round(PositionEnXSurCarte + DirectionEnX * Vitesse)-1
Local B=Round(PositionEnYSurCarte + DirectionEnY * Vitesse)-1
Local Tposy=Round(PositionEnYSurCarte)
If map[A][Tposy] = 0 Then PositionEnXSurCarte = PositionEnXSurCarte - DirectionEnX * Vitesse
Local Tposx=Round(PositionEnXSurCarte)
If map[Tposx][B] = 0 Then PositionEnYSurCarte = PositionEnYSurCarte - DirectionEnY * Vitesse
EndIf

If IsKeyDown("Left")=True 
;--both camera direction And camera plane must be rotated
oldDirX = DirectionEnX ;
DirectionEnx = DirectionEnX * Cos(-rotation) - DirectionEnY * Sin(-rotation);
DirectionEnY = oldDirX * Sin(-rotation) + DirectionEnY * Cos(-rotation);
oldPlaneX = planex;
planex = planex * Cos(-rotation) - planey * Sin(-rotation);
planey = oldPlaneX * Sin(-rotation) + planey * Cos(-rotation);
EndIf

If IsKeyDown("Right")=True 
;--both camera direction And camera plane must be rotated
oldDirX = DirectionEnX ;
DirectionEnx = DirectionEnX * Cos(rotation) - DirectionEnY * Sin(rotation);
DirectionEnY = oldDirX * Sin(rotation) + DirectionEnY * Cos(rotation);
oldPlaneX = planex;
planex = planex * Cos(rotation) - planey * Sin(rotation);
planey = oldPlaneX * Sin(rotation) + planey * Cos(rotation);
EndIf

EndFunction

BeginDoubleBuffer

SetInterval(1,PRG,1000/25)

Repeat	
WaitEvent()
Forever
Respect
jalih
Posts: 276
Joined: Fri Jun 18, 2010 8:08 pm
Location: Finland

Re: Raycasting

Post by jalih »

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.

Have fun!

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
ArtBlink
Posts: 484
Joined: Mon Nov 01, 2010 10:37 am
Location: Albert - France
Contact:

Re: Raycasting

Post by ArtBlink »

Yes... i used the same tuto ;-)

Well you are strong man in holly...

Thanks, you give me time to dev.

You can download my 3D engine at

http://jeannoel.roueste.free.fr/Amiga/starship3d4.hws

I think i used your raytracing engine to implemant light effect in my 3D engine ;-)

I ry to optimize you're raycast engine ;-)

Respect
Bugala
Posts: 1178
Joined: Sun Feb 14, 2010 7:11 pm

Re: Raycasting

Post by Bugala »

Would you please share the same tutorial with us too if its online one?
jalih
Posts: 276
Joined: Fri Jun 18, 2010 8:08 pm
Location: Finland

Re: Raycasting

Post by jalih »

Bugala wrote:Would you please share the same tutorial with us too if its online one?
Sure, just look at the first comments on my source posting. ;)
Post Reply