I have been working on a raycaster for school based off Lodev's texture free example (search up Lodev raycaster on most search engines and it should come up) and I am struggling with a couple major issues.
- I can't change the resolution variables, it makes no difference to how it gets drawn out
- While I haven't finished writing out the controls what I have already done should be capable of moving the player back and forth a bit
- the fps counter I can't get working
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'It seems that in order for the windows form to even load
'I have to I need to have everything run on a second thread, this is very annoying
'I have had less trouble with ininite loops on C than I have on VB.net
'Initial setup of variables
'Labeltest()
ScreenWidth = 640
ScreenHeight = 480
MapWidth = 24
MapWidth = 24
Do
'Label1.Text = "Wow the code actually ran this far!"
For X = 0 To ScreenWidth 'fix this later
'I assume the "w" on lodev's website is simply
'a stand in for "Width" As in screen width
'Label1.Text = "Wow the code actually ran this far!"
Dim CameraX As Double = 2 * X / Convert.ToDouble(ScreenWidth) - 1
Dim RayDirX As Double = DirX + PlaneX * CameraX
Dim RayDirY As Double = DirY + PlaneY * CameraX
'What box of the map the player is in
Dim MapX As Int16 = Convert.ToInt16(PosX)
'I'm trying out possible optimisations
'I'm considering making all integers 16 bit
Dim MapY As Int16 = Convert.ToInt16(PosY)
Dim SideDistX As Double
Dim SideDistY As Double
Dim PerpWallDist As Double
Dim StepX As Int16 'what direction to step in?
Dim StepY As Int16 'Either + or -1
Dim Hit As Int16 = 0 'Wall hit?
Dim Side As Int16 'Was a North-South or East-West wall hit?
Dim DeltaDistX As Double = Math.Sqrt(1 + (RayDirY * RayDirY) / (RayDirX * RayDirX))
Dim DeltaDistY As Double = Math.Sqrt(1 + (RayDirX * RayDirX) / (RayDirY * RayDirY))
'RayDir is the length of the vector (RayDirX, RayDirY)
If RayDirX < 0 Then
StepX = -1
SideDistX = (PosX - MapX) * DeltaDistX
ElseIf RayDirX > 0 Or RayDirX = 0 Then
StepX = 1
SideDistX = (MapX + 1.0 - PosX) * DeltaDistX
End If
If RayDirY < 0 Then
StepY = -1
SideDistY = (PosY - MapY) * DeltaDistY
ElseIf RayDirY > 0 Or RayDirY = 0 Then
StepY = 1
SideDistY = (MapY + 1.0 - PosY) * DeltaDistY
End If
'It is now time to perform DDA (I believe stands for Digital Differential Analyzer)
While Hit = 0
'Label1.Text = "Wow the code actually ran this far!"
'DDA is a way of reducing the amount of calculations needed
'for a raycaster down by a lot
'Without DDA it could theoretically take infinite calculations
'as is my understanding, DDA works by if a block in the map is "0" it doesn't
'keep checking smaller parts of the block it skips to the next one
If SideDistX < SideDistY Then
SideDistX += DeltaDistX
MapX += StepX
Side = 0
ElseIf SideDistX > SideDistY Or SideDistX = SideDistY Then
SideDistY += DeltaDistY
MapY += StepY
Side = 1
End If
If WorldMap(MapX, MapY) > 0 Then
Hit = 1
End If
End While
'Once thats done we know which wall our ray has hit
'Label1.Text = "Wow the code actually ran this far!"
If Side = 0 Then
PerpWallDist = SideDistX - DeltaDistX
ElseIf Side = 1 Then
PerpWallDist = SideDistY - DeltaDistY
End If
'480 is the test screen height
Dim LineHeight As Int16 = Int(ScreenHeight / PerpWallDist) 'ScreenHeight /
Dim DrawStart = (-LineHeight / 2) + ScreenHeight / 2
If DrawStart < 0 Then
DrawStart = 0
End If
Dim DrawEnd As Int16 = LineHeight / 2 + ScreenHeight / 2
If DrawEnd > ScreenHeight Or DrawEnd = ScreenHeight Then
DrawEnd = DrawEnd - 1
End If
'choosing wall colour I guess
Dim ColourRGB As Color
Select Case WorldMap(MapX, MapY)
'was considering alpha values but decided against it
Case 1
ColourRGB = Color.Gray
Case 2
ColourRGB = Color.Red
Case 3
ColourRGB = Color.Blue
Case 4
ColourRGB = Color.DarkMagenta
Case Else
ColourRGB = Color.Yellow
End Select
If Side = 1 Then
ColourRGB = Color.FromArgb(ColourRGB.R / 2, ColourRGB.G / 2, ColourRGB.B / 2)
'had quite a bit of trouble figuring this out
End If
ThePen = New Pen(ColourRGB, 1)
RayGraphics.DrawLine(ThePen, X, CInt(DrawStart), X, DrawEnd)
ThePen.Dispose() 'This seems to reduce memory usage by quite a bit. So thats good
MoveSpeed = 20.0
RotSpeed = 60.0
OldTime = Time
Time = inbetweentime
Dim FrameTime As Double = (Time - OldTime) / 1000.0
FPS = (1.0 / Time)
'While testing methods of erasing the screen I found a great way
'to demonstrate how raycasting works
'If you wish to demonstrate this uncomment the code below
'ThePen = New Pen(Color.Black, 999)
'RayGraphics.DrawLine(ThePen, 0, 0, ScreenWidth, ScreenHeight)
'Threading.Thread.Sleep(300)
Next
Loop
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text = "Frame:" & FPS
inbetweentime += 1
End Sub
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Up Then 'move forward if no wall is in front of you
If Not WorldMap(Int(PosX + DirX * MoveSpeed), Int(PosY)) Then
PosX += DirX * MoveSpeed
End If
'Label2.Text = "ok cool this works!"
If Not WorldMap(Int(PosX), Int(PosY + DirY * MoveSpeed)) Then
PosY += DirY * MoveSpeed
End If
End If
If e.KeyCode = Keys.Up Then 'move forward if no wall behind you
If WorldMap(Int(PosX - DirX * MoveSpeed), Int(PosY)) = False Then
PosX -= DirX * MoveSpeed
End If
End If
If e.KeyCode = Keys.Escape Then
Application.Exit()
End If
End Sub
End Class
Apologies for the poor formatting of the code, also I could not get all of the code into this post but this is the stuff that is the most relevant anyways. Also ignore the comments many of them are relevant to bits of code that no longer exist or were moved elsewhere, I do plan to fix this before I submit it to my teacher.