Cone-View Question

Discussion in 'Plugin Development' started by TheHandfish, Jun 24, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    TheHandfish

    Hi,

    I'm designing a plugin that has to do with whether or not the player can see other players. This does not me if his crosshair is over the player, it means if anywhere on the screen a player can be seen. I'm thinking I'll need to make some kind of cone that extends out (probably really far). I did do some Googling, and I did find a few methods, such as this one:

    Code:Java
    1.  
    2.  
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import org.bukkit.Location;
    6. import org.bukkit.entity.Player;
    7.  
    8. public class Cone
    9. {
    10. public static List<Player> getPlayersInCone(List<Player> players, Location startLoc, int radius, int degrees, int direction)
    11. {
    12. List<Player> newPlayers = new ArrayList<>();
    13.  
    14. int[] startPos = new int[] { (int)startLoc.getX(), (int)startLoc.getZ() };
    15.  
    16. int[] endA = new int[] { (int)(radius * Math.cos(direction - (degrees/2))), (int)(radius * Math.sin(direction - (degrees/2))) };
    17. int[] endB = new int[] { (int)(radius * Math.cos(direction + (degrees/2))), (int)(radius * Math.sin(direction + (degrees/2))) };
    18.  
    19. for(Player p :players) {
    20. Location l = p.getLocation();
    21. if (!isPointInCircle(startPos[0], startPos[1], radius, l.getBlockX(), l.getBlockZ())) {
    22. continue;
    23. }
    24. int [] playerVector = getVectorForPoints(startPos[0], startPos[1], l.getBlockX(), l.getBlockZ());
    25.  
    26. double angle = getAngleBetweenVectors(endA, playerVector) + getAngleBetweenVectors(endB, playerVector);
    27. if (Math.abs(angle) * 10 - 2 < degrees) {
    28. newPlayers.add(p);
    29. }
    30. }
    31. return newPlayers;
    32. }
    33.  
    34.  
    35. private static boolean isPointInCircle(int cx, int cy, int radius, int px, int py)
    36. {
    37. double dist = (px-cx)^2 + (py-cy)^2;
    38. return dist < (radius^2);
    39. }
    40.  
    41. private static int[] getVectorForPoints(int x1, int y1, int x2, int y2)
    42. {
    43. return new int[]
    44. {
    45. Math.abs(x2-x1), Math.abs(y2-y1)
    46. };
    47. }
    48.  
    49. private static double getAngleBetweenVectors(int[] vector1, int[] vector2)
    50. {
    51. return Math.atan2(vector2[1], vector2[0]) - Math.atan2(vector1[1], vector1[0]);
    52. }
    53.  
    54. }


    I tried this:

    Code:text
    1. public List<Player> getPlayersInCone(Player p)
    2. {
    3. List<Player> players = null;
    4. for(Entity e : p.getNearbyEntities(Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16))
    5. {
    6. if(e instanceof Player && !e.equals(p))
    7. {
    8. players.add((Player) e);
    9. }
    10. }
    11. return Cone.getPlayersInCone(players, p.getLocation(), Bukkit.getViewDistance(), p.getLocation().getYaw());
    12. }
    13.  

    I get the feeling I have no clue what I'm doing, so I don't bother testing it. So, question: Is this a good way to do it? Am I doing it wrong?
    Is there a better way to do it?
     
  2. Offline

    fireblast709

    TheHandfish Isn't it easier to just take the Vector from your location to the other, and the direction Vector. Then just normalize both and use the dot product, which will give you the cosine of the angle between the cursor and the player
     
    jthort likes this.
  3. Offline

    TheHandfish

    fireblast709: So, would it be something like:

    Code:java
    1.  
    2. public List<Player> getPlayersInCone(Player p)
    3. {
    4. ArrayList<Player> players = new ArrayList<>();
    5. for(Entity e : p.getNearbyEntities(Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16))
    6. {
    7. if(e instanceof Player && !e.equals(p))
    8. {
    9. players.add((Player) e);
    10. }
    11. }
    12.  
    13. List<Player> toreturn = null;
    14.  
    15. for(Player near : players)
    16. {
    17. Vector tovec = near.getLocation().toVector().normalize();
    18. Vector dir = near.getLocation().getDirection().normalize();
    19.  
    20. double dotproduct = tovec.dot(dir);
    21. }
    22.  
    23. return toreturn;
    24. }
    25.  

    Does this look right so far? What else should I do? (I'm not awesome with Vectors x_x)
     
  4. Offline

    fireblast709

    TheHandfish subtract near's location with p's location, and use p's direction
     
  5. Offline

    TheHandfish

    fireblast709:

    Code:text
    1. Location prod = near.getLocation().subtract(p.getLocation());
    2.  

    How do you mean "use P's direction?"

    EDIT: Or more like:

    Code:java
    1. prod = near.getLocation().subtract(p.getLocation()).toVector().normalize().dot(p.getLocation().getDirection().normalize());
    2.  


    UPDATE:

    Never mind, figured it out.

    Code:java
    1. public HashMap<LivingEntity, Double> leVector(Player p)
    2. {
    3. ArrayList<LivingEntity> living = new ArrayList<>(); // This is where we'll save all the living entities that are nearby.
    4. for(Entity e : p.getNearbyEntities(Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16, Bukkit.getViewDistance() * 16))
    5. {
    6. if(e instanceof LivingEntity && !e.equals(p))
    7. {
    8. living.add((LivingEntity) e);
    9. }
    10. }
    11.  
    12.  
    13. HashMap<LivingEntity, Double> toreturn = new HashMap<>(); // This is where we'll save
    14.  
    15. for(LivingEntity near : living)
    16. {
    17. /*Vector tovec = near.getLocation().toVector().normalize();
    18.   Vector dir = near.getLocation().getDirection().normalize();
    19.  
    20.   double dotproduct = tovec.dot(dir);
    21.   mab = Math.abs(dotproduct);*/
    22. double prod = Math.abs(near.getLocation().subtract(p.getLocation()).toVector().normalize().dot(p.getLocation().getDirection().normalize()));
    23. toreturn.put(near, prod);
    24. }
    25.  
    26. return toreturn;
    27. }


    Thanks for the help!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  6. Offline

    blablubbabc

    Keep in mind that clients can theoretically use different field of views.

    You can check if the other player is behind the player by checking if the dot product between the players view direction and the normalized vector towards the other player is smaller than zero:
    Vector viewDirection = player.getDirection();
    Vector direction = otherPlayer.getLocation().subtract(player.getLocation()).toVector().normalize();
    if (viewDirection.dot(direction) > 0)
    { /* otherPlayer is somwhere in front of the player */ }
     
  7. Offline

    TheHandfish

    Thanks! My solution works pretty well, and keep in mind, all that really matters (to me) is if the character himself can see others, not the person controlling him.

    I was looking for a way to force first-person view but I don't think that is server-side.
     
  8. Offline

    fireblast709

    Which is pretty much where I ninja'd you in the first reply I gave :3
     
    TheHandfish likes this.
Thread Status:
Not open for further replies.

Share This Page