public bool CheckAABBCollision(AABB rect) { //return !(rect.y1 > y2 || rect.x1 > x2 || rect.x2 < x1 || rect.y2 < y1); if (rect.y1 > y2) return false; if (rect.x1 > x2) return false; if (rect.x2 < x1) return false; if (rect.y2 < y1) return false; return true; }
public Vector2 SolveCollision(AABB rect) { // If the two AABBs don't collide, do nothing: //if (rect.y1 > y2) return Vector2.Zero; //if (rect.x1 > x2) return Vector2.Zero; //if (rect.x2 < x1) return Vector2.Zero; //if (rect.y2 < y1) return Vector2.Zero; if (!CheckAABBCollision(rect)) return Vector2.Zero; float Y1 = y1 - rect.y2; // distance to move object up float X1 = x1 - rect.x2; // distance to move object left float X2 = x2 - rect.x1; // distance to move object right float Y2 = y2 - rect.y1; // distance to move object down float aX1 = Math.Abs(X1); float aX2 = Math.Abs(X2); float aY1 = Math.Abs(Y1); float aY2 = Math.Abs(Y2); /* // Allow player to go up stairs!! if (!omitTop && (!omitLeft || !omitRight) && aY1 < Level.collisionSize.Y * 1.5) { if (rect.physObj != null) { Line path = rect.physObj.GetMovementPath(); if (Math.Abs(path.nx) >= .25) { return new Vector2(0, Y1); } } } */ if (incline) { if (aY1 <= aX1 && aY1 <= aX2 && aY1 <= aY2) return omitTop ? Vector2.Zero : new Vector2(0, Y1); // move up if (aX1 <= aY1 && aX1 <= aY2 && aX1 <= aX2) return omitLeft ? Vector2.Zero : new Vector2(X1, 0); // move left if (aX2 <= aY1 && aX2 <= aY2 && aX2 <= aX1) return omitRight ? Vector2.Zero : new Vector2(X2, 0); // more right if (aY2 <= aX1 && aY2 <= aX2 && aY2 <= aY1) return omitBottom ? Vector2.Zero : new Vector2(0, Y2); // move down } else { if (aY1 <= aX1 && aY1 <= aX2 && aY1 <= aY2) if (!omitTop) return new Vector2(0, Y1); // move up if (aX1 <= aY1 && aX1 <= aY2 && aX1 <= aX2) if (!omitLeft) return new Vector2(X1, 0); // move left if (aX2 <= aY1 && aX2 <= aY2 && aX2 <= aX1) if (!omitRight) return new Vector2(X2, 0); // more right if (aY2 <= aX1 && aY2 <= aX2 && aY2 <= aY1) if (!omitBottom) return new Vector2(0, Y2); // move down } return Vector2.Zero; }
public static void CheckEnvironment(PhysObj obj) { Point cornerTopLeft = PositionToGrid(new Vector2(obj.hitBox.Left(), obj.hitBox.Top())); Point cornerBottomRight = PositionToGrid(new Vector2(obj.hitBox.Right(), obj.hitBox.Bottom())); bool collision = false; float friction = obj.frictionMultiplier; List<AABB> collisionList = new List<AABB>(); List<float> frictionList = new List<float>(); for (int y = cornerTopLeft.Y; y <= cornerBottomRight.Y; y++) { for (int x = cornerTopLeft.X; x <= cornerBottomRight.X; x++) { if (CheckCollision(new Point(x, y))) { AABB aabb = new AABB(null, GridToPosition(new Point(x, y)), new Vector2(collisionSize)); if (environmentData[x, y].inclineType != InclineType.Flat) { aabb = SolveIncline(obj, x, y); } if (environmentData[x, y].oneWayPlatform) { aabb.omitLeft = true; aabb.omitRight = true; aabb.omitBottom = true; if (obj.speed.Y < 0 || obj.ignoreOneWay) { aabb.omitTop = true; } } if ((CheckCollision(x - 1, y) && !environmentData[x - 1, y].oneWayPlatform) || environmentData[x, y].omitLeft) aabb.omitLeft = true; if ((CheckCollision(x + 1, y) && !environmentData[x + 1, y].oneWayPlatform) || environmentData[x, y].omitRight) aabb.omitRight = true; if ((CheckCollision(x, y + 1) && !environmentData[x, y + 1].oneWayPlatform) || environmentData[x, y].omitBottom) aabb.omitBottom = true; if ((CheckCollision(x, y - 1) && !environmentData[x, y - 1].oneWayPlatform) || environmentData[x, y].omitTop) aabb.omitTop = true; //if (CheckCollision(x - 1, y) && environmentData[x,y].inclineType == InclineType.Flat) //{ // if (environmentData[x - 1, y].inclineType != InclineType.Flat && (obj.position.X > aabb.x1 && obj.position.X < aabb.x2)) aabb.omitTop = true; //} collisionList.Add(aabb); collision = true; frictionList.Add(GetFriction(obj, environmentData[x, y])); } CheckCurrent(obj, x, y); if (IsLegalXY(x,y) && environmentData[x, y].killZone) { obj.Die(); } } } Point checkBelow = PositionToGrid(new Vector2(obj.position.X, obj.hitBox.Bottom() + 1)); if (CheckCollision(checkBelow)) { if (environmentData[checkBelow.X, checkBelow.Y].inclineType != InclineType.Flat) { //Trace.WriteLine("Barf!"); if (!obj.jumpingLegacy) { //AABB aabb = new AABB(null, GridToPosition(checkBelow), new Vector2(collisionSize)); //aabb = SolveIncline(obj, checkBelow.X, checkBelow.Y); //obj.hitBox.SetPosition(obj.hitBox.GetPosition() + new Vector2(0, aabb.y2 - obj.hitBox.Bottom())); //collisionList.Add(aabb); //frictionList.Add(GetFriction(obj, environmentData[checkBelow.X, checkBelow.Y])); obj.nextForce.Y += 20; } } } //int y1 = cornerBottomRight.Y + 1; //for (int x = cornerTopLeft.X; x <= cornerBottomRight.X; x++) //{ // if (CheckCollision(x, y1)) // { // AABB aabb = new AABB(null, GridToPosition(new Point(x, y1)), new Vector2(collisionSize)); // if (environmentData[x, y1].inclineType != InclineType.Flat) // { // obj.position += new Vector2(0, 32); // collisionList.Add(aabb); // frictionList.Add(GetFriction(obj, environmentData[x, y1])); // } // } //} //if (collision == false) //{ // if (obj.state == PhysState.Grounded) //{ //check to see if there's ground beneath the object: //Point under = PositionToGrid(obj.tempPosition); //under.Y += 1; //if (CheckCollision(under.X, under.Y)) //{ // collision = true; //} //if (!collision) obj.state = PhysState.Air; //int y = cornerBottomRight.Y + 1; //for (int x = cornerTopLeft.X; x < cornerBottomRight.X; x++) //{ // if (CheckCollision(x, y)) // { // collision = true; // break; // } //} //if (!collision) obj.state = PhysState.Air; // } // return; //} foreach (AABB aabb in collisionList) { Vector2 solution = aabb.SolveCollision(obj.hitBox.GetAABB()); obj.hitBox.SetPosition(obj.hitBox.GetPosition() + solution); if (solution.Y < 0) { friction = frictionList.ElementAt(collisionList.IndexOf(aabb)); } } Vector2 newpos = obj.hitBox.GetPosition(); if (newpos.Y != obj.tempPosition.Y) obj.speed.Y = SolveBounce(obj, true); if (newpos.X != obj.tempPosition.X) obj.speed.X = SolveBounce(obj, false); if (newpos.Y < obj.tempPosition.Y) { obj.state = PhysState.Grounded; } obj.tempPosition = newpos; if (obj.state == PhysState.Grounded) { obj.frictionMultiplier = friction; if (friction == EnvironmentData.NORMAL) { obj.moveForce = 1; } else if (friction == EnvironmentData.ICE) { obj.moveForce = .2f; } } else { obj.frictionMultiplier = EnvironmentData.AIR; obj.moveForce = .2f; } }
public AABB GetAABB() { AABB aabb = new AABB(physObj, WorldCornerMin, Size); aabb.omitTop = omitTop; aabb.omitBottom = omitBottom; aabb.omitRight = omitRight; aabb.omitLeft = omitLeft; return aabb; }
public static AABB SolveIncline(PhysObj obj, int x, int y) { bool omitTop = false; Vector2 cornerTopLeft = GridToPosition(new Point(x, y)); Vector2 cornerBottomRight = cornerTopLeft + new Vector2(collisionSize); float thirdSize = collisionSize / 3; float halfSize = collisionSize / 2; switch (environmentData[x, y].inclineType) { case InclineType.ThreeTileRight1: float ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerBottomRight.Y + ratio * (thirdSize); break; case InclineType.ThreeTileRight2: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; cornerTopLeft.Y = cornerBottomRight.Y - (thirdSize) + ratio * (thirdSize); if (ratio > 0 || ratio < -1) omitTop = true; break; case InclineType.ThreeTileRight3: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerBottomRight.Y - (2 * thirdSize) + ratio * (thirdSize); break; case InclineType.ThreeTileLeft1: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerTopLeft.Y - ratio * (thirdSize); break; case InclineType.ThreeTileLeft2: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; //if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerTopLeft.Y + (thirdSize) - ratio * (thirdSize); break; case InclineType.ThreeTileLeft3: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerTopLeft.Y + (2 * thirdSize) - ratio * (thirdSize); break; case InclineType.TwoTileRight1: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerBottomRight.Y + ratio * (halfSize); break; case InclineType.TwoTileRight2: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerBottomRight.Y - (halfSize) + ratio * (halfSize); break; case InclineType.TwoTileLeft1: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerTopLeft.Y - ratio * (halfSize); break; case InclineType.TwoTileLeft2: ratio = (cornerTopLeft.X - obj.tempPosition.X) / collisionSize; if (ratio > 0 || ratio < -1) omitTop = true; cornerTopLeft.Y = cornerTopLeft.Y + (halfSize) - ratio * (halfSize); break; } AABB aabb = new AABB(null, cornerTopLeft.X, cornerTopLeft.Y, cornerBottomRight.X, cornerBottomRight.Y); aabb.omitLeft = true; aabb.omitRight = true; if (omitTop) { aabb.omitTop = true; aabb.omitBottom = true; } aabb.incline = true; return aabb; }