public bool HasCollision(ChunkInfo ci, int x, int y) { Vector2 worldPos = WorldMap.Chunk2World(ci, x, y); Box2D worldBox = new Box2D(worldPos, 0.5f, 0.5f); // Check against any player Box2D playerBox = GameManager.Instance.MainPlayer.Box; return(CollisionCode.TestBox2DBox2D(worldBox, playerBox)); }
public ItemInstance GetItemInstanceFromWorldPos(Vector2 worldPos) { // (O(n)) - No spatial partitioning, will probably be slow when many items are present. foreach (ItemInstance item in ItemManager.Instance) { if (CollisionCode.TestPointBox2D(worldPos, item.Box)) { return(item); } } return(null); }
public Enemy GetEnemyFromWorldPos(Vector2 worldPos) { foreach (Entity entity in EntityManager.Instance.Entities) { Enemy enemy = entity as Enemy; if (enemy && CollisionCode.TestPointBox2D(worldPos, enemy.Box)) { return(enemy); } } return(null); }
private void UpdatePositionInternal(Entity entity, Vector3 oldPosition, ref Vector3 newPosition, int step) { // Figure out sweep area Vector2 oldPosition2D = new Vector2(oldPosition.x, oldPosition.y); Vector2 newPosition2D = new Vector2(newPosition.x, newPosition.y); float mostLeft = Math.Min(oldPosition2D.x, newPosition2D.x) - 0.5f; float mostRight = Math.Max(oldPosition2D.x, newPosition2D.x) + 0.5f; float mostUp = Math.Max(oldPosition2D.y, newPosition2D.y) + 0.5f; float mostDown = Math.Min(oldPosition2D.y, newPosition2D.y) - 0.5f; Vector2 topLeft = new Vector2(mostLeft, mostUp); Vector2 bottomRight = new Vector2(mostRight, mostDown); Box2D sweep = new Box2D(topLeft, bottomRight); Box2D originalBox = new Box2D(oldPosition2D, 0.5f, 0.5f); Box2D endBox = new Box2D(newPosition2D, 0.5f, 0.5f); Vector2 displacement = endBox.Center - originalBox.Center; // now get the list of tiles that we may have encountered during this sweep and return their boxes CollisionInfo[] broadPhase = CollisionCode.BroadPhase(entity, sweep); float bestT = 1.0f; // no collision foreach (CollisionInfo ci in broadPhase) { // now for each collision potential collision, figure out at which 't' we hit the box, return the shortest t in case of multiple collision float tFirst, tLast; bool collide = CollisionCode.IntersectMovingBox2DBox2D(originalBox, ci.Box, displacement, new Vector2(0, 0), out tFirst, out tLast); if (collide) { // Are we allowed to go through ? if ((ci.Flags & CollisionFlags.Wall) == CollisionFlags.Wall) { // hard collision, prevent movement bestT = Mathf.Min(tFirst, bestT); } else { // send OnTouchEvent on Entity // Note: This will probably send multiple Touch events to the same pair. We should accumulate these TouchEvent and then sweep them if we get the bug. Entity entity2 = ci.Entity; // TODO - Since UpdateCollisionInternal is called multiple times per frame, also when checking potential collision detection, we need a way to turn it on and off // to avoid sending false positive, also to avoid sending multiple touches on the same frame if (entity2 != null) { entity.OnTouch(entity2); entity2.OnTouch(entity); } } } } if (bestT < 1.0f) // got at least one collision, reduce wanted velocity { displacement *= bestT; newPosition2D = oldPosition2D + displacement; } if (bestT >= 0.999) { newPosition.x = newPosition2D.x; newPosition.y = newPosition2D.y; } else if (step < 5) { // we were at oldPosition, we wanted to go at newPosition, we are currently stuck at newPosition2D // if displacement was on a single-axis, forget it, there's nothing we do can Vector3 wantedDisplacement = newPosition - oldPosition; if (Mathf.Abs(wantedDisplacement.x) <= 0.001 || Mathf.Abs(wantedDisplacement.y) <= 0.001) //if (true) { newPosition.x = newPosition2D.x; newPosition.y = newPosition2D.y; } else { Vector3 subOldPosition = new Vector3(newPosition2D.x, newPosition2D.y, 0.0f); Vector3 subNewPositionInX = newPosition; subNewPositionInX.y = subOldPosition.y; Vector3 subNewPositionInY = newPosition; subNewPositionInY.x = subOldPosition.x; // Try X-Axis only UpdatePositionInternal(entity, subOldPosition, ref subNewPositionInX, step + 1); // Try Y-Axis only UpdatePositionInternal(entity, subOldPosition, ref subNewPositionInY, step + 1); // Which one got us closer to our goal ? if ((subNewPositionInX - newPosition).sqrMagnitude < (subNewPositionInY - newPosition).sqrMagnitude) { // TODO - Recurse again ? // it was better to go in X only newPosition.x = subNewPositionInX.x; newPosition.y = subNewPositionInX.y; } else { newPosition.x = subNewPositionInY.x; newPosition.y = subNewPositionInY.y; } } } }