|
|
@ -31,6 +31,8 @@ namespace SemiColinGames { |
|
|
|
// centered at that point and extending out by halfSize.X and halfSize.Y.
|
|
|
|
private Point position = new Point(64, 16 * 13); |
|
|
|
private Vector2 halfSize = new Vector2(11, 24); |
|
|
|
private Vector2 eyeOffsetStanding = new Vector2(7, -14); |
|
|
|
private Vector2 eyeOffsetWalking = new Vector2(15, -7); |
|
|
|
|
|
|
|
private int jumps = 0; |
|
|
|
private Facing facing = Facing.Right; |
|
|
@ -70,7 +72,7 @@ namespace SemiColinGames { |
|
|
|
new Vector2(halfSize.X + Math.Abs(movement.X) + 1, halfSize.Y + Math.Abs(movement.Y) + 1)); |
|
|
|
foreach (var box in collisionTargets) { |
|
|
|
if (box.Intersect(largeBox) != null) { |
|
|
|
Debug.AddRect(box, Color.Green); |
|
|
|
// Debug.AddRect(box, Color.Green);
|
|
|
|
candidates.Add(box); |
|
|
|
} |
|
|
|
} |
|
|
@ -121,10 +123,10 @@ namespace SemiColinGames { |
|
|
|
if (standingOnGround) { |
|
|
|
jumps = 1; |
|
|
|
ySpeed = -0.0001f; |
|
|
|
Debug.AddRect(Box(position), Color.Cyan); |
|
|
|
// Debug.AddRect(Box(position), Color.Cyan);
|
|
|
|
} else { |
|
|
|
jumps = 0; |
|
|
|
Debug.AddRect(Box(position), Color.Orange); |
|
|
|
// Debug.AddRect(Box(position), Color.Orange);
|
|
|
|
} |
|
|
|
|
|
|
|
if (movement.X > 0) { |
|
|
@ -145,6 +147,92 @@ namespace SemiColinGames { |
|
|
|
} else { |
|
|
|
pose = Pose.Standing; |
|
|
|
} |
|
|
|
|
|
|
|
DrawSightLines(collisionTargets); |
|
|
|
} |
|
|
|
|
|
|
|
Vector2 Rotate(Vector2 point, float angle) { |
|
|
|
float cos = FMath.Cos(angle); |
|
|
|
float sin = FMath.Sin(angle); |
|
|
|
return new Vector2( |
|
|
|
point.X * cos - point.Y * sin, |
|
|
|
point.Y * cos + point.X * sin); |
|
|
|
} |
|
|
|
|
|
|
|
bool PointInCone( |
|
|
|
float visionRangeSq, float fovCos, Vector2 eyePos, Vector2 direction, Vector2 test) { |
|
|
|
Vector2 delta = Vector2.Subtract(test, eyePos); |
|
|
|
if (delta.LengthSquared() > visionRangeSq) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
float dot = Vector2.Dot(Vector2.Normalize(direction), Vector2.Normalize(delta)); |
|
|
|
return dot > fovCos; |
|
|
|
} |
|
|
|
|
|
|
|
void DrawSightLines(AABB[] collisionTargets) { |
|
|
|
float fov = FMath.DegToRad(45); |
|
|
|
float fovCos = FMath.Cos(fov); |
|
|
|
Color color = Color.LightYellow; |
|
|
|
|
|
|
|
Vector2 eyeOffset = pose == Pose.Walking ? eyeOffsetWalking : eyeOffsetStanding; |
|
|
|
Vector2 eyePos = Vector2.Add( |
|
|
|
Position.ToVector2(), new Vector2(eyeOffset.X * (int) facing, eyeOffset.Y)); |
|
|
|
|
|
|
|
float visionRange = 150; |
|
|
|
float visionRangeSq = visionRange * visionRange; |
|
|
|
Vector2 ray = new Vector2(visionRange * (int) facing, 0); |
|
|
|
Vector2 coneBottom = Rotate(ray, fov); |
|
|
|
Vector2 coneTop = Rotate(ray, -fov); |
|
|
|
|
|
|
|
List<Vector2> points = new List<Vector2>(); |
|
|
|
List<AABB> boxes = new List<AABB>(); |
|
|
|
points.Add(Vector2.Add(eyePos, coneBottom)); |
|
|
|
points.Add(Vector2.Add(eyePos, coneTop)); |
|
|
|
foreach (AABB box in collisionTargets) { |
|
|
|
int hitCount = points.Count; |
|
|
|
if (PointInCone(visionRangeSq, fovCos, eyePos, ray, box.TopLeft)) { |
|
|
|
points.Add(box.TopLeft); |
|
|
|
} |
|
|
|
if (PointInCone(visionRangeSq, fovCos, eyePos, ray, box.TopRight)) { |
|
|
|
points.Add(box.TopRight); |
|
|
|
} |
|
|
|
if (PointInCone(visionRangeSq, fovCos, eyePos, ray, box.BottomLeft)) { |
|
|
|
points.Add(box.BottomLeft); |
|
|
|
} |
|
|
|
if (PointInCone(visionRangeSq, fovCos, eyePos, ray, box.BottomRight)) { |
|
|
|
points.Add(box.BottomRight); |
|
|
|
} |
|
|
|
if (points.Count > hitCount) { |
|
|
|
boxes.Add(box); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
HashSet<AABB> boxesSeen = new HashSet<AABB>(); |
|
|
|
foreach (Vector2 hit in points) { |
|
|
|
float minTime = 1; |
|
|
|
AABB? closestBox = null; |
|
|
|
Vector2 delta = Vector2.Subtract(hit, eyePos); |
|
|
|
foreach (AABB box in boxes) { |
|
|
|
Hit? maybeHit = box.IntersectSegment(eyePos, delta); |
|
|
|
if (maybeHit != null && maybeHit.Value.Time < minTime) { |
|
|
|
minTime = maybeHit.Value.Time; |
|
|
|
closestBox = box; |
|
|
|
} |
|
|
|
} |
|
|
|
if (closestBox != null) { |
|
|
|
Vector2 target = Vector2.Add(eyePos, Vector2.Multiply(delta, minTime)); |
|
|
|
Debug.AddLine(eyePos, target, color); |
|
|
|
boxesSeen.Add(closestBox.Value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
foreach (AABB box in boxesSeen) { |
|
|
|
Debug.AddRect(box, color); |
|
|
|
} |
|
|
|
|
|
|
|
Debug.AddLine(eyePos, Vector2.Add(eyePos, ray), Color.Red); |
|
|
|
Debug.AddLine(eyePos, Vector2.Add(eyePos, coneTop), Color.Red); |
|
|
|
Debug.AddLine(eyePos, Vector2.Add(eyePos, coneBottom), Color.Red); |
|
|
|
} |
|
|
|
|
|
|
|
// Returns the desired (dx, dy) for the player to move this frame.
|
|
|
|