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; }
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); }
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(); } }
public void Draw(Body body, Camera camera) { Draw(body, camera, false, true, true, false, true, false); }
public void Add(Body body) { if (!body_list.Contains(body)) body_list.Add(body); }
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); }
public void Remove(Body body) { if (body_list.Contains(body)) body_list.Remove(body); }
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++; }
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; }
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; }
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); } }
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; }