Exemplo n.º 1
0
        public HitboxArmorMarker(HitboxPolygon hitbox, Armor arg_armor, float displacement, float segment_separation)
        {
            // we need to construct the lines to represent our armor segments.
            // We have to project the armors angular system onto the hitbox.

            armor = arg_armor;
            nodes = new List<Vector2>[armor.segment_count];


            int count = hitbox.count;
            Vector2[] corners = new Vector2[count];
            Vector2[] displacements = new Vector2[count];

            Vector2 last = hitbox.corners.Last();
            
            for (int i = 0; i < count; i++)
            {
                Vector2 p = hitbox.corners[i];

                Vector2 delta = last - p;
                delta.Normalize();

                displacements[i] = Utility.RotateNeg(delta) * displacement / 2.0f;
                corners[i] = p;
                last = p;
            }
            for (int i = 0; i < count; i++)
            {
                int k = (i == count - 1) ? 0 : i + 1;

                corners[i] += displacements[i];
                corners[i] += displacements[k];
            }



            Vector2 p1 = corners[0];
            int first_segment = armor.GetSegmentLocal(p1);
            int segment = first_segment;
            nodes[segment] = new List<Vector2>();

            List<Vector2> popped = null;

            for (int j = 0; j < count; j++)
            {
                // iterate through all hitbox segments
                int i = j + 1;
                if (i == count) { i = 0; }
                Vector2 p2 = corners[i];

                // if this line has crossed an armor intersection
                int new_segment = armor.GetSegmentLocal(p2);
                if (new_segment != segment)
                {
                    // We find the midpoint of the the line where it croses the armor angle
                    Vector2 cossin = Utility.CosSin(-armor.GetSegmentStartAngle(segment));
                    float p1ry = p1.X * cossin.Y + p1.Y * cossin.X;
                    float p2ry = p2.X * cossin.Y + p2.Y * cossin.X;
                    float alpha = p1ry / (p1ry - p2ry);
                    Vector2 mid = ((p2 - p1) * alpha) + p1;


                    if (new_segment == first_segment)
                    {
                        // this segment already has data in it.
                        // we will add this back in later.
                        popped = nodes[new_segment];
                    }

                    // the new segment starts at the midpoint
                    nodes[new_segment] = new List<Vector2>();
                    nodes[new_segment].Add(mid);
                    nodes[new_segment].Add(p2);

                    // the previous segment ends at the midpoint
                    nodes[segment].Add(mid);

                    segment = new_segment;

                }
                else
                {
                    nodes[segment].Add(p2);
                }


                p1 = p2;
            }


            if (popped != null)
            {
                // We popped some of the data from the first segment, time to get it back
                foreach (Vector2 pt in popped)
                {
                    nodes[first_segment].Add(pt);
                }
            }


            float sep = segment_separation / 2.0f;

            foreach (List<Vector2> node in nodes)
            {
                trim(node, 1, sep);
                trim(node, -1, sep);
            }            
        }
Exemplo n.º 2
0
        Intersection IntersectPolygonHalf(HitboxPolygon hitbox)
        {
            Intersection best_sect = null;

            // checks each point in the hitbox 
            for (int i = 0; i < count; i++)
            {
                // shift the point into global frame
                Vector2 point = pos + Utility.Rotate(corners[i], angle);

                // we then see to if any of the points lie inside this polygon
                Intersection sect = hitbox.Intersect(point);

                if (sect != null)
                {
                    // the intersection with the biggest overlap is the most important to service
                    if (best_sect == null || sect.overlap > best_sect.overlap)
                    {
                        // we average the surface normal and the corner normal
                        // To provide a better approximation of the impact normal
                        float corner_normal = corner_normals[i] + angle;

                        float delta = Utility.AngleDelta(corner_normal + MathHelper.Pi, sect.surface_normal);
                        sect.surface_normal = Utility.WrapAngle(sect.surface_normal + delta / 2.0f);
                        
                        //sect.surface_normal = Utility.Angle(hitbox.pos - pos); // COM approx. A backup solution.
                    
                        best_sect = sect;
                    }
                }
            }

            return best_sect;
        }
Exemplo n.º 3
0
        // Returns the intersection of two HitboxPolygons
        public Intersection IntersectPolygon(HitboxPolygon hitbox)
        {
            //TODO: abstract the two point test loops out.


            Intersection best_sect = this.IntersectPolygonHalf(hitbox);
            Intersection next_sect = hitbox.IntersectPolygonHalf(this);

            if (next_sect != null)
            {
                next_sect.surface_normal = Utility.WrapAngle(next_sect.surface_normal + MathHelper.Pi);
            }
            else { return best_sect; }

            if (best_sect == null) { return next_sect; }
            
            return (best_sect.overlap > next_sect.overlap) ? best_sect : next_sect;
        }
Exemplo n.º 4
0
 public HitboxPolygon( HitboxPolygon clone )
 {
     corners = clone.corners;
     count = clone.count;
     segment_normals = clone.segment_normals;
     corner_normals = clone.corner_normals;
     radius = clone.radius;
     radius_sq = clone.radius_sq;
     size = clone.size;
 }