-
Jun 28th, 2017, 12:20 PM
#1
Thread Starter
Junior Member
I have a problem getting this raycasting example to work
First of all, I am copying lodevs c++ tutorial on raycasting. I got it to work partway, but my inexperience got me stuck in several different points. I'm posting the code here. You will need a picturebox and a timer to get this to run. It is a windows forms application.
If you run it and use the w-a-s-d keys, turn left and right a couple of key presses. You will notice that there is an anomaly and the room is not rendered the way it is in the map array. I don't know why.
Another problem I have, is that I did not correctly copy the timing routine from lodevs example. I'm not sure how to set that up in visual basic. So I am using a timer for the steps. I am guessing that maybe because its exactly 100 milliseconds between ticks, that i get the the artifacts. How can I fix this. i understand that this is a big question and that it takes considerable knowledge to perhaps get this going, but maybe there is an expert here that knows 3D graphics. As for Visual Basic, I initially noticed that in raycasting, the example's performance is really good. So it is a possible project, that I would like to take further once I understand this.
Since it's my first post, I think I shouldn't post a link. Just google "Lodev's raycasting" graphics tutorial and it should come up with the C++ example webpage so you can compare my effort.
Thank you.
Code:
Public Class frmMain
Dim w As Integer = 512
Dim h As Integer = 384
Const mapWidth As Integer = 23
Const mapHeight As Integer = 23
Dim worldMap(mapWidth, mapHeight) As Integer
Dim posX As Double = 22
Dim posY As Double = 12
Dim dirX As Double = -1
Dim dirY As Double = 0
Dim planeX As Double = 0
Dim planeY As Double = 0.66
Dim backbuffer As New Bitmap(w, h)
Dim g_backbuffer As Graphics = Graphics.FromImage(backbuffer)
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Init()
myTimer.Interval = 100
myTimer.Start()
End Sub
Private Sub Init()
worldMap = {{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, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 4, 4, 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, 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, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 4, 0, 0, 0, 0, 0, 0, 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}}
End Sub
Dim s As New Stopwatch
Private Sub GameLoop()
g_backbuffer.Clear(Color.Black)
For x As Integer = 0 To w - 1
Dim cameraX As Double = 2 * x / w - 1
Dim rayPosX As Double = posX
Dim rayPosY As Double = posY
Dim rayDirX As Double = dirX + planeX * cameraX
Dim rayDirY As Double = dirY + planeY * cameraX
Dim mapX As Integer = CInt(rayPosX)
Dim mapY As Integer = CInt(rayPosY)
Dim sideDistX As Double
Dim sideDistY As Double
Dim deltaDistX As Double = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Dim deltaDistY As Double = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Dim perpWallDist As Double
Dim stepX As Integer
Dim stepY As Integer
Dim hit As Integer = 0
Dim side As Integer
If rayDirX < 0 Then
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
End If
If rayDirY < 0 Then
stepY = -1
sideDistX = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
End If
While hit = 0
If sideDistX < sideDistY Then
sideDistX += deltaDistX
mapX += stepX
side = 0
Else
sideDistY += deltaDistY
mapY += stepY
side = 1
End If
If worldMap(mapX, mapY) > 0 Then
hit = 1
End If
End While
If side = 0 Then
perpWallDist = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX
Else
perpWallDist = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY
End If
Dim lineHeight As Integer = CInt(h / perpWallDist)
Dim drawStart As Double = -lineHeight / 2 + h / 2
If drawStart < 0 Then
drawStart = 0
End If
Dim drawEnd As Double = lineHeight / 2 + h / 2
If drawEnd >= h Then
drawEnd = h - 1
End If
Dim colr As Color
Select Case worldMap(mapX, mapY)
Case 1
colr = Color.Red
Case 2
colr = Color.Green
Case 3
colr = Color.Blue
Case 4
colr = Color.White
Case Else
colr = Color.Yellow
End Select
If side = 1 Then
colr = Color.FromArgb(colr.R \ 2, colr.G \ 2, colr.B \ 2)
End If
g_backbuffer.DrawLine(New Pen(colr), x, CInt(drawStart), x, CInt(drawEnd))
Next
End Sub
Dim moveSpeed As Double
Dim rotSpeed As Double
Private Sub pbView_Paint(sender As Object, e As PaintEventArgs) Handles pbView.Paint
e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
e.Graphics.DrawImage(backbuffer, 0, 0)
End Sub
Private Sub frmMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.W
If worldMap(CInt(posX + dirX * moveSpeed), CInt(posY)) = 0 Then
posX += dirX * moveSpeed
End If
If worldMap(CInt(posX), CInt(posY + dirY * moveSpeed)) = 0 Then
posY += dirY * moveSpeed
End If
pbView.Invalidate()
Case Keys.S
If worldMap(CInt(posX - dirX * moveSpeed), CInt(posY)) = 0 Then
posX -= dirX * moveSpeed
End If
If worldMap(CInt(posX), CInt(posY - dirY * moveSpeed)) = 0 Then
posY -= dirY * moveSpeed
End If
Case Keys.D
Dim oldDirX As Double = dirX
dirX = dirX * Math.Cos(-rotSpeed) - dirY * Math.Sin(-rotSpeed)
dirY = oldDirX * Math.Sin(-rotSpeed) + dirY * Math.Cos(-rotSpeed)
Dim oldPlaneX As Double = planeX
planeX = planeX * Math.Cos(-rotSpeed) - planeY * Math.Sin(-rotSpeed)
planeY = oldPlaneX * Math.Sin(-rotSpeed) + planeY * Math.Cos(-rotSpeed)
Case Keys.A
Dim oldDirX As Double = dirX
dirX = dirX * Math.Cos(rotSpeed) - dirY * Math.Sin(rotSpeed)
dirY = oldDirX * Math.Sin(rotSpeed) + dirY * Math.Cos(rotSpeed)
Dim oldPlaneX As Double = planeX
planeX = planeX * Math.Cos(rotSpeed) - planeY * Math.Sin(rotSpeed)
planeY = oldPlaneX * Math.Sin(rotSpeed) + planeY * Math.Cos(rotSpeed)
End Select
End Sub
Private Sub myTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles myTimer.Tick
moveSpeed = 1.0
rotSpeed = 1.0
GameLoop()
pbView.Invalidate
End Sub
End Class
-
Jun 29th, 2017, 12:22 AM
#2
Re: I have a problem getting this raycasting example to work
Well, there may be other problems, but one definite one is a copy and past error, I think.
Code:
If rayDirY < 0 Then
stepY = -1
sideDistX = (rayPosY - mapY) * deltaDistY
Else
You're dealing with Y here, but modifying sideDistX instead of sideDistY.
That should clear up the major anomaly.
-
Jun 30th, 2017, 05:16 AM
#3
Thread Starter
Junior Member
Re: I have a problem getting this raycasting example to work
It's really great to get a second opinion. I verified the mistake and the lodev tutorial does not have the mistake either, so like you said it's probably my cut and paste error. I will test it first thing tomorrow. I really appreciate that, thank you.
-
Jul 2nd, 2017, 05:26 PM
#4
Thread Starter
Junior Member
Re: I have a problem getting this raycasting example to work
I followed the recommendation and as it turns out, the problem disappeared. I have a few more issues that I am trying to solve, which I am still having a hard time with.
What I did first of all is strip the program down completely so it does not depend on timing of any type. This time all you have to do is cut and paste the code and add a picturebox (be sure to name it). So you don't have to worry about setting up a timer or anything like that.
The issue now is in the WASD keys. I would like to move 1 unit forward and 1 back and turn 90 degrees left and 90 degrees right. I followed the rules with sin and cos, but the turns are not accurate 90 degree turns. The steps forward and backward are in units of 1, so also I am not sure how that could correspond to each square on the map. I don't know how to measure it.
After solving this, the only other thing that does not work is collision detection. In the original lodev program, there seems to be a boundary that is not passed. If I take steps instead of units, I think I step into the collision which crashes the program. Not sure if I understand that either, so here I am again asking for someone to look at this for me.
btw - What I am trying to do is move around in 3D space like I would in a tile map.
Code:
Public Class frmMain
Dim w As Integer = 512
Dim h As Integer = 384
Const mapWidth As Integer = 23
Const mapHeight As Integer = 23
Dim worldMap(mapWidth, mapHeight) As Integer
Dim posX As Double = 22
Dim posY As Double = 12
Dim dirX As Double = -1
Dim dirY As Double = 0
Dim planeX As Double = 0
Dim planeY As Double = 0.66
Dim backbuffer As New Bitmap(w, h)
Dim g_backbuffer As Graphics = Graphics.FromImage(backbuffer)
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Init()
End Sub
Private Sub Init()
worldMap = {{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, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 4, 4, 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, 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, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 4, 0, 0, 0, 0, 0, 0, 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}}
End Sub
Private Sub GameLoop()
g_backbuffer.Clear(Color.Black)
For x As Integer = 0 To w - 1
Dim cameraX As Double = 2 * x / w - 1
Dim rayPosX As Double = posX
Dim rayPosY As Double = posY
Dim rayDirX As Double = dirX + planeX * cameraX
Dim rayDirY As Double = dirY + planeY * cameraX
Dim mapX As Integer = CInt(rayPosX)
Dim mapY As Integer = CInt(rayPosY)
Dim sideDistX As Double
Dim sideDistY As Double
Dim deltaDistX As Double = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Dim deltaDistY As Double = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Dim perpWallDist As Double
Dim stepX As Integer
Dim stepY As Integer
Dim hit As Integer = 0
Dim side As Integer
If rayDirX < 0 Then
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
End If
If rayDirY < 0 Then
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
End If
While hit = 0
If sideDistX < sideDistY Then
sideDistX += deltaDistX
mapX += stepX
side = 0
Else
sideDistY += deltaDistY
mapY += stepY
side = 1
End If
If worldMap(mapX, mapY) > 0 Then
hit = 1
End If
End While
If side = 0 Then
perpWallDist = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX
Else
perpWallDist = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY
End If
Dim lineHeight As Integer = CInt(h / perpWallDist)
Dim drawStart As Double = -lineHeight / 2 + h / 2
If drawStart < 0 Then
drawStart = 0
End If
Dim drawEnd As Double = lineHeight / 2 + h / 2
If drawEnd >= h Then
drawEnd = h - 1
End If
Dim colr As Color
Select Case worldMap(mapX, mapY)
Case 1
colr = Color.Red
Case 2
colr = Color.Green
Case 3
colr = Color.Blue
Case 4
colr = Color.White
Case Else
colr = Color.Yellow
End Select
If side = 1 Then
colr = Color.FromArgb(colr.R \ 2, colr.G \ 2, colr.B \ 2)
End If
g_backbuffer.DrawLine(New Pen(colr), x, CInt(drawStart), x, CInt(drawEnd))
Next
pbView.Invalidate()
End Sub
Dim moveSpeed As Double = 1.0F
Dim rotSpeed As Double = 1.0F
Private Sub pbView_Paint(sender As Object, e As PaintEventArgs) Handles pbView.Paint
e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
GameLoop()
e.Graphics.DrawImage(backbuffer, 0, 0)
End Sub
Private Sub frmMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.W
If worldMap(CInt(posX + dirX * moveSpeed), CInt(posY)) = 0 Then
posX += dirX * moveSpeed
End If
If worldMap(CInt(posX), CInt(posY + dirY * moveSpeed)) = 0 Then
posY += dirY * moveSpeed
End If
pbView.Invalidate()
Case Keys.S
If worldMap(CInt(posX - dirX * moveSpeed), CInt(posY)) = 0 Then
posX -= dirX * moveSpeed
End If
If worldMap(CInt(posX), CInt(posY - dirY * moveSpeed)) = 0 Then
posY -= dirY * moveSpeed
End If
Case Keys.D
Dim oldDirX As Double = dirX
dirX = dirX * Math.Cos(-90) - dirY * Math.Sin(-90)
dirY = oldDirX * Math.Sin(-90) + dirY * Math.Sin(-90)
Dim oldPlaneX As Double = planeX
planeX = planeX * Math.Cos(-90) - planeY * Math.Sin(-90)
planeY = oldPlaneX * Math.Sin(-90) + planeY * Math.Cos(-90)
Case Keys.A
' opposite direction
End Select
End Sub
End Class
-
Jul 2nd, 2017, 09:22 PM
#5
Thread Starter
Junior Member
Re: I have a problem getting this raycasting example to work
OK, somewhat of a success. I don't want to clutter this thread, so let me be clear about what is going on. There is only one more thing I need assistance with for now. Hopefully someone can help.
I finally have a working example, that steps approximately. The only problem, if you notice is that each step the player takes is not exactly 1 unit square. All this code with degrees and radians is a bit confusing to me. Everything works, and collision is approximately ok. I know the collision is bad because the steps are incorrect now.
What I would like to know, is how can I finally normalize the steps. So one keypress = 1 unit square step for the player. Every time I rotate, the radians that are the result for dirX and dirY multiply a different extent for the pos of the player. How can I normalize it to 1?
Here is the code:
Code:
Public Class frmMain
Dim w As Integer = 512
Dim h As Integer = 384
Const mapWidth As Integer = 23
Const mapHeight As Integer = 23
Dim worldMap(mapWidth, mapHeight) As Integer
Dim posX As Double = 7
Dim posY As Double = 12
Dim dirX As Double = -1
Dim dirY As Double = 0
Dim planeX As Double = 0
Dim planeY As Double = 0.66
Dim backbuffer As New Bitmap(w, h)
Dim g_backbuffer As Graphics = Graphics.FromImage(backbuffer)
Dim bRunning As Boolean = True
Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
bRunning = False
End Sub
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Init()
Me.Show()
Do While bRunning
Application.DoEvents()
GameLoop
Loop
End Sub
Private Sub Init()
worldMap = {{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, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 4, 0, 4, 4, 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, 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, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 4, 0, 0, 0, 0, 0, 0, 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}}
End Sub
Private Sub GameLoop()
g_backbuffer.Clear(Color.Black)
For x As Integer = 0 To w - 1
Dim cameraX As Double = 2 * x / w - 1
Dim rayPosX As Double = posX
Dim rayPosY As Double = posY
Dim rayDirX As Double = dirX + planeX * cameraX
Dim rayDirY As Double = dirY + planeY * cameraX
Dim mapX As Integer = CInt(rayPosX)
Dim mapY As Integer = CInt(rayPosY)
Dim sideDistX As Double
Dim sideDistY As Double
Dim deltaDistX As Double = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
Dim deltaDistY As Double = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
Dim perpWallDist As Double
Dim stepX As Integer
Dim stepY As Integer
Dim hit As Integer = 0
Dim side As Integer
If rayDirX < 0 Then
stepX = -1
sideDistX = (rayPosX - mapX) * deltaDistX
Else
stepX = 1
sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
End If
If rayDirY < 0 Then
stepY = -1
sideDistY = (rayPosY - mapY) * deltaDistY
Else
stepY = 1
sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
End If
While hit = 0
If sideDistX < sideDistY Then
sideDistX += deltaDistX
mapX += stepX
side = 0
Else
sideDistY += deltaDistY
mapY += stepY
side = 1
End If
If worldMap(mapX, mapY) > 0 Then
hit = 1
End If
End While
If side = 0 Then
perpWallDist = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX
Else
perpWallDist = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY
End If
Dim lineHeight As Integer = CInt(h / perpWallDist)
Dim drawStart As Double = -lineHeight / 2 + h / 2
If drawStart < 0 Then
drawStart = 0
End If
Dim drawEnd As Double = lineHeight / 2 + h / 2
If drawEnd >= h Then
drawEnd = h - 1
End If
Dim colr As Color
Select Case worldMap(mapX, mapY)
Case 1
colr = Color.Red
Case 2
colr = Color.Green
Case 3
colr = Color.Blue
Case 4
colr = Color.White
Case Else
colr = Color.Yellow
End Select
If side = 1 Then
colr = Color.FromArgb(colr.R \ 2, colr.G \ 2, colr.B \ 2)
End If
g_backbuffer.DrawLine(New Pen(colr), x, CInt(drawStart), x, CInt(drawEnd))
Next
pbView.Invalidate()
End Sub
Private Sub pbView_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles pbView.Paint
e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
e.Graphics.DrawImage(backbuffer, 0, 0)
End Sub
Private Sub frmMain_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.W
If worldMap(CInt(posX + dirX), CInt(posY)) = 0 Then
posX += dirX
End If
If worldMap(CInt(posX), CInt(posY + dirY)) = 0 Then
posY += dirY
End If
Case Keys.S
If worldMap(CInt(posX - dirX), CInt(posY)) = 0 Then
posX -= dirX
End If
If worldMap(CInt(posX), CInt(posY - dirY)) = 0 Then
posY -= dirY
End If
Case Keys.D
'Dim oldDirX As Double = dirX
'dirX = dirX * Math.Cos(-rotSpeed) - dirY * Math.Sin(-rotSpeed)
'dirY = oldDirX * Math.Sin(-rotSpeed) + dirY * Math.Cos(-rotSpeed)
'Dim oldPlaneX As Double = planeX
'planeX = planeX * Math.Cos(-rotSpeed) - planeY * Math.Sin(-rotSpeed)
'planeY = oldPlaneX * Math.Sin(-rotSpeed) + planeY * Math.Cos(-rotSpeed)
Dim oldDirX As Double = dirX
dirX = dirX * Math.Cos(-1.5708) - dirY * Math.Sin(-1.5708)
dirY = oldDirX * Math.Sin(-1.5708) + dirY * Math.Cos(-1.5708)
Dim oldPlaneX As Double = planeX
planeX = planeX * Math.Cos(-1.5708) - planeY * Math.Sin(-1.5708)
planeY = oldPlaneX * Math.Sin(-1.5708) + planeY * Math.Cos(-1.5708)
Case Keys.A
'Dim oldDirX As Double = dirX
'dirX = dirX * Math.Cos(rotSpeed) - dirY * Math.Sin(rotSpeed)
'dirY = oldDirX * Math.Sin(rotSpeed) + dirY * Math.Cos(rotSpeed)
'Dim oldPlaneX As Double = planeX
'planeX = planeX * Math.Cos(rotSpeed) - planeY * Math.Sin(rotSpeed)
'planeY = oldPlaneX * Math.Sin(rotSpeed) + planeY * Math.Cos(rotSpeed)
Dim oldDirX As Double = dirX
dirX = dirX * Math.Cos(1.5708) - dirY * Math.Sin(1.5708)
dirY = oldDirX * Math.Sin(1.5708) + dirY * Math.Cos(1.5708)
Dim oldPlaneX As Double = planeX
planeX = planeX * Math.Cos(1.5708) - planeY * Math.Sin(1.5708)
planeY = oldPlaneX * Math.Sin(1.5708) + planeY * Math.Cos(1.5708)
End Select
Me.Text = dirX.ToString & ":" & dirY.ToString
End Sub
End Class
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|