Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Line Of Sight


shadowwulf
 Share

Recommended Posts

Here is a crack at pseudo-code for a Line of Sight.
For those that need explaining:Line of sight means you can see your intended target. If you can't see them. You can't target them.

What I am trying to do via code:
1:Get attacker and victim locations.
2:Get slope of angle from attacker to target.
3a:Move along X axis to target
3b:Move along Y axis when we hit slope

>! Public Function CanTarget()
'finds the target locations, calculates slope, checks for blocks on tiles, cancels targeting if attacker shouldnt see victim.
>! Dim AttackerX as Byte
Dim AttackerY as Byte
Dim VictimX as Byte
Dim VictimY as Byte
Dim SlopeX as Byte
Dim SlopeY as Byte
Dim i as Byte
Dim TileX as Long
Dim TileY as Long
Dim Angle as Byte
Dim n as Byte
>! AttackerX = player().x
AttackerY = Player().y
>! If targetType = NPC
VictimX = npc().x
VictimY = npc().y
Else
VictimX = player().x
VictimY = player().y
End If
>! 'get the slope
SlopeX = VictimX - PlayerX
SlopeY - VIctimY - PlayerY
>! 'get how often we change on Y axis
Angle = SlopeX / SlopeY
'Round Angle to nearest Integer.
'Set our Y axis counter up
n = 0
>! If AttackerX < VictimX Then
For i = AttackerX to VictimX Step +1
If AttackerY < VictimY then
TileX = i
n=n+1
If n => Angle then
TileY = TileY+1
End If
If Tile(TileX, TileY).Attribute = Block then
CanTarget=False
Exit Function
End If
End If
If AttackerY > VictimY then
TileX = i
n=n+1
If n => Angle then
TileY = TileY-1
End If
If Tile(TileX, TileY).Attribute = Block then
CanTarget=False
Exit Function
End If
End If
Next i
End If
>! If AttackerX > VictimX Then
For i = AttackerX to VictimX Step -1
If AttackerY < VictimY then
TileX = i
n=n+1
If n => Angle then
TileY = TileY+1
End If
If Tile(TileX, TileY).Attribute = Block then
CanTarget=False
Exit Function
End If
End If
If AttackerY > VictimY then
TileX = i
n=n+1
If n => Angle then
TileY = TileY-1
End If
If Tile(TileX, TileY).Attribute = Block then
CanTarget=False
Exit Function
End If
End If
Next i
End If

If anyone has any input on if this might work or any obvious reason why it wont please let me know.
I need to sleep before i try and code it.
:P
Link to comment
Share on other sites

So from what I can get from this the player has a pre-defined sight range, lets say 3 tiles for this example. You then want to check whether the player is within that range?

```
Public Function CanTarget(ByVal Index as Long, ByVal NPCNum as Long) As Boolean
Dim pX As Long, pY as Long 'Player coords
Dim nX As Long, nY As Long 'npc coords
Dim Dist As Long 'Diagonal distance
Dim LoopX As Long, LoopY As Long
Dim Angle As Byte

pX = Player(index).x
pY = Player(index).y

nX = npc(NPCNum).x
nY = npc(NPCNum).y

'2D Pythagoras
Dist = ((nX - pX) ^ 2) + ((nY - pY) ^ 2)

Dist = (Dist) ^ 1/2

'Check distance
If Dist > 3 Then
CanTarget = False
Exit Function
Else
CanTarget = True
Exit Function
End If

'Check Blocks

If nX > pX Then
Angle = Math.Tan((nX - pX) / (nY - pY))

For LoopX = pX to nX
If Math.Tan((nX - LoopX) / (nY - LoopY)) > Angle Then
LoopY = LoopY + 1
End If

'Check the tile

If Map(MapNum).Tile(LoopX, LoopY) = TILE_TYPE_BLOCKED Then
CanTarget = False
Exit Function
End If
Next

ElseIf pX > nX Then
Angle = Math.Tan((pX - nX) / (pY - nY))

For LoopX = pX to nX Step -1
If Math.Tan((nX - LoopX) / (nY - LoopY)) > Angle Then
LoopY = LoopY - 1
End If

'Check the tile

If Map(MapNum).Tile(LoopX, LoopY) = TILE_TYPE_BLOCKED Then
CanTarget = False
Exit Function
End If
Next

End If

End Function
```
Just a quick write-up I did. You don't need to worry about negatives as the squares take them out.  :P

If there are any problems, just send me a PM.

EDIT: Ok, the updated version is above, which includes tile checking which I had forgotten earlier. My maths on it may be a little dodgy, so I would suggest looking over that bit before you do anything with it. :P
Link to comment
Share on other sites

Yeah I realized some issues with mine overnight. Looks like you may have sorted them out.
I didnt think it would work without considering negatives but i se eyou used a math.tan function… so that might help LOL.
Ill give it a try as soon as possible.

Thanks!
Link to comment
Share on other sites

I think i worked out most of the kinks.
This is the wall i hit though.

Looks Like it needs to add my Y to that variable. Not sure yet.
(Just thought I would post these while thinking it out…)

My version so far...

>! Public Function CanPlayerTargetNPC(ByVal Index As Long, ByVal NPCNum As Long) As Boolean
    Dim pX As Long, pY As Long 'Player coords
    Dim nX As Long, nY As Long 'npc coords
    Dim Dist As Long 'Diagonal distance
    Dim LoopX As Long, LoopY As Long
    Dim Angle As Long
>!     pX = Player(Index).x
    pY = Player(Index).y
>!     nX = MapNpc(GetPlayerMap(Index)).Npc(NPCNum).x
    nY = MapNpc(GetPlayerMap(Index)).Npc(NPCNum).y
>!     '2D Pythagoras
    Dist = ((nX - pX) ^ 2) + ((nY - pY) ^ 2)
>!     Dist = ((Dist) ^ 1 / 2) / 32
    'Check distance
    If Dist > Item(GetPlayerEquipment(Index, Weapon)).AttackRange Then
        Call PlayerMsg(Index, "They are too far away!", BrightRed)
        CanPlayerTargetNPC = False
        Exit Function
    Else
        CanPlayerTargetNPC = True
    End If
>!     'Check Blocks
    If nX > pX Then
        Angle = Math.Tan((nX - pX) / ((nY - pY)))
>!         For LoopX = pX To nX
            If Math.Tan((nX - LoopX) / (nY - LoopY)) > Angle Then
                LoopY = LoopY + 1
            End If

            'Check the tile
>!             If Map(GetPlayerMap(Index)).Tile(LoopX, LoopY).Type = TILE_TYPE_BLOCKED Then
                CanPlayerTargetNPC = False
                Call PlayerMsg(Index, "There was a wall 1!", BrightRed)
                Exit Function
            End If
        Next
>!     ElseIf pX > nX Then
        Angle = Math.Tan((pX - nX) / (pY - nY))
>!         For LoopX = pX To nX Step -1
            If Math.Tan((nX - LoopX) / (nY - LoopY)) > Angle Then
                LoopY = LoopY - 1
            End If

            'Check the tile
>!             If Map(GetPlayerMap(Index)).Tile(LoopX, (LoopY + nX)).Type = TILE_TYPE_BLOCKED Then
                CanPlayerTargetNPC = False
                Call PlayerMsg(Index, "There was a wall 2!", BrightRed)
                Exit Function
            End If
        Next
>!     End If
>! End Function
Link to comment
Share on other sites

ok. I finally got this working perfectly!!!
It requires alot of work even when based off of this but it was a good start none the less.

Hints to those trying it.
1:Trig(aka triangle math) doesnt work when using a straight line(duh).
2:Make each check work towards a false result with exit and set to true before the end.
3:For distances less than 3 you tend to get overflow errors without a work around.
Link to comment
Share on other sites

Found a bug with this still.
In situations where :
```
Angle = Math.Tan((nX - pX) / (pY - nY))
```is basically this:
```
Angle = Math.Tan((2X)/(1X))
```You get an overflow error.

I though rounding to the neared 6th decimal space would help but it didnt.
Any ideas?

I guess i could add a check where If A = (B/2) then do everything based on moving +/-1 by +/-1 but that would be pretty sloppy…
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...