예제 #1
0
 public void Clear()
 {
     body_a = body_b = null;
     pointmass_a = pointmass_b = pointmass_c = new PointMass();
     edge_distance = 0f;
     point = Vector2.Zero;
     normal = Vector2.Zero;
     penetration = 0f;
 }
예제 #2
0
        public void BuildWall(Plane p)
        {
            ShapeBuilder shapebuilder = new ShapeBuilder(model);

            Matrix transform = GetTransform();
            Vector2[] points = shapebuilder.GetShape(ref transform, p);

            shape = new Shape(points, false);
            offset = shape.GetCenter() - new Vector2(position.X, position.Y);
            shape.CenterAtZero();

            body = new Body(shape, float.MaxValue);
            body.position.X = position.X + offset.X;
            body.position.Y = position.Y + offset.Y;
            body.is_static = true;
            body.Update(0);
        }
예제 #3
0
        public void Draw(Body body, Camera camera, bool shapes, bool outlines, bool normals, bool points, bool chains, bool tags)
        {
            material.Projection = camera.projection;
            material.View = camera.view;
            material.World = Matrix.Identity;
            material.CurrentTechnique.Passes[0].Apply();

            PrimitiveBatch instance = PrimitiveBatch.GetInstance(device);
            instance.Begin(Primitive.Line);

            if (shapes)
            {
                instance.SetColor(Color.Purple);
                for (int p = 1; p < body.curr_shape.count; p++)
                {
                    instance.AddVertex(body.curr_shape.points[p - 1]);
                    instance.AddVertex(body.curr_shape.points[p - 0]);
                }

                instance.AddVertex(body.curr_shape.points[body.curr_shape.count - 1]);
                instance.AddVertex(body.curr_shape.points[0]);
            }

            if (outlines)
            {
                instance.SetColor(Color.White);
                for (int p = 1; p < body.pointmass_list.Length; p++)
                {
                    instance.AddVertex(body.pointmass_list[p - 1].position);
                    instance.AddVertex(body.pointmass_list[p - 0].position);
                }

                instance.AddVertex(body.pointmass_list[body.pointmass_list.Length - 1].position);
                instance.AddVertex(body.pointmass_list[0].position);
            }

            if (normals)
            {
                instance.SetColor(Color.Purple);
                for (int p = 0; p < body.pointmass_list.Length; p++)
                {
                    Vector2 pt = body.pointmass_list[p].position;

                    int prevPt = (p > 0) ? p - 1 : body.pointmass_list.Length - 1;
                    int nextPt = (p < body.pointmass_list.Length - 1) ? p + 1 : 0;

                    Vector2 prev = body.pointmass_list[prevPt].position;
                    Vector2 next = body.pointmass_list[nextPt].position;

                    Vector2 fromPrev = new Vector2();
                    fromPrev.X = pt.X - prev.X;
                    fromPrev.Y = pt.Y - prev.Y;

                    Vector2 toNext = new Vector2();
                    toNext.X = next.X - pt.X;
                    toNext.Y = next.Y - pt.Y;

                    Vector2 ptNorm = new Vector2();
                    ptNorm.X = fromPrev.X + toNext.X;
                    ptNorm.Y = fromPrev.Y + toNext.Y;
                    VectorHelper.Perpendicular(ref ptNorm);

                    ptNorm = Vector2.Normalize(ptNorm) * (camera.position.Z * 0.03f); ;

                    instance.AddVertex(pt);
                    instance.AddVertex(pt + ptNorm);
                }
            }
            instance.End();

            if (points)
            {
                instance.Begin(Primitive.Quad);
                instance.SetColor(Color.Red);

                float size = 0.015f;

                for (int p = 0; p < body.pointmass_list.Length; p++)
                {
                    PointMass pm = body.pointmass_list[p];

                    instance.AddVertex(pm.position.X + size, pm.position.Y - size, 0);
                    instance.AddVertex(pm.position.X + size, pm.position.Y + size, 0);
                    instance.AddVertex(pm.position.X - size, pm.position.Y + size, 0);
                    instance.AddVertex(pm.position.X - size, pm.position.Y - size, 0);

                }

                instance.End();
            }

            if (tags)
            {
                SpriteRenderer spriterenderer = SpriteRenderer.GetInstance(device);
                spriterenderer.Begin(null);

                Vector3 proj = camera.Project(new Vector3(body.position, 0));
                spriterenderer.AddString(Resources.arial10px_font, body.ToStringSimple(), proj.X, proj.Y);

                spriterenderer.End();
            }
        }
예제 #4
0
 public void Draw(Body body, Camera camera)
 {
     Draw(body, camera, false, true, true, false, true, false);
 }
예제 #5
0
 public void Add(Body body)
 {
     if (!body_list.Contains(body))
         body_list.Add(body);
 }
예제 #6
0
        public void UpdateBitmask(Body body)
        {
            BoundingSquare box = body.aabb;

            int minX = (int)Math.Floor((box.min.X - aabb.min.X) / cell.X);
            int maxX = (int)Math.Floor((box.max.X - aabb.min.X) / cell.X);

            if (minX < 0) { minX = 0; } else if (minX > 32) { minX = 32; }
            if (maxX < 0) { maxX = 0; } else if (maxX > 32) { maxX = 32; }

            int minY = (int)Math.Floor((box.min.Y - aabb.min.Y) / cell.Y);
            int maxY = (int)Math.Floor((box.max.Y - aabb.min.Y) / cell.Y);

            if (minY < 0) { minY = 0; } else if (minY > 32) { minY = 32; }
            if (maxY < 0) { maxY = 0; } else if (maxY > 32) { maxY = 32; }

            body.bitmaskx.clear();
            for (int i = minX; i <= maxX; i++)
                body.bitmaskx.setOn(i);

            body.bitmasky.clear();
            for (int i = minY; i <= maxY; i++)
                body.bitmasky.setOn(i);
        }
예제 #7
0
 public void Remove(Body body)
 {
     if (body_list.Contains(body))
         body_list.Remove(body);
 }
예제 #8
0
        private void penetration(Body body_a, Body body_b)
        {
            // early out, cant be a bubble merge
            if (body_a.is_static || body_b.is_static)
                return;

            if (body_a == player.body)
                if (TryMerge(FindBubble(body_b)))
                    player.num_collected++;

            if (body_b == player.body)
                if (TryMerge(FindBubble(body_a)))
                    player.num_collected++;
        }
예제 #9
0
        private Entity FindEnemy(Body body)
        {
            for (int i = 0; i < entities.Count; i++)
            {
                Entity entity = entities[i];

                if (entity is Enemy || entity is Fish || entity is Octopus)
                {
                    Enemy enemy = entity as Enemy;

                    if (enemy.body == body)
                        return enemy;
                }
            }

            return null;
        }
예제 #10
0
        private Entity FindBubble(Body body)
        {
            for (int i = 0; i < entities.Count; i++)
            {
                Entity entity = entities[i];

                if (entity is Bubble)
                {
                    Bubble bubble = entity as Bubble;

                    if (bubble.body == body)
                        return bubble;
                }
            }

            return null;
        }
예제 #11
0
        private void collision(Body body_a, Body body_b, CollisionInfo info)
        {
            if (player.hurt != 0)
                return;

            // early out, cant be a bubble merge
            if (body_a.is_static || body_b.is_static)
                return;

            if (body_a == player.body)
                if (FindEnemy(body_b) != null)
                {
                    player.Hurt();
                    Resources.droplet_sound.Play(0.025f, ((float)rand.NextDouble() - 0.5f), 0);
                }

            if (body_b == player.body)
                if (FindEnemy(body_a) != null)
                {
                    player.Hurt();
                    Resources.droplet_sound.Play(0.025f, ((float)rand.NextDouble() - 0.5f), 0);
                }
        }
예제 #12
0
        public static List<CollisionInfo> Intersects(Body body_a, Body body_b)
        {
            List<CollisionInfo> data = new List<CollisionInfo>();

            int bApmCount = body_a.count;
            int bBpmCount = body_b.count;

            BoundingSquare boxB = body_b.aabb;

            // check all PointMasses on bodyA for collision against bodyB.  if there is a collision, return detailed info.
            CollisionInfo infoAway = new CollisionInfo();
            CollisionInfo infoSame = new CollisionInfo();
            for (int i = 0; i < bApmCount; i++)
            {
                Vector2 pt = body_a.pointmass_list[i].position;

                // early out - if this point is outside the bounding box for bodyB, skip it!
                if (!boxB.Contains(pt.X, pt.Y))
                    continue;

                // early out - if this point is not inside bodyB, skip it!
                if (!body_b.Contains(ref pt))
                    continue;

                int prevPt = (i > 0) ? i - 1 : bApmCount - 1;
                int nextPt = (i < bApmCount - 1) ? i + 1 : 0;

                Vector2 prev = body_a.pointmass_list[prevPt].position;
                Vector2 next = body_a.pointmass_list[nextPt].position;

                // now get the normal for this point. (NOT A UNIT VECTOR)
                Vector2 fromPrev = new Vector2();
                fromPrev.X = pt.X - prev.X;
                fromPrev.Y = pt.Y - prev.Y;

                Vector2 toNext = new Vector2();
                toNext.X = next.X - pt.X;
                toNext.Y = next.Y - pt.Y;

                Vector2 ptNorm = new Vector2();
                ptNorm.X = fromPrev.X + toNext.X;
                ptNorm.Y = fromPrev.Y + toNext.Y;
                VectorHelper.Perpendicular(ref ptNorm);

                // this point is inside the other body.  now check if the edges on either side intersect with and edges on bodyB.
                float closestAway = 100000.0f;
                float closestSame = 100000.0f;

                infoAway.Clear();
                infoAway.body_a = body_a;
                infoAway.pointmass_a = body_a.pointmass_list[i];
                infoAway.body_b = body_b;

                infoSame.Clear();
                infoSame.body_a = body_a;
                infoSame.pointmass_a = body_a.pointmass_list[i];
                infoSame.body_b = body_b;

                bool found = false;

                int b1 = 0;
                int b2 = 1;
                for (int j = 0; j < bBpmCount; j++)
                {
                    Vector2 hitPt;
                    Vector2 norm;
                    float edgeD;

                    b1 = j;

                    if (j < bBpmCount - 1)
                        b2 = j + 1;
                    else
                        b2 = 0;

                    Vector2 pt1 = body_b.pointmass_list[b1].position;
                    Vector2 pt2 = body_b.pointmass_list[b2].position;

                    // quick test of distance to each point on the edge, if both are greater than current mins, we can skip!
                    float distToA = ((pt1.X - pt.X) * (pt1.X - pt.X)) + ((pt1.Y - pt.Y) * (pt1.Y - pt.Y));
                    float distToB = ((pt2.X - pt.X) * (pt2.X - pt.X)) + ((pt2.Y - pt.Y) * (pt2.Y - pt.Y));

                    if ((distToA > closestAway) && (distToA > closestSame) && (distToB > closestAway) && (distToB > closestSame))
                        continue;

                    // test against this edge.
                    float dist = body_b.GetClosestPointOnEdgeSquared(pt, j, out hitPt, out norm, out edgeD);

                    // only perform the check if the normal for this edge is facing AWAY from the point normal.
                    float dot;
                    Vector2.Dot(ref ptNorm, ref norm, out dot);
                    if (dot <= 0f)
                    {
                        if (dist < closestAway)
                        {
                            closestAway = dist;
                            infoAway.pointmass_b = body_b.pointmass_list[b1];
                            infoAway.pointmass_c = body_b.pointmass_list[b2];
                            infoAway.edge_distance = edgeD;
                            infoAway.point = hitPt;
                            infoAway.normal = norm;
                            infoAway.penetration = dist;
                            found = true;
                        }
                    }
                    else
                    {
                        if (dist < closestSame)
                        {
                            closestSame = dist;
                            infoSame.pointmass_b = body_b.pointmass_list[b1];
                            infoSame.pointmass_c = body_b.pointmass_list[b2];
                            infoSame.edge_distance = edgeD;
                            infoSame.point = hitPt;
                            infoSame.normal = norm;
                            infoSame.penetration = dist;
                        }
                    }
                }

                // we've checked all edges on BodyB.
                if ((found) && (closestAway > 0.3f) && (closestSame < closestAway))
                {
                    infoSame.penetration = (float)Math.Sqrt(infoSame.penetration);
                    data.Add(infoSame);
                }
                else
                {
                    infoAway.penetration = (float)Math.Sqrt(infoAway.penetration);
                    data.Add(infoAway);
                }
            }

            return data;
        }