//------------------------------------------------------------------------------------------ // BallSegmentCollisionDetection() //------------------------------------------------------------------------------------------ private void BallSegmentCollisionDetection(ref GameObject current, ref Vec2 currentNormal) { for (int i = 0; i < myGame.GetNumberOfLines(); i++) { LineSegment line = myGame.GetLine(i); if (Input.GetKey(Key.S) && line.parent is Stairs) { continue; } Vec2 differenceVector = _oldPosition - line.start; float ballDistance = differenceVector.Dot((line.end - line.start).Normal()); Vec2 normal = (line.end - line.start).Normal(); Vec2 dist = position + (-ballDistance + radius) * normal; float difference = (dist - position).Magnitude(); float b = -velocity.Dot(normal); float a = ballDistance - radius; if (b > 0) { float t = 3f; if (a >= 0) { t = a / b; } else if (a >= -radius) { t = 0; } else { continue; } if (t <= 1f) { Vec2 POI = _oldPosition + t * velocity; float d = (POI - line.start).Dot((line.end - line.start).Normalized()); if (0 <= d && d <= (line.end - line.start).Magnitude()) { if (t < smallestToi) { smallestToi = t; current = line; currentNormal = normal; currentline = (Platform)line; } } } } } }
CollisionInfo FindEarliestCollision() { GameObject current = null; Vec2 currentNormal = new Vec2(); smallestToi = 2f; MyGame myGame = (MyGame)game; // Check other movers: for (int i = 0; i < myGame.GetNumberOfMovers(); i++) { Ball mover = myGame.GetMover(i); if (mover != this) { Vec2 relativePosition = position - mover.position; //if (relativePosition.Magnitude() < radius + mover.radius) //{ // TODO: compute correct normal and time of impact, and // return *earliest* collision instead of *first detected collision*: Vec2 u = _oldPosition - mover.position; float a = velocity.Magnitude() * velocity.Magnitude(); float b = 2 * u.Dot(velocity); float c = u.Magnitude() * u.Magnitude() - (radius + mover.radius) * (radius + mover.radius); float delta = b * b - 4 * a * c; float t; t = (-b - Mathf.Sqrt(delta)) / (2 * a); if (c < 0) { if (b < 0) { t = 0; //Vec2 normal = (_oldPosition - mover.position).Normalized(); //return new CollisionInfo(normal, mover, t); } else { continue; } } if (a != 0) //{ // return null; //} //else { if (delta >= 0) //{ // return null; //} //else { Vec2 pointOfImpact = _oldPosition + velocity * t; Vec2 normal = (pointOfImpact - mover.position).Normalized(); if (0 <= t && t < 1) { if (t < smallestToi) { smallestToi = t; current = mover; currentNormal = normal; } } //else return null; } } //Vec2 normal = relativePosition.Normalized(); //float overlap = radius + mover.radius - relativePosition.Magnitude(); //return new CollisionInfo(normal, mover, overlap); //} } } for (int i = 0; i < myGame.GetNumberOfLines(); i++) { NLineSegment line = myGame.GetLine(i); Vec2 differenceVector = _oldPosition - line.start; float ballDistance = differenceVector.Dot((line.end - line.start).Normal()); //if (ballDistance < radius) //{ Vec2 normal = (line.end - line.start).Normal(); Vec2 dist = position + (-ballDistance + radius) * normal; float difference = (dist - position).Magnitude(); float b = -velocity.Dot(normal); //float a = b - difference; float a = ballDistance - radius; if (b > 0) //{ // return null; //} //else { float t = 3f; if (a >= 0) //{ // return null; //} //else { t = a / b; } else if (a >= -radius) { t = 0; } else { continue; } if (t <= 1f) { Vec2 POI = _oldPosition + t * velocity; float d = (POI - line.start).Dot((line.end - line.start).Normalized()); if (0 <= d && d <= (line.end - line.start).Magnitude()) { if (t < smallestToi) { smallestToi = t; current = line; currentNormal = normal; } } // else return null; } } //} } if (current != null) { return(new CollisionInfo(currentNormal, current, smallestToi)); } else { return(null); } // TODO: Check Line segments using myGame.GetLine(); // return null; }