AI sight range

how to determine that our player is within the sight range of the AI enemy in JME?

i want to trigger the AI to focus on the player and planning an attack whenever the player is within its sight range

Personally, I would keep your data and rules separate from the scene graph.



Have a service in your code which updates enemy locations and that service updates your scenegraph. The service should be told of the player location and can do the necesary (pythagos / A* / line of sight) calculations needed to see if the enemy will attack your player.



The service will also be used as a facade to the enemy behaviour routine, so each enemy can behave differently.



This design will also allow you to take advantage of multithreading too.






Using a camera frustum is a good idea, once you find the player you can fire a ray from the center toward and see if he's behind any obstacles.

why not for every enemy do the following:

  • create a ray from the enemy to the play
  • if this ray is in the FOV of the enemy then proceed (easy trig. check), otherwise it can't see the player
  • test the ray against the geometry on it's way to the player and see if hits something in between (increase the boundings of the geometry according to the radius of the player)

Couldn't you first check if the player is in the FOV of an enemy

Then cast a ray to each vertex that makes up the siloute of the player (used for casting shadow cubemaps anyway) and check if any of those rays are ocluded.  The only problem with this technique is that its possible that a character's siloute is not a good indicator of the visibility.



For a more accurate but potentially more computationally expensive technique you could use Monte Carlo ray scattering from the enemies eyes onto the player and calculate which rays actually hit the player.  Using this second technique you could even weight them to accurately account for shadow and movement.

@Haladria - In the end I implemented something similar; I fired the ray from the enemy in the direction it was patrolling and made the enemy perform a rotation at the end of the patrol so if player was in FOV it would be discovered.



The problem I found with your original suggestion was that if the player was half behind the wall and the ray would just about avoid obstacle/wall and intersect the player, the enemy would start firing and the bullets would go into the wall and before even player attacked, the enemy would be out of bullets. Also, it would be difficult to rule out every obstacle as you might put that first obstacle as wall(i.e. "if the player is behind wall - do nothing") but if it intersects ammo/med boxes before wall you have to design additional query(i.e. "if the player is behind wall and there is no ammo/med box - do nothing"). This would getting increasingly complex with complex maps!



@walrus - your technique sounds accurate but potentially more expensive both in terms of computation and programming. For advanced users, this might be feasible but for beginners/intermediaries looking to develop a simple FOV for enemy, it would be quite complicated to achieve.

i'll add a small code example for people who have problems with simple math like me :slight_smile:

i guess its really trivial for a lot of people but anyway.




        // get the direction of the player from the enemies point of view
        Vector3f direction = player.getLocalTranslation().subtract(enemy.getLocalTranslation()).normalizeLocal();

        // get the difference between the Enemy's heading direction and the players direction
        Vector3f difference = enemy.getLocalRotation().getRotationColumn(2).subtract(direction);
        System.out.println("i'm heading: " +enemy.getLocalRotation().getRotationColumn(2));
        System.out.println("players is in direction: " +direction);
        System.out.println("difference is: " +difference);
        if (difference.length() < 0.5f) {
            // 2    == 180

If the rotating plane were registered with a collision manager, the resulting number of collisions to look at and make a decision for would be rather high.



The first thing that I would do is implement a distance system that uses 2 arrays, one is for x coordinates, the other for y. Keep them both sorted. A simple 'who is close to me' check can cut down on a large majority of those checks. All  that would be left is obstacle checking. If someone is close enough on either the x or y axis, then check the other players actual distance (x and y together) and see if they are within range / are visible, etc.



Another option is to use an octree to keep track of locations and use it for distance checks. There are implementations of this, but it requires more maintenance in order to keep it correctly resembling the current game state.


JimSlade said:

EDIT: Okay, bust that radar-thing. Divide the map virtually into cubes. Size of the cubes depend on map-style and general sight-range of the map. put every entity that should be visible for any other entity in a List associated to one cube. Cast a ray to every entity in the same cube, check visibility (or obstacles) by using an abstraction like described above and handle cases, where the "seeing" entity is between more than one cube. Done. Or not?


that basically sounds like the concept for an octree