heres my RayCasting function:

Private Sub DrawRays2()
    Dim AY As Double
    Dim AX As Double
    Dim StepX As Double
    Dim StepY As Double
    Dim VertX As Double
    Dim VertY As Double
    Dim HorizX As Double
    Dim HorizY As Double
    Dim MapX As Long
    Dim MapY As Long
    Dim HorizDist As Double
    Dim VertDist As Double
    Dim WallDistance As Double
    Dim RayHeight As Double

    MapX = Player.MapX
    MapY = Player.MapY
    On Error Resume Next

'    'Check for horizontal intersections:
    If ((Player.Radians > 0 And Player.Radians < PI)) Then 'Facing down
        AY = (Int(Player.PosY / ObjectSize) * ObjectSize) + ObjectSize ' Calculate grid position
        AX = Player.PosX + (AY - Player.PosY) / Tan(Player.Radians)
        StepY = ObjectSize
    ElseIf ((Player.Radians = 0 And Player.Radians = PI)) Then
        AY = Player.PosY
        AX = Player.PosX
    Else 'Facing Up
        AY = (Int(Player.PosY / ObjectSize) * ObjectSize) - 1
        AX = Player.PosX + (AY - Player.PosY) / Tan(Player.Radians)
        StepY = -ObjectSize
    End If


    HorizX = AX
    HorizY = AY
    StepX = StepY / Tan(Player.Radians)
    MapX = Fix((HorizX) / ObjectSize)
    MapY = Fix((HorizY) / ObjectSize)
    A.SetPixel (Fix(HorizX)), (Fix(HorizY)), ColorConstants.vbCyan
    If LevelMap0(MapY, MapX) <> vbBlue Then

        Do

            HorizX = HorizX + StepX
            HorizY = HorizY + StepY

            MapX = Fix((HorizX) / ObjectSize)
            MapY = Fix((HorizY) / ObjectSize)
            A.SetPixel (Fix(HorizX)), (Fix(HorizY)), ColorConstants.vbCyan
            If LevelMap0(MapY, MapX) = vbBlue Then
                Exit Do
            End If
            DoEvents
        Loop
    End If


    HorizDist = Sqr(((HorizX - Player.PosX) * (HorizX - Player.PosX)) + ((HorizY - Player.PosY) * (HorizY - Player.PosY)))


    'Check for vertical intersections:
    If ((Player.Radians < PI / 2 Or Player.Radians > 3 * PI / 2)) Then 'Facing right
        AX = (Int(Player.PosX / ObjectSize) * ObjectSize) + ObjectSize ' Calculate grid position
        AY = Player.PosY + (Player.PosX - AX) * Tan(Player.Radians)
        StepX = ObjectSize
    ElseIf ((Player.Radians = PI / 2 Or Player.Radians = 3 * PI / 2)) Then
        AY = Player.PosY
        AX = Player.PosX
    Else 'Facing left
        AX = (Int(Player.PosX / ObjectSize) * ObjectSize) - 1
        AY = Player.PosY + (Player.PosX - AX) * Tan(Player.Radians)
        StepX = -ObjectSize
    End If


    VertX = AX
    VertY = AY
    StepY = StepX * Tan(Player.Radians)
    MapX = Fix((VertX) / ObjectSize)
    MapY = Fix((VertY) / ObjectSize)
    A.SetPixel (Fix(VertX)), (Fix(VertY)), vbYellow
    If LevelMap0(MapY, MapX) <> vbBlue Then
        Do

            VertX = VertX + StepX
            VertY = VertY + StepY


            MapX = Fix((VertX) / ObjectSize)
            MapY = Fix((VertY) / ObjectSize)
            A.SetPixel (Fix(VertX)), (Fix(VertY)), vbYellow
            If LevelMap0(MapY, MapX) = vbBlue Then
                Exit Do
            End If

            DoEvents
        Loop
    End If


    VertDist = Sqr(((VertX - Player.PosX)) * ((VertX - Player.PosX))) + (((VertY - Player.PosY)) * ((VertY - Player.PosY)))
    A.ForeColor vbRed

    'obter o a linha mais curta(horizontal ou vertical):
    If VertDist < HorizDist Then
        ' Draw the vertical ray:

        A.DrawLine Fix(Player.PosX), Fix(Player.PosY), Fix(VertX), Fix(VertY)
        WallDistance = VertDist
        Debug.Print VertDist & vbTab & "Draw Vertical" & vbTab & HorizDist & vbTab & "Horizontal line"
    Else
        ' Draw the horzontal ray:

        A.DrawLine Fix(Player.PosX), Fix(Player.PosY), Fix(HorizX), Fix(HorizY)
        WallDistance = HorizDist
        Debug.Print HorizDist & vbTab & " Draw Horizontal" & vbTab & VertDist & vbTab & "vertical line"
    End If

    WallDistance = WallDistance * Cos(Player.Radians)
    RayHeight = ObjectSize / WallDistance * 320
    A.ForeColor vbBlue
    A.DrawLine 475 + 50, 200 / 2 - RayHeight / 2, 475 + 50, 200 / 2 + RayHeight / 2

End Sub

output:
35,4424985851603     Draw Horizontal    4548,40096311184    vertical line

the Horizontal intersection works fine.. but why the Vertical intersection give me so big values(4548,40096311184)?
why the horizontal works fine but not the vertical?

Recommended Answers

All 6 Replies

For VertDist I would set a break on line 104 so I could examine the values in line 103.

Also, could be a localization issue that the comma is used for the decimal point and the integer of the results might be 35 and 4548.

finally i found the problem is on these line:

HorizDist = Sqr(((HorizX - Player.PosX) * (HorizX - Player.PosX)) + ((HorizY - Player.PosY) * (HorizY - Player.PosY))) 'works fine




VertDist = Sqr(((VertX - Player.PosX)) * ((VertX - Player.PosX))) + (((VertY - Player.PosY)) * ((VertY - Player.PosY)))'calculation incorrect

like you see the problem was the calculation order(or signal inverted)...
now works fine...
i need correct another calculation after these:

    WallDistance = WallDistance * Cos(Player.Radians) 'avoiding the Fish Effect.. works correctly
    RayHeight = ObjectSize / WallDistance * 320 '320 is the width screen... is for get the height of vertical line 
    A.ForeColor vbBlue
    A.DrawLine 475 + 50, 200 / 2 - RayHeight / 2, 475 + 50, 200 / 2 + RayHeight / 2 '200 is the Height screen
    '475 + 50 is where it must be drawed

like you see i get the Height vertical line... but theres a problem, because the 200 is the max... but i can get more when i'm too close :(
how can i fix these calculation?

commented: Let's say 200 is the max value, you can code it to limit it to 200. +17

not so easy :(

WallDistance = WallDistance * Cos(Abs(RayRadians - Player.Radians)) 'avoiding the Fish Effect
        RayHeight = (ObjectSize / WallDistance) * 200 '320 is the width screen
        If (RayHeight > 200) Then RayHeight = 200
        A.ForeColor vbBlue
        A.DrawLine 475 + 50 + RayCounts, 200 / 2 - RayHeight / 2, 475 + 50 + RayCounts, 200 / 2 + RayHeight / 2 '200 is the Height screen

because the wall never change if RayHeight is more than 200(moving to front or moving to back) :(

actual code:

Private Sub DrawRays2()
    Dim AY As Double
    Dim AX As Double
    Dim StepX As Double
    Dim StepY As Double
    Dim VertX As Double
    Dim VertY As Double
    Dim HorizX As Double
    Dim HorizY As Double
    Dim MapX As Long
    Dim MapY As Long
    Dim HorizDist As Double
    Dim VertDist As Double
    Dim WallDistance As Double
    Dim RayHeight As Double
    Dim RayRadians As Double
    Dim RadiansSteps As Double
    Dim RayCount As Integer
    Dim RayCounts As Integer
    RayCount = 320

    MapX = Player.MapX
    MapY = Player.MapY
    RadiansSteps = Radian60 / 320
    On Error Resume Next
    RayRadians = Player.Radians - Radian30
    RayCounts = 0
    Do While RayCounts < RayCount

    '    'Check for horizontal intersections:
        If ((RayRadians > 0 And RayRadians < PI)) Then 'Facing down
            AY = (Int(Player.PosY / ObjectSize) * ObjectSize) + ObjectSize ' Calculate grid position
            AX = Player.PosX + (AY - Player.PosY) / Tan(RayRadians)
            StepY = ObjectSize
        ElseIf ((RayRadians = 0 And RayRadians = PI)) Then
            AY = Player.PosY
            AX = Player.PosX
        Else 'Facing Up
            AY = (Int(Player.PosY / ObjectSize) * ObjectSize) - 1
            AX = Player.PosX + (AY - Player.PosY) / Tan(RayRadians)
            StepY = -ObjectSize
        End If


        HorizX = AX
        HorizY = AY
        StepX = StepY / Tan(RayRadians)
        MapX = Fix((HorizX) / ObjectSize)
        MapY = Fix((HorizY) / ObjectSize)
        'A.SetPixel (Fix(HorizX)), (Fix(HorizY)), ColorConstants.vbCyan
        If LevelMap0(MapY, MapX) <> vbBlue Then

            Do

                HorizX = HorizX + StepX
                HorizY = HorizY + StepY

                MapX = Fix((HorizX) / ObjectSize)
                MapY = Fix((HorizY) / ObjectSize)

                If LevelMap0(MapY, MapX) = vbBlue Then
                    Exit Do
                End If
                'A.SetPixel (Fix(HorizX)), (Fix(HorizY)), ColorConstants.vbCyan
                DoEvents
            Loop
        End If


        'HorizDist = Sqr(((HorizX - Player.PosX) * (HorizX - Player.PosX)) + ((HorizY - Player.PosY) * (HorizY - Player.PosY)))
        HorizDist = Abs((Player.PosX - HorizX) / Cos(RayRadians))

        'Check for vertical intersections:
        If ((RayRadians < PI / 2 Or RayRadians > 3 * PI / 2)) Then 'Facing right
            AX = (Int(Player.PosX / ObjectSize) * ObjectSize) + ObjectSize ' Calculate grid position
            AY = Player.PosY + (Player.PosX - AX) * -Tan(RayRadians)
            StepX = ObjectSize
        ElseIf ((RayRadians = PI / 2 Or RayRadians = 3 * PI / 2)) Then
            AY = Player.PosY
            AX = Player.PosX
        Else 'Facing left
            AX = (Int(Player.PosX / ObjectSize) * ObjectSize) - 1
            AY = Player.PosY + (Player.PosX - AX) * -Tan(RayRadians)
            StepX = -ObjectSize
        End If


        VertX = AX
        VertY = AY
        StepY = StepX * Tan(RayRadians)
        MapX = Fix((VertX) / ObjectSize)
        MapY = Fix((VertY) / ObjectSize)
        'A.SetPixel (Fix(VertX)), (Fix(VertY)), vbYellow
        If LevelMap0(MapY, MapX) <> vbBlue Then
            Do

                VertX = VertX + StepX
                VertY = VertY + StepY


                MapX = Fix((VertX) / ObjectSize)
                MapY = Fix((VertY) / ObjectSize)

                If LevelMap0(MapY, MapX) = vbBlue Then
                    Exit Do
                End If
                'A.SetPixel (Fix(VertX)), (Fix(VertY)), vbYellow
                'DoEvents
            Loop
        End If


        'VertDist = Sqr(((VertX - Player.PosX)) * ((VertX - Player.PosX))) + (((VertY - Player.PosY)) * ((VertY - Player.PosY)))
        VertDist = Abs((Player.PosX - VertX) / Cos(RayRadians))
        'A.ForeColor vbRed

        'obter o a linha mais curta(horizontal ou vertical):
        If VertDist < HorizDist Then
            ' Draw the vertical ray:

            A.DrawLine Fix(Player.PosX), Fix(Player.PosY), Fix(VertX), Fix(VertY)
            WallDistance = VertDist
            'Debug.Print VertDist & vbTab & "Draw Vertical" & vbTab & HorizDist & vbTab & "Horizontal line"
        Else
            ' Draw the horzontal ray:

            A.DrawLine Fix(Player.PosX), Fix(Player.PosY), Fix(HorizX), Fix(HorizY)
            WallDistance = HorizDist
            'Debug.Print HorizDist & vbTab & " Draw Horizontal" & vbTab & VertDist & vbTab & "vertical line"
        End If

        WallDistance = WallDistance * Cos(Abs(RayRadians - Player.Radians)) 'avoiding the Fish Effect
        RayHeight = (ObjectSize / WallDistance) * 200 '320 is the width screen
        'If (RayHeight > 200) Then RayHeight = 200
        'A.ForeColor vbBlue
        A.DrawLine 475 + 50 + RayCounts, 200 / 2 - RayHeight / 2, 475 + 50 + RayCounts, 200 / 2 + RayHeight / 2 '200 is the Height screen
        RayRadians = RayRadians + RadiansSteps
        If RayRadians >= (Player.Radians + Radian30) Then RayRadians = (Player.Radians + Radian30)
        If RayRadians <= (Player.Radians - Radian30) Then RayRadians = (Player.Radians - Radian30)
        RayCounts = RayCounts + 1
        DoEvents
    Loop
    'Debug.Print RayCounts
End Sub

the bugs:

  • when radians is between 6 and 5:
    https://imgur.com/MNb7J8W

  • when i'm too close to the wall(it can be 'fixed' when i move?):

    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Const Speed As Integer = 2
    Const Radians As Double = 0.1
    If (KeyCode = vbKeyEscape) Then
    blnLoop = False
    Set A = Nothing
    Set s = Nothing
    End
    ElseIf (KeyCode = vbKeyLeft) Then
    Player.Radians = Player.Radians - Radians
    If (Player.Radians <= 0) Then Player.Radians = 2 PI + Player.Radians
    Player.MoveX = Cos(Player.Radians)
    Speed
    Player.MoveY = Sin(Player.Radians) Speed
    ElseIf (KeyCode = vbKeyRight) Then
    Player.Radians = Player.Radians + Radians
    If (Player.Radians >= 2
    PI) Then Player.Radians = 0
    Player.MoveX = Cos(Player.Radians) Speed
    Player.MoveY = Sin(Player.Radians)
    Speed
    ElseIf (KeyCode = vbKeyUp) Then
    If (LevelMap0(Fix((Player.PosY + Player.MoveY) / ObjectSize), Fix((Player.PosX + Player.MoveX) / ObjectSize)) <> vbBlue) Then
    Player.PosX = Player.PosX + Player.MoveX
    Player.PosY = Player.PosY + Player.MoveY
    Player.MapX = Fix((Player.PosX) / ObjectSize)
    Player.MapY = Fix((Player.PosY) / ObjectSize)
    End If
    ElseIf (KeyCode = vbKeyDown) Then
    If (LevelMap0(Fix((Player.PosY - Player.MoveY) / ObjectSize), Fix((Player.PosX - Player.MoveX) / ObjectSize)) <> vbBlue) Then
    Player.PosX = Player.PosX - Player.MoveX
    Player.PosY = Player.PosY - Player.MoveY
    Player.MapX = Fix((Player.PosX) / ObjectSize)
    Player.MapY = Fix((Player.PosY) / ObjectSize)
    End If
    End If
    Me.Caption = "X: " + Str(Player.MapX) + " Y: " + Str(Player.MapY) + " FPS: " + Str(FramePerSecond) + "Player Radians: " + Str(Player.Radians)
    End Sub

https://imgur.com/xsO4bS2
what i'm doing wrong?

i fix 1 error:

ElseIf (KeyCode = vbKeyUp) Then
        If (LevelMap0(Fix((Player.PosY + Player.MoveY * Speed) / ObjectSize), Fix((Player.PosX + Player.MoveX * Speed) / ObjectSize)) <> vbBlue) Then

'and:
ElseIf (KeyCode = vbKeyDown) Then
        If (LevelMap0(Fix((Player.PosY - Player.MoveY * Speed) / ObjectSize), Fix((Player.PosX - Player.MoveX * Speed) / ObjectSize)) <> vbBlue) Then

now i see some space between the player and the wall... was the best way.
now see the entire function:

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Const Speed As Double = 4.2
    Const Radians As Double = 0.1
    If (KeyCode = vbKeyEscape) Then
        blnLoop = False
        Set A = Nothing
        Set s = Nothing
        End
    ElseIf (KeyCode = vbKeyLeft) Then
        Player.Radians = Player.Radians - Radians
        If (Player.Radians <= 0) Then Player.Radians = 2 * PI
        Player.MoveX = Cos(Player.Radians) * Speed
        Player.MoveY = Sin(Player.Radians) * Speed
    ElseIf (KeyCode = vbKeyRight) Then
        Player.Radians = Player.Radians + Radians
        If (Player.Radians >= 2 * PI) Then Player.Radians = 0
        Player.MoveX = Cos(Player.Radians) * Speed
        Player.MoveY = Sin(Player.Radians) * Speed
    ElseIf (KeyCode = vbKeyUp) Then
        If (LevelMap0(Fix((Player.PosY + Player.MoveY * Speed) / ObjectSize), Fix((Player.PosX + Player.MoveX * Speed) / ObjectSize)) <> vbBlue) Then
            Player.PosX = Player.PosX + Player.MoveX
            Player.PosY = Player.PosY + Player.MoveY
            Player.MapX = Fix((Player.PosX) / ObjectSize)
            Player.MapY = Fix((Player.PosY) / ObjectSize)
        End If
    ElseIf (KeyCode = vbKeyDown) Then
        If (LevelMap0(Fix((Player.PosY - Player.MoveY * Speed) / ObjectSize), Fix((Player.PosX - Player.MoveX * Speed) / ObjectSize)) <> vbBlue) Then
            Player.PosX = Player.PosX - Player.MoveX
            Player.PosY = Player.PosY - Player.MoveY
            Player.MapX = Fix((Player.PosX) / ObjectSize)
            Player.MapY = Fix((Player.PosY) / ObjectSize)
        End If
    End If
    Me.Caption = "X: " + Str(Player.MapX) + "  Y: " + Str(Player.MapY) + " FPS: " + Str(FramePerSecond) + "Player Radians: " + Str(Player.Radians)
End Sub

i'm trying 'fix' the Radians code... my objective is avoiding the negative values..... how can i fix that 'if's'?

after several tests i fix it:

Do While RayCounts < RayCount
        If (RayRadians > (2 * PI)) Then RayRadians = 0.001

i have more to update:
1 - win more performance\FPS;
2 - and trying avoid the 'on error resume next'(it's about the array dimensions):

Private Sub DrawRays2()

    Dim AY As Double
    Dim AX As Double
    Dim StepX As Double
    Dim StepY As Double
    Dim VertX As Double
    Dim VertY As Double
    Dim HorizX As Double
    Dim HorizY As Double
    Dim MapX As Long
    Dim MapY As Long
    Dim HorizDist As Double
    Dim VertDist As Double
    Dim WallDistance As Double
    Dim RayHeight As Double
    Dim RayRadians As Double
    Dim RadiansSteps As Double
    Dim RayCount As Integer
    Dim RayCounts As Integer
    RayCount = 320

    MapX = Player.MapX
    MapY = Player.MapY
    RadiansSteps = Radian60 / 320

    On Error Resume Next
    RayRadians = (Player.Radians - Radian30)
    RayCounts = 0
    Do While RayCounts < RayCount
        If (RayRadians > (2 * PI)) Then RayRadians = 0.001
        'Check for horizontal intersections:
        If RayRadians > 0 And RayRadians < PI Then 'Facing down

thanks for all

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.