예제 #1
0
 private void OnObjectFound(MarsObject o)
 {
     if (ObjectFound != null)
     {
         ObjectFound(this, o);
     }
 }
예제 #2
0
 private void OnObjectSeen(MarsObject o)
 {
     if (ObjectSeen != null)
     {
         ObjectSeen(this, o);
     }
 }
예제 #3
0
 protected void DrawDebugEllipse(MarsObject obj, Brush b)
 {
     if (DebugEllipse != null)
     {
         DebugEllipse(obj, b);
     }
 }
예제 #4
0
        private void DrawRover(Rover r, Graphics g)
        {
            // cheat and draw the rover twice as large as it should be
            MarsObject obj = new MarsObject(r.Position, r.Radius * 4);

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            Rectangle rect = GetObjectRect(obj);

            g.FillEllipse(m_roverBrush, rect);
            g.DrawEllipse(m_borderPen, rect);
        }
예제 #5
0
        public bool FindClosestCollision(Vector2d origin, float direction, float length, float padding, ref MarsObject obj, ref float distance, ref int tests)
        {
            Vector2d end = origin + (Vector2d.FromAngle(direction) * -length);

            // exit if line doesn't intersect
            if (!IntersectsLine(origin, end))
            {
                return(false);
            }

            // test children
            if (children != null)
            {
                return(FindClosestCollisionChildren(origin, direction, length, padding, ref obj, ref distance, ref tests));
            }

            // test objects
            float      closest_range  = float.MaxValue;
            MarsObject closest_object = null;

            foreach (MarsObject o in objects)
            {
                tests++;
                Vector2d point = new Vector2d();
                if (o.Intersect(origin, end, padding, ref point))
                {
                    //OnCollision(point);
                    float range = (origin - point).length();
                    if (range < closest_range && range > 0.0f)
                    {
                        closest_range  = range;
                        closest_object = o;
                    }
                }
            }

            if (closest_range != float.MaxValue)
            {
                obj      = closest_object;
                distance = closest_range;
                return(true);
            }

            return(false);
        }
예제 #6
0
 public void AddObject(MarsObject o)
 {
     if (children == null)
     {
         objects.Add(o);
         if (objects.Count > SPLIT_ITEMS && depth < MAX_DEPTH)
         {
             Split();
         }
     }
     else
     {
         foreach (SimpleQuadTree t in children)
         {
             if (t.rect.IntersectsWith(o.GetRect()))
             {
                 t.AddObject(o);
             }
         }
     }
 }
예제 #7
0
        private bool FindClosestCollisionChildren(Vector2d origin, float direction, float length, float padding, ref MarsObject obj, ref float distance, ref int tests)
        {
            bool found_closer = false;

            foreach (SimpleQuadTree t in children)
            {
                float      temp_distance = float.MaxValue;
                MarsObject temp_obj      = null;

                if (t.FindClosestCollision(origin, direction, length, padding, ref temp_obj, ref temp_distance, ref tests))
                {
                    if (temp_distance < distance)
                    {
                        distance     = temp_distance;
                        obj          = temp_obj;
                        found_closer = true;
                    }
                }
            }
            return(found_closer);
        }
예제 #8
0
        private Rectangle GetObjectRect(MarsObject obj)
        {
            PointF center = new PointF(
                (obj.Position.x + m_offset.X) * m_scale.Width,
                ((obj.Position.y * -1.0f) + m_offset.Y) * m_scale.Height);

            Rectangle r = new Rectangle(
                (int)(center.X - (obj.Radius * m_scale.Width)),
                (int)(center.Y - (obj.Radius * m_scale.Height)),
                (int)((obj.Radius * m_scale.Width) * 2),
                (int)((obj.Radius * m_scale.Height) * 2));

            // make sure it is at least 1 px by 1px
            if (r.Width == 0)
            {
                r.Width = 1;
            }
            if (r.Height == 0)
            {
                r.Height = 1;
            }

            return(r);
        }
예제 #9
0
        private float NearestObject(float heading, float max_dist, float padding, ref MarsObject closest_obj, bool check_martians)
        {
            m_numRayCasts++;
            max_dist = Math.Min(max_dist, m_world.Rover.Speed * 5.0f);
            //Vector2d angle = new Vector2d(
            //    (float)Math.Cos(((-1.0f * heading) - 90) * (Math.PI / 180.0f)),
            //    (float)Math.Sin(((-1.0f * heading) - 90) * (Math.PI / 180.0f)));
            //Vector2d end = m_world.Rover.Position + (-max_dist * angle);
            Vector2d end = m_world.Rover.Position + (Vector2d.FromAngle(heading) * -max_dist);

            //DrawDebugLine(m_world.Rover.Position, end, Pens.Blue);

            float closest_range = float.MaxValue;

            m_world.QuadTree.FindClosestCollision(m_world.Rover.Position, heading, max_dist, padding, ref closest_obj, ref closest_range, ref m_numRayTests);
            Vector2d point = new Vector2d();

            if (check_martians)
            {
                foreach (Martian m in m_world.Martians)
                {
                    //m_numRayTests++;
                    if (m.Intersect(m_world.Rover.Position, end, padding, ref point)) // give martians a wide berth
                    {
                        //DrawDebugEllipse(m, Brushes.Yellow);
                        float range = (m_world.Rover.Position - point).length();
                        if (range < closest_range && range > 0.0f) // ignore the obstacle if we think we are inside of it (avoids panics)
                        {
                            closest_range = range;
                            closest_obj   = m;
                        }
                    }
                }
            }

            if ((m_debugFlags & DebugFlags.ChooseRandomTarget) == DebugFlags.ChooseRandomTarget) // actively avoid home
            {
                if (m_world.FoundHome && m_world.Home.Intersect(m_world.Rover.Position, end, padding, ref point))
                {
                    float range = (m_world.Rover.Position - point).length();
                    if (range < closest_range && range > 0.0f) // ignore the obstacle if we think we are inside of it (avoids panics)
                    {
                        closest_range = range;
                        closest_obj   = m_world.Home;
                    }
                }
            }

            if (closest_range == float.MaxValue)
            {
                if ((m_debugFlags & DebugFlags.DrawRays) == DebugFlags.DrawRays)
                {
                    DrawDebugLine(m_world.Rover.Position, end, Pens.Blue);
                }
            }
            else if ((m_debugFlags & DebugFlags.DrawRays) == DebugFlags.DrawRays)
            {
                DrawDebugLine(m_world.Rover.Position, end, Pens.Red);
            }

            return(closest_range);
        }
예제 #10
0
        private bool TrajectoryHitsObject(float heading, float max_dist, float padding, bool check_martians)
        {
            MarsObject dummy = null;

            return(float.MaxValue != NearestObject(heading, max_dist, padding, ref dummy, check_martians));
        }
예제 #11
0
        private float GetClosestDistance(Vector2d vector2d, float heading, float distance, float padding, bool checkmartians)
        {
            MarsObject temp = null;

            return(NearestObject(heading, distance, padding, ref temp, checkmartians));
        }
예제 #12
0
        private bool VerifyTurn(ref float heading, ref MoveType gas)
        {
            float turn_angle = heading - m_world.Rover.Direction;

            if (turn_angle > 0.0f)
            {
                if (turn_angle > 180.0f)
                {
                    turn_angle -= 360.0f;
                }
            }
            if (turn_angle < 0.0f)
            {
                if (turn_angle < -180.0f)
                {
                    turn_angle += 360.0f;
                }
            }

            MarsObject critical_object   = null;
            float      critical_distance = NearestObject(m_world.Rover.Direction, m_world.Rover.Speed * 1.5f, 1.0f, ref critical_object, true);

            if (critical_object != null) // need to perform a close-range avoidance
            {
                Vector2d angle            = Vector2d.FromAngle(m_world.Rover.Direction);
                Vector2d end              = m_world.Rover.Position + (m_world.Rover.Speed * angle);
                float    collision_offset = critical_object.DistanceFromLine(m_world.Rover.Position, end);
                TurnType dir              = critical_object.DistanceFromLine(m_world.Rover.Position, end) > 0.0 ? TurnType.Left : TurnType.Right;
                if ((critical_object.Radius - Math.Abs(collision_offset) > m_criticalTurn) ||
                    critical_distance < m_criticalDistance)
                {
                    dir = critical_object.DistanceFromLine(m_world.Rover.Position, end) > 0.0 ? TurnType.HardLeft : TurnType.HardRight;
                    gas = MoveType.Brake;
                    //Log("BRAKING");
                }
                DoTurn(dir);
                return(false);
            }

            float safe_angle       = float.MaxValue;
            float closest_distance = float.MaxValue;
            float safest_angle     = float.MaxValue;
            float safest_distance  = float.MinValue;
            bool  found_safest     = false;

            float inc = turn_angle > 0.0f ? 0.5f : -0.5f;

            for (float angle = inc; Math.Abs(angle) < Math.Abs(turn_angle); angle += inc)
            {
                float temp_closest = GetClosestDistance(m_world.Rover.Position, m_world.Rover.Direction + angle, m_world.Rover.Speed * 1.5f, 1.0f, true);
                closest_distance = Math.Min(closest_distance, temp_closest);
                if (closest_distance == float.MaxValue) // still nothing
                {
                    safe_angle = angle;
                }
                if (temp_closest > safest_distance && !found_safest)
                {
                    safest_distance = temp_closest;
                    safest_angle    = angle;
                }
                else if (temp_closest < safest_distance)
                {
                    found_safest = true;
                }
            }

            if (safe_angle != float.MaxValue)
            {
                //DrawDebugRay(m_world.Rover.Position, m_world.Rover.Direction + safe_angle, m_world.Rover.Speed * 1.5f, Pens.Blue);
                heading = m_world.Rover.Direction + safe_angle;
            }
            else if (safest_angle != float.MaxValue)
            {
                //DrawDebugRay(m_world.Rover.Position, m_world.Rover.Direction, m_world.Rover.Speed * 1.5f, Pens.Green);
                //for (float angle = inc; Math.Abs(angle) <= Math.Abs(turn_angle); angle += inc)
                //    DrawDebugRay(m_world.Rover.Position, m_world.Rover.Direction + angle, m_world.Rover.Speed * 1.5f, Pens.Yellow);

                heading = m_world.Rover.Direction + safest_angle;
                //DrawDebugRay(m_world.Rover.Position, heading, m_world.Rover.Speed * 1.5f, Pens.Yellow);
            }

            return(true);
        }
예제 #13
0
 private bool FindFirstCollision(Vector2d origin, float direction, float length, float padding, ref MarsObject obj, ref float distance)
 {
     return(false);
 }
예제 #14
0
 void m_controller_DebugEllipse(MarsObject obj, Brush b)
 {
     worldVisualizer.DrawEllipse(obj, b);
 }
예제 #15
0
 public void DrawEllipse(MarsObject obj, Brush b)
 {
     m_debugEllipses.Add(new Ellipse(GetObjectRect(obj), b));
 }