Hey there!
I’ve run into a rather simple still puzzling problem in my game. In my tilebased game, I need the enemies to look for the player’s units at intervals, to seek targets.
I currently do this by (per player-controlled unit) dividing the distance between the enemy and the unit into a list of points, and checking if any of the points are occupied by f.ex a wall. If so, the trace returns false (sight impared), otherwise true (clear view).
http://81.216.242.88/misc/method1.png
My second idea is to calculate the angle of the “line” between enemy and unit, then for each object that is an obstacle, calculate the angles of each corner against the enemy coordinate.
If all of the corner’s angles are less, or more than, the angle of the “line”, the obstacle is outside the line of sight, if they differ… the obstacle is in the line of sight.
http://81.216.242.88/misc/method2.png
Problem is if angles are calculated to be negative and are wrapped positive, angles which would differ are suddenly on the same “side” of the line.
The second approach appear significantly faster, but if I can’t fix my problem it’s not much use. Help would be much appreciated.
Posting source to help explain my algoritm;
public boolean trace(Coord coord1, Coord coord2) {
double angle = CommonMath.angle(coord1.x, coord1.y, coord2.x, coord2.y);
double distance = CommonMath.distance(coord1, coord2);
List<Thing> list = main.getThingHandler().getList();
Coord coord3;
for (Thing thing : list) {
if (thing.isObstacle()) {
coord3 = thing.getCoord();
if (CommonMath.distance(coord1, coord3) > distance) continue;
/*
* Retrieve angles for each of the obstacles corners
*/
double angle1 = CommonMath.angle(coord1.x, coord1.y, coord3.x - 0.5, coord3.y - 0.5);
double angle2 = CommonMath.angle(coord1.x, coord1.y, coord3.x + 0.5, coord3.y - 0.5);
double angle3 = CommonMath.angle(coord1.x, coord1.y, coord3.x - 0.5, coord3.y + 0.5);
double angle4 = CommonMath.angle(coord1.x, coord1.y, coord3.x + 0.5, coord3.y + 0.5);
/*
* Which side of the line of sight are we on?
*/
boolean rel1 = angle1 < angle;
boolean rel2 = angle2 < angle;
boolean rel3 = angle3 < angle;
boolean rel4 = angle4 < angle;
/*
* Are all of the corners on the same side of the line of sight?
*/
if ((rel1 != rel2) || (rel2 != rel3) || (rel3 != rel4)) {
return false;
}
}
}
return true;
}
