Beispiel #1
0
        private bool CircleLineIntersect(MovingObject o, SimpleCollidableLine boundry)
        {
            Vector2 A = boundry.From;
            Vector2 B = boundry.To;
            Vector2 C = o.Position;
            float r = (o.Width - 5) / 2; // approx. radius of bibble
            // compute the euclidean distance between A and B
            float lab = Vector2.Distance(A, B);
            // compute the direction vector D from A to B
            Vector2 D = new Vector2((B.X - A.X) / lab, (B.Y - A.Y) / lab);
            // check, whether the centre of o has passed the line within one update cycle
            // the object must be fast, else, in the last collision check(s) it would have
            // touched the line!
            if (Vector2.Distance(o.LastPos, o.Position) > r) // this object is fast!
            {
                Vector2 C2 = o.LastPos;
                float ua = (C.X - C2.X) * (A.Y - C2.Y) - (C.Y - C2.Y) * (A.X - C2.X);
                float ub = (B.X - A.X) * (A.Y - C2.Y) - (B.Y - A.Y) * (A.X - C2.X);
                float denominator = (C.Y - C2.Y) * (B.X - A.X) - (C.X - C2.X) * (B.Y - A.Y);

                if (Math.Abs(denominator) <= 0.00001f)
                {
                    if (Math.Abs(ua) <= 0.00001f && Math.Abs(ub) <= 0.00001f && o.Collide(boundry))
                    {
                        //arbitrary intersectionpoint
                        // (A + B) / 2;
                        return true;
                    }
                }
                else
                {
                    ua /= denominator;
                    ub /= denominator;

                    if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
                    {
                        // crossing point E
                        Vector2 Es = new Vector2(A.X + ua * (B.X - A.X), A.Y + ua * (B.Y - A.Y));
                        // compute the euclidean distance from E to C
                        float lecs = (float)Math.Sqrt((Es.X - C.X) * (Es.X - C.X) + (Es.Y - C.Y) * (Es.Y - C.Y));
                        //intersectionPoint.X = A.X + ua * (B.X - A.X);
                        //intersectionPoint.Y = A.Y + ua * (B.Y - A.Y);
                        if (o.Collide(boundry))
                        {
                            o.Position = Es;
                            return true;
                        }
                        else
                        {
                            //position and orientation correction
                            Vector2 resulting;
                            Vector2 oldDirection = new Vector2((float)Math.Cos(o.MovementDirection), (float)Math.Sin(o.MovementDirection));
                            Vector2 normal = new Vector2(-D.Y, D.X);
                            Vector2.Reflect(ref oldDirection, ref normal, out resulting);
                            if (resulting.Length() != 1f)
                            {
                                resulting.Normalize();
                            }
                            o.MovementDirection = (float)Math.Atan2(resulting.Y, resulting.X);
                            // move it back distance r-lec and furth r-lec again (in the new direction)
                            o.Position = Es + resulting * lecs;
                            return false;
                        }
                    }
                }
            }

            if (Vector2.Distance(A, C) + Vector2.Distance(B, C) - 2 * r > lab)
            {
                return false;
            }

            // Now the line equation is x = Dx*t + Ax, y = Dy*t + Ay with 0 <= t <= 1.
            // compute the value t of the closest point to the circle center (Cx, Cy)
            float t = D.X * (C.X - A.X) + D.Y * (C.Y - A.Y);
            // This is the projection of C on the line from A to B.
            // compute the coordinates of the point E on line and closest to C
            Vector2 E = new Vector2(t * D.X + A.X, t * D.Y + A.Y);
            // compute the euclidean distance from E to C
            float lec = (float)Math.Sqrt((E.X - C.X) * (E.X - C.X) + (E.Y - C.Y) * (E.Y - C.Y));
            // test if the line intersects or tangents the circle
            if (lec < r) // TODO lec = r
            {
                /*    // compute distance from t to circle intersection point
                    float dt = (float)Math.Sqrt(r * r - lec * lec);
                    // compute first intersection point
                    Vector2 F = new Vector2((t - dt) * D.X + A.X, (t - dt) * D.Y + A.Y);
                    // compute second intersection point
                    Vector2 G = new Vector2((t + dt) * D.X + A.X, (t + dt) * D.Y + A.Y);*/
                if (o.Collide(boundry))
                {
                    Explosion(E, 0.05f, false); // ugly style
                    return true;
                }
                else
                {
                    Vector2 resulting;
                    Vector2 oldDirection = new Vector2((float)Math.Cos(o.MovementDirection), (float)Math.Sin(o.MovementDirection));
                    if (Vector2.Distance(C - oldDirection, E) < Vector2.Distance(C + oldDirection, E)) return false;
                    Vector2 normal = new Vector2(-D.Y, D.X);
                    Vector2.Reflect(ref oldDirection, ref normal, out resulting);
                    if (resulting.Length() != 1f)
                    {
                        resulting.Normalize();
                    }
                    o.MovementDirection = (float)Math.Atan2(resulting.Y, resulting.X);
                    // move it back distance r-lec and furth r-lec again (in the new direction)
                    o.Position -= oldDirection * (r - lec);
                    o.Position += resulting * (r - lec);
                    return false;
                }
            }

            else
            {
                // line doesn't touch circle
                return false;
            }
        }
Beispiel #2
0
 internal void addLine(SimpleCollidableLine l)
 {
     lines.Add(l);
     Components.Add(l);
 }