shadowwulf Posted April 19, 2011 Author Share Posted April 19, 2011 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 target3b: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 ByteDim AttackerY as ByteDim VictimX as ByteDim VictimY as ByteDim SlopeX as ByteDim SlopeY as ByteDim i as ByteDim TileX as LongDim TileY as LongDim Angle as ByteDim n as Byte>! AttackerX = player().xAttackerY = Player().y>! If targetType = NPCVictimX = npc().xVictimY = npc().yElseVictimX = player().xVictimY = player().yEnd If>! 'get the slopeSlopeX = VictimX - PlayerXSlopeY - VIctimY - PlayerY>! 'get how often we change on Y axisAngle = SlopeX / SlopeY'Round Angle to nearest Integer.'Set our Y axis counter upn = 0>! If AttackerX < VictimX ThenFor i = AttackerX to VictimX Step +1If AttackerY < VictimY thenTileX = in=n+1If n => Angle thenTileY = TileY+1End IfIf Tile(TileX, TileY).Attribute = Block thenCanTarget=FalseExit FunctionEnd IfEnd IfIf AttackerY > VictimY thenTileX = in=n+1If n => Angle thenTileY = TileY-1End IfIf Tile(TileX, TileY).Attribute = Block thenCanTarget=FalseExit FunctionEnd IfEnd IfNext iEnd If>! If AttackerX > VictimX ThenFor i = AttackerX to VictimX Step -1If AttackerY < VictimY thenTileX = in=n+1If n => Angle thenTileY = TileY+1End IfIf Tile(TileX, TileY).Attribute = Block thenCanTarget=FalseExit FunctionEnd IfEnd IfIf AttackerY > VictimY thenTileX = in=n+1If n => Angle thenTileY = TileY-1End IfIf Tile(TileX, TileY).Attribute = Block thenCanTarget=FalseExit FunctionEnd IfEnd IfNext iEnd 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 More sharing options...
Yxxe Posted April 19, 2011 Share Posted April 19, 2011 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 IfEnd Function```Just a quick write-up I did. You don't need to worry about negatives as the squares take them out. :PIf 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 More sharing options...
shadowwulf Posted April 19, 2011 Author Share Posted April 19, 2011 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 More sharing options...
shadowwulf Posted April 20, 2011 Author Share Posted April 20, 2011 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 More sharing options...
Yxxe Posted April 20, 2011 Share Posted April 20, 2011 You'll need to define a number for LoopY before you start looping with LoopX. Set LoopY to the Y coordinate of the player. Link to comment Share on other sites More sharing options...
shadowwulf Posted April 23, 2011 Author Share Posted April 23, 2011 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 More sharing options...
shadowwulf Posted April 24, 2011 Author Share Posted April 24, 2011 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 More sharing options...
shadowwulf Posted April 24, 2011 Author Share Posted April 24, 2011 ~Bump~~~Anyone know?If i can get this error to go away I might release me completed sub(which works for player vs player also)~~Resolved. had to edit a data type. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now