rename Aabb -> AABB
GitOrigin-RevId: 37b49d7a3ff2b4d0cf3e14e4339316bc72e2785e
This commit is contained in:
parent
f78bff249c
commit
57b65f559c
@ -68,7 +68,7 @@ namespace SemiColinGames {
|
|||||||
rects.Add(new DebugRect(rect, color));
|
rects.Add(new DebugRect(rect, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddRect(Aabb box, Color color) {
|
public static void AddRect(AABB box, Color color) {
|
||||||
Rectangle rect = new Rectangle(
|
Rectangle rect = new Rectangle(
|
||||||
(int) (box.Position.X - box.HalfSize.X), (int) (box.Position.Y - box.HalfSize.Y),
|
(int) (box.Position.X - box.HalfSize.X), (int) (box.Position.Y - box.HalfSize.Y),
|
||||||
(int) (box.HalfSize.X * 2), (int) (box.HalfSize.Y * 2));
|
(int) (box.HalfSize.X * 2), (int) (box.HalfSize.Y * 2));
|
||||||
|
@ -6,17 +6,17 @@ using System;
|
|||||||
namespace SemiColinGames {
|
namespace SemiColinGames {
|
||||||
|
|
||||||
public readonly struct Hit {
|
public readonly struct Hit {
|
||||||
public readonly Aabb Collider;
|
public readonly AABB Collider;
|
||||||
public readonly Vector2 Position;
|
public readonly Vector2 Position;
|
||||||
public readonly Vector2 Delta;
|
public readonly Vector2 Delta;
|
||||||
public readonly Vector2 Normal;
|
public readonly Vector2 Normal;
|
||||||
public readonly float Time; // ranges from [0, 1].
|
public readonly float Time; // ranges from [0, 1].
|
||||||
|
|
||||||
public Hit(Aabb collider, Vector2 position, Vector2 delta, Vector2 normal) :
|
public Hit(AABB collider, Vector2 position, Vector2 delta, Vector2 normal) :
|
||||||
this(collider, position, delta, normal, 0.0f) {
|
this(collider, position, delta, normal, 0.0f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hit(Aabb collider, Vector2 position, Vector2 delta, Vector2 normal, float time) {
|
public Hit(AABB collider, Vector2 position, Vector2 delta, Vector2 normal, float time) {
|
||||||
Collider = collider;
|
Collider = collider;
|
||||||
Position = position;
|
Position = position;
|
||||||
Delta = delta;
|
Delta = delta;
|
||||||
@ -37,7 +37,7 @@ namespace SemiColinGames {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct Aabb {
|
public readonly struct AABB {
|
||||||
public readonly Vector2 Position; // centroid
|
public readonly Vector2 Position; // centroid
|
||||||
public readonly Vector2 HalfSize;
|
public readonly Vector2 HalfSize;
|
||||||
|
|
||||||
@ -51,12 +51,12 @@ namespace SemiColinGames {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Aabb(Vector2 position, Vector2 halfSize) {
|
public AABB(Vector2 position, Vector2 halfSize) {
|
||||||
Position = position;
|
Position = position;
|
||||||
HalfSize = halfSize;
|
HalfSize = halfSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hit? Intersect(Aabb box) {
|
public Hit? Intersect(AABB box) {
|
||||||
float dx = box.Position.X - Position.X;
|
float dx = box.Position.X - Position.X;
|
||||||
float px = box.HalfSize.X + HalfSize.X - Math.Abs(dx);
|
float px = box.HalfSize.X + HalfSize.X - Math.Abs(dx);
|
||||||
if (px <= 0) {
|
if (px <= 0) {
|
||||||
@ -121,7 +121,7 @@ namespace SemiColinGames {
|
|||||||
return new Hit(this, hitPos, hitDelta, normal, hitTime);
|
return new Hit(this, hitPos, hitDelta, normal, hitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sweep Sweep(Aabb box, Vector2 delta) {
|
public Sweep Sweep(AABB box, Vector2 delta) {
|
||||||
// fast-path case if the other box is static
|
// fast-path case if the other box is static
|
||||||
if (delta.X == 0 && delta.Y == 0) {
|
if (delta.X == 0 && delta.Y == 0) {
|
||||||
Hit? staticHit = Intersect(box);
|
Hit? staticHit = Intersect(box);
|
||||||
|
@ -46,25 +46,26 @@ namespace SemiColinGames {
|
|||||||
|
|
||||||
public Point Position { get { return position; } }
|
public Point Position { get { return position; } }
|
||||||
|
|
||||||
public void Update(float modelTime, History<Input> input, Aabb[] collisionTargets) {
|
public void Update(float modelTime, History<Input> input, AABB[] collisionTargets) {
|
||||||
Aabb BoxOffset(Point position, int yOffset) {
|
AABB BoxOffset(Point position, int yOffset) {
|
||||||
return new Aabb(new Vector2(position.X, position.Y + yOffset), halfSize);
|
return new AABB(new Vector2(position.X, position.Y + yOffset), halfSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Aabb Box(Point position) {
|
AABB Box(Point position) {
|
||||||
return BoxOffset(position, 0);
|
return BoxOffset(position, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 movement = HandleInput(modelTime, input);
|
Vector2 movement = HandleInput(modelTime, input);
|
||||||
|
|
||||||
// Broad test: remove all collision targets nowhere near the player.
|
// Broad test: remove all collision targets nowhere near the player.
|
||||||
var candidates = new List<Aabb>();
|
// TODO: don't allocate a list here.
|
||||||
|
var candidates = new List<AABB>();
|
||||||
// Expand the box in the direction of movement. The center is the midpoint of the line
|
// Expand the box in the direction of movement. The center is the midpoint of the line
|
||||||
// between the player's current position and their desired movement. The width increases by
|
// between the player's current position and their desired movement. The width increases by
|
||||||
// the magnitude of the movement in each direction. We add 1 to each dimension just to be
|
// the magnitude of the movement in each direction. We add 1 to each dimension just to be
|
||||||
// sure (the only downside is a small number of false-positive AABBs, which should be
|
// sure (the only downside is a small number of false-positive AABBs, which should be
|
||||||
// discarded by later tests anyhow.)
|
// discarded by later tests anyhow.)
|
||||||
Aabb largeBox = new Aabb(
|
AABB largeBox = new AABB(
|
||||||
new Vector2(position.X + movement.X / 2, position.Y + movement.Y / 2),
|
new Vector2(position.X + movement.X / 2, position.Y + movement.Y / 2),
|
||||||
new Vector2(halfSize.X + Math.Abs(movement.X) + 1, halfSize.Y + Math.Abs(movement.Y) + 1));
|
new Vector2(halfSize.X + Math.Abs(movement.X) + 1, halfSize.Y + Math.Abs(movement.Y) + 1));
|
||||||
foreach (var box in collisionTargets) {
|
foreach (var box in collisionTargets) {
|
||||||
@ -80,7 +81,7 @@ namespace SemiColinGames {
|
|||||||
int dy = movePoints[i].Y - movePoints[i - 1].Y;
|
int dy = movePoints[i].Y - movePoints[i - 1].Y;
|
||||||
if (dy != 0) {
|
if (dy != 0) {
|
||||||
Point newPosition = new Point(position.X, position.Y + dy);
|
Point newPosition = new Point(position.X, position.Y + dy);
|
||||||
Aabb player = Box(newPosition);
|
AABB player = Box(newPosition);
|
||||||
bool reject = false;
|
bool reject = false;
|
||||||
foreach (var box in candidates) {
|
foreach (var box in candidates) {
|
||||||
if (box.Intersect(player) != null) {
|
if (box.Intersect(player) != null) {
|
||||||
@ -94,7 +95,7 @@ namespace SemiColinGames {
|
|||||||
}
|
}
|
||||||
if (dx != 0) {
|
if (dx != 0) {
|
||||||
Point newPosition = new Point(position.X + dx, position.Y);
|
Point newPosition = new Point(position.X + dx, position.Y);
|
||||||
Aabb player = Box(newPosition);
|
AABB player = Box(newPosition);
|
||||||
bool reject = false;
|
bool reject = false;
|
||||||
foreach (var box in candidates) {
|
foreach (var box in candidates) {
|
||||||
if (box.Intersect(player) != null) {
|
if (box.Intersect(player) != null) {
|
||||||
@ -109,7 +110,7 @@ namespace SemiColinGames {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool standingOnGround = false;
|
bool standingOnGround = false;
|
||||||
Aabb groundIntersect = BoxOffset(position, 1);
|
AABB groundIntersect = BoxOffset(position, 1);
|
||||||
foreach (var box in candidates) {
|
foreach (var box in candidates) {
|
||||||
if (groundIntersect.Intersect(box) != null) {
|
if (groundIntersect.Intersect(box) != null) {
|
||||||
standingOnGround = true;
|
standingOnGround = true;
|
||||||
|
@ -166,21 +166,21 @@ namespace SemiColinGames {
|
|||||||
// Because we added tiles from left to right, the CollisionTargets are sorted by x-position.
|
// Because we added tiles from left to right, the CollisionTargets are sorted by x-position.
|
||||||
// We maintain this invariant so that it's possible to efficiently find CollisionTargets that
|
// We maintain this invariant so that it's possible to efficiently find CollisionTargets that
|
||||||
// are nearby a given x-position.
|
// are nearby a given x-position.
|
||||||
CollisionTargets = new Aabb[tiles.Length + 2];
|
CollisionTargets = new AABB[tiles.Length + 2];
|
||||||
|
|
||||||
// Add a synthetic collisionTarget on the left side of the world.
|
// Add a synthetic collisionTarget on the left side of the world.
|
||||||
CollisionTargets[0] = new Aabb(new Vector2(-1, 0), new Vector2(1, float.MaxValue));
|
CollisionTargets[0] = new AABB(new Vector2(-1, 0), new Vector2(1, float.MaxValue));
|
||||||
|
|
||||||
// Now add all the normal collisionTargets for every static terrain tile.
|
// Now add all the normal collisionTargets for every static terrain tile.
|
||||||
Vector2 halfSize = new Vector2(TileSize / 2, TileSize / 2);
|
Vector2 halfSize = new Vector2(TileSize / 2, TileSize / 2);
|
||||||
for (int i = 0; i < tiles.Length; i++) {
|
for (int i = 0; i < tiles.Length; i++) {
|
||||||
Vector2 center = new Vector2(
|
Vector2 center = new Vector2(
|
||||||
tiles[i].Position.Left + halfSize.X, tiles[i].Position.Top + halfSize.Y);
|
tiles[i].Position.Left + halfSize.X, tiles[i].Position.Top + halfSize.Y);
|
||||||
CollisionTargets[i + 1] = new Aabb(center, halfSize);
|
CollisionTargets[i + 1] = new AABB(center, halfSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a final synthetic collisionTarget on the right side of the world.
|
// Add a final synthetic collisionTarget on the right side of the world.
|
||||||
CollisionTargets[tiles.Length + 1] = new Aabb(
|
CollisionTargets[tiles.Length + 1] = new AABB(
|
||||||
new Vector2(Width + 1, 0), new Vector2(1, float.MaxValue));
|
new Vector2(Width + 1, 0), new Vector2(1, float.MaxValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +190,6 @@ namespace SemiColinGames {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Aabb[] CollisionTargets { get; }
|
public AABB[] CollisionTargets { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ namespace SemiColinGames.Tests {
|
|||||||
public class GeometryTests {
|
public class GeometryTests {
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentNotColliding() {
|
public void TestIntersectSegmentNotColliding() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(8, 8));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8));
|
||||||
Assert.IsNull(box.IntersectSegment(new Vector2(-16, -16), new Vector2(32, 0)));
|
Assert.IsNull(box.IntersectSegment(new Vector2(-16, -16), new Vector2(32, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentHit() {
|
public void TestIntersectSegmentHit() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(8, 8));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8));
|
||||||
var point = new Vector2(-16, 4);
|
var point = new Vector2(-16, 4);
|
||||||
var delta = new Vector2(32, 0);
|
var delta = new Vector2(32, 0);
|
||||||
Hit? maybeHit = box.IntersectSegment(point, delta);
|
Hit? maybeHit = box.IntersectSegment(point, delta);
|
||||||
@ -36,7 +36,7 @@ namespace SemiColinGames.Tests {
|
|||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentFromInsideBox() {
|
public void TestIntersectSegmentFromInsideBox() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(8, 8));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8));
|
||||||
var point = new Vector2(-4, 4);
|
var point = new Vector2(-4, 4);
|
||||||
var delta = new Vector2(32, 0);
|
var delta = new Vector2(32, 0);
|
||||||
Hit? maybeHit = box.IntersectSegment(point, delta);
|
Hit? maybeHit = box.IntersectSegment(point, delta);
|
||||||
@ -59,7 +59,7 @@ namespace SemiColinGames.Tests {
|
|||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentWithPadding() {
|
public void TestIntersectSegmentWithPadding() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(8, 8));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8));
|
||||||
var point = new Vector2(-16, 4);
|
var point = new Vector2(-16, 4);
|
||||||
var delta = new Vector2(32, 0);
|
var delta = new Vector2(32, 0);
|
||||||
int padding = 4;
|
int padding = 4;
|
||||||
@ -83,7 +83,7 @@ namespace SemiColinGames.Tests {
|
|||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentFromTwoDirections() {
|
public void TestIntersectSegmentFromTwoDirections() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(32, 32));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(32, 32));
|
||||||
var farPos = new Vector2(64, 0);
|
var farPos = new Vector2(64, 0);
|
||||||
var farToNearDelta = new Vector2(-32, 0);
|
var farToNearDelta = new Vector2(-32, 0);
|
||||||
Assert.IsNull(box.IntersectSegment(farPos, farToNearDelta));
|
Assert.IsNull(box.IntersectSegment(farPos, farToNearDelta));
|
||||||
@ -95,7 +95,7 @@ namespace SemiColinGames.Tests {
|
|||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentXAxisAligned() {
|
public void TestIntersectSegmentXAxisAligned() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(16, 16));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(16, 16));
|
||||||
var pos = new Vector2(-32, 0);
|
var pos = new Vector2(-32, 0);
|
||||||
var delta = new Vector2(64, 0);
|
var delta = new Vector2(64, 0);
|
||||||
Hit? maybeHit = box.IntersectSegment(pos, delta);
|
Hit? maybeHit = box.IntersectSegment(pos, delta);
|
||||||
@ -110,7 +110,7 @@ namespace SemiColinGames.Tests {
|
|||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestIntersectSegmentYAxisAligned() {
|
public void TestIntersectSegmentYAxisAligned() {
|
||||||
Aabb box = new Aabb(new Vector2(0, 0), new Vector2(16, 16));
|
AABB box = new AABB(new Vector2(0, 0), new Vector2(16, 16));
|
||||||
var pos = new Vector2(0, -32);
|
var pos = new Vector2(0, -32);
|
||||||
var delta = new Vector2(0, 64);
|
var delta = new Vector2(0, 64);
|
||||||
Hit? maybeHit = box.IntersectSegment(pos, delta);
|
Hit? maybeHit = box.IntersectSegment(pos, delta);
|
||||||
|
Loading…
Reference in New Issue
Block a user