private static void IterateLineOfSightBodies(Vector2 at, float radius, Predicate<RigidBody> affectsObject, LineOfSightCallback callback) { // Iterate over all RigidBodies in the area List<RigidBody> nearBodies = RigidBody.QueryRectGlobal(at - new Vector2(radius, radius), new Vector2(radius, radius) * 2); foreach (RigidBody body in nearBodies) { if (body.WorldMassCenter == at) continue; if (!affectsObject(body)) continue; Vector2 bodyPos = body.WorldMassCenter; Vector2 bodyDir = (bodyPos - at).Normalized; Vector2 maxRadiusPos = at + bodyDir * radius; // Perform a raycast to find out whether the current body has a direct line of sight to the center RayCastData firstHit; bool hitAnything = RigidBody.RayCast(at, maxRadiusPos, d => { // Clip the cast ray if (d.Body == body) return d.Fraction; else if (d.Body.BodyType != BodyType.Static || d.Shape.IsSensor || !affectsObject(d.Body)) return -1.0f; else return d.Fraction; }, out firstHit); // If the current body is really the first one to be hit, push it away if (hitAnything && firstHit.Body == body) { callback(body, firstHit); } } }
private static void IterateLineOfSightBodies(Vector2 at, float radius, Predicate <RigidBody> affectsObject, LineOfSightCallback callback) { // Iterate over all RigidBodies in the area List <RigidBody> nearBodies = new List <RigidBody>(); RigidBody.QueryRectGlobal( at - new Vector2(radius, radius), new Vector2(radius, radius) * 2, nearBodies); foreach (RigidBody body in nearBodies) { if (body.WorldMassCenter == at) { continue; } if (!affectsObject(body)) { continue; } Vector2 bodyPos = body.WorldMassCenter; Vector2 bodyDir = (bodyPos - at).Normalized; Vector2 maxRadiusPos = at + bodyDir * radius; // Perform a raycast to find out whether the current body has a direct line of sight to the center RayCastData firstHit; bool hitAnything = RigidBody.RayCast(at, maxRadiusPos, d => { // Clip the cast ray if (d.Body == body) { return(d.Fraction); } else if (d.Body.BodyType != BodyType.Static || d.Shape.IsSensor || !affectsObject(d.Body)) { return(-1.0f); } else { return(d.Fraction); } }, out firstHit); // If the current body is really the first one to be hit, push it away if (hitAnything && firstHit.Body == body) { callback(body, firstHit); } } }