public Projectile(Player creator, float x, float y, float width, float height) : base(creator, 0, 0) { /* Create New Projectile Body */ BodyDef def = new BodyDef(); def.IsBullet = true; def.Position = creator.body.GetPosition() + new Vec2(x, y); projectile = creator.body.GetWorld().CreateBody(def); /* Create a fixture for the projectile */ PolygonDef fixdef = new PolygonDef(); fixdef.Density = 1.0f; fixdef.SetAsBox(width / 2, height / 2); fixdef.Filter.GroupIndex = creator.ID; fixture = projectile.CreateFixture(fixdef); fixture.Filter.CategoryBits = 0x0004; fixture.Filter.MaskBits = 0xFFFF; /* Made a 2nd fixture, one to observe all collisions */ fixdef.IsSensor = true; fix2 = projectile.CreateFixture(fixdef); fix2.UserData = this; /* Finally, give this projectile some mass */ projectile.SetMassFromShapes(); /* Also, make sure we destroy the projectile when it is time */ this.OnDestroy += Cleanup; }
public PolygonContact(Fixture fixtureA, Fixture fixtureB) : base(fixtureA, fixtureB) { Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.PolygonShape); Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.PolygonShape); CollideShapeFunction = CollidePolygons; }
public CircleContact(Fixture fixtureA, Fixture fixtureB) : base(fixtureA, fixtureB) { Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.CircleShape); Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape); CollideShapeFunction = CollideCircles; }
public Breakable() { // Ground body { BodyDef bd = new BodyDef(); Body ground = _world.CreateBody(bd); PolygonShape shape = new PolygonShape(); shape.SetAsEdge(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); ground.CreateFixture(shape, 0); } // Breakable dynamic body { BodyDef bd = new BodyDef(); bd.Position.Set(0.0f, 40.0f); bd.Angle = 0.25f * Box2DX.Common.Settings.PI; _body1 = _world.CreateBody(bd); _shape1.SetAsBox(0.5f, 0.5f, new Vec2(-0.5f, 0.0f), 0.0f); _piece1 = _body1.CreateFixture(_shape1, 1.0f); _shape2.SetAsBox(0.5f, 0.5f, new Vec2(0.5f, 0.0f), 0.0f); _piece2 = _body1.CreateFixture(_shape2, 1.0f); } _break = false; _broke = false; }
public override float ReportFixture(Fixture fixture, Vec2 point, Vec2 normal, float fraction) { _fixture = fixture; _point = point; _normal = normal; return fraction; }
public Fixture() { UserData = null; Body = null; _next = null; ProxyId = BroadPhase.NullProxy; Shape = null; }
public EdgeAndCircleContact(Fixture fixtureA, Fixture fixtureB) : base(fixtureA, fixtureB) { Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.EdgeShape); Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape); _manifold.PointCount = 0; _manifold.Points[0].NormalImpulse = 0.0f; _manifold.Points[0].TangentImpulse = 0.0f; CollideShapeFunction = CollideEdgeAndCircle; }
/// <summary> /// Return true if the given shape should be considered for ray intersection. /// </summary> public bool RayCollide(object userData, Fixture fixture) { //By default, cast userData as a shape, and then collide if the shapes would collide if (userData == null) { return true; } return ShouldCollide((Fixture)userData, fixture); }
/// <summary> /// Return true if contact calculations should be performed between these two shapes. /// If you implement your own collision filter you may want to build from this implementation. /// @warning for performance reasons this is only called when the AABBs begin to overlap. /// </summary> public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB) { FilterData filterA = fixtureA.Filter; FilterData filterB = fixtureB.Filter; if (filterA.GroupIndex == filterB.GroupIndex && filterA.GroupIndex != 0) { return filterA.GroupIndex > 0; } bool collide = (filterA.MaskBits & filterB.CategoryBits) != 0 && (filterA.CategoryBits & filterB.MaskBits) != 0; return collide; }
public SensorTest() { { BodyDef bd = new BodyDef(); Body ground = _world.CreateBody(bd); { PolygonShape shape = new PolygonShape(); shape.SetAsEdge(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); ground.CreateFixture(shape, 0); } #if false { b2FixtureDef sd; sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f); sd.isSensor = true; m_sensor = ground->CreateFixture(&sd); } #else { CircleShape shape = new CircleShape(); shape._radius = 5.0f; shape._p.Set(0.0f, 10.0f); FixtureDef fd = new FixtureDef(); fd.Shape = shape; fd.IsSensor = true; _sensor = ground.CreateFixture(fd); } #endif } { CircleShape shape = new CircleShape(); shape._radius = 1.0f; for (int i = 0; i < _count; ++i) { BodyDef bd = new BodyDef(); bd.Position.Set(-10.0f + 3.0f * i, 20.0f); bd.UserData = false; _bodies[i] = _world.CreateBody(bd); _bodies[i].CreateFixture(shape, 1.0f); } } }
/// Called for each fixture found in the query AABB. /// @return false to terminate the query. public abstract bool ReportFixture(Fixture fixture);
public void Create(BroadPhase broadPhase, Body body, XForm xf, FixtureDef def) { UserData = def.UserData; Friction = def.Friction; Restitution = def.Restitution; Density = def.Density; _body = body; _next = null; Filter = def.Filter; _isSensor = def.IsSensor; _type = def.Type; // Allocate and initialize the child shape. switch (_type) { case ShapeType.CircleShape: { CircleShape circle = new CircleShape(); CircleDef circleDef = (CircleDef)def; circle._position = circleDef.LocalPosition; circle._radius = circleDef.Radius; _shape = circle; } break; case ShapeType.PolygonShape: { PolygonShape polygon = new PolygonShape(); PolygonDef polygonDef = (PolygonDef)def; polygon.Set(polygonDef.Vertices, polygonDef.VertexCount); _shape = polygon; } break; case ShapeType.EdgeShape: { EdgeShape edge = new EdgeShape(); EdgeDef edgeDef = (EdgeDef)def; edge.Set(edgeDef.Vertex1, edgeDef.Vertex2); _shape = edge; } break; default: Box2DXDebug.Assert(false); break; } // Create proxy in the broad-phase. AABB aabb; _shape.ComputeAABB(out aabb, xf); bool inRange = broadPhase.InRange(aabb); // You are creating a shape outside the world box. Box2DXDebug.Assert(inRange); if (inRange) { _proxyId = broadPhase.CreateProxy(aabb, this); } else { _proxyId = PairManager.NullProxy; } }
private void DrawFixture(Fixture fixture, Transform xf, Color color, bool core) { #warning "the core argument is not used, the coreColor variable is also not used" Color coreColor = new Color(0.9f, 0.6f, 0.6f); switch (fixture.ShapeType) { case ShapeType.CircleShape: { CircleShape circle = (CircleShape)fixture.Shape; Vector2 center = xf.TransformPoint(circle._position); float radius = circle._radius; // [CHRISK] FIXME Vector2 axis = xf.R.Col1; //_debugDraw.DrawSolidCircle(center, radius, axis, color); } break; case ShapeType.PolygonShape: { PolygonShape poly = (PolygonShape)fixture.Shape; int vertexCount = poly._vertexCount; Vector2[] localVertices = poly._vertices; Box2DXDebug.Assert(vertexCount <= Settings.MaxPolygonVertices); Vector2[] vertices = new Vector2[Settings.MaxPolygonVertices]; for (int i = 0; i < vertexCount; ++i) { vertices[i] = xf.TransformPoint(localVertices[i]); } _debugDraw.DrawSolidPolygon(vertices, vertexCount, color); } break; case ShapeType.EdgeShape: { EdgeShape edge = (EdgeShape)fixture.Shape; _debugDraw.DrawSegment(xf.TransformPoint(edge.Vertex1), xf.TransformPoint(edge.Vertex2), color); } break; } }
public PolyAndCircleContact(Fixture fixtureA, Fixture fixtureB) : base(fixtureA, fixtureB) { Box2DXDebug.Assert(_fixtureA.GetType() == ShapeType.PolygonShape); Box2DXDebug.Assert(_fixtureB.GetType() == ShapeType.CircleShape); }
/// Destroy a fixture. This removes the fixture from the broad-phase and /// therefore destroys any contacts associated with this fixture. All fixtures /// attached to a body are implicitly destroyed when the body is destroyed. /// @param fixture the fixture to be removed. /// @warning This function is locked during callbacks. public void DestroyFixture(ref Fixture fixture) { Box2DXDebug.Assert(_world.IsLocked() == false); if (_world.IsLocked() == true) { return; } Box2DXDebug.Assert(fixture.Body == this); // Remove the fixture from this body's singly linked list. Box2DXDebug.Assert(_fixtureCount > 0); Fixture node = _fixtureList; bool found = false; while (node != null) { if (node == fixture) { _fixtureList = fixture._next; found = true; break; } node = node._next; } // You tried to remove a shape that is not attached to this body. Box2DXDebug.Assert(found); // Destroy any contacts associated with the fixture. ContactEdge edge = _contactList; while (edge != null) { Contact c = edge.Contact; edge = edge.Next; Fixture fixtureA = c.GetFixtureA(); Fixture fixtureB = c.GetFixtureB(); if (fixture == fixtureA || fixture == fixtureB) { // This destroys the contact and removes it from // this body's contact list. _world._contactManager.Destroy(c); } } bool needMassUpdate = fixture._massData.Mass > 0.0f || fixture._massData.I > 0.0f; BroadPhase broadPhase = _world._contactManager._broadPhase; fixture.Destroy(broadPhase); fixture.Body = null; fixture._next = null; --_fixtureCount; // Adjust mass properties if needed. if (needMassUpdate) { ResetMass(); } }
public static Contact Create(Fixture fixtureA, Fixture fixtureB) { if (Initialized == false) { InitializeRegisters(); Initialized = true; } ShapeType type1 = fixtureA.GetType(); ShapeType type2 = fixtureB.GetType(); Box2DXDebug.Assert(ShapeType.UnknownShape < type1 && type1 < ShapeType.ShapeTypeCount); Box2DXDebug.Assert(ShapeType.UnknownShape < type2 && type2 < ShapeType.ShapeTypeCount); ContactCreateFcn createFcn = Registers[(int)type1][(int)type2].CreateFcn; if (createFcn != null) { if (Registers[(int)type1][(int)type2].Primary) { return createFcn(fixtureA, fixtureB); } else { return createFcn(fixtureB, fixtureA); } } else { return null; } }
public void MouseDown(Vec2 p) { if (_mouseJoint != null) { return; } // Make a small box. AABB aabb = new AABB(); Vec2 d = new Vec2(); d.Set(0.001f, 0.001f); aabb.LowerBound = p - d; aabb.UpperBound = p + d; // Query the world for overlapping shapes. int k_maxCount = 10; Fixture[] shapes = new Fixture[k_maxCount]; int count = _world.Query(aabb, shapes, k_maxCount); Body body = null; for (int i = 0; i < count; ++i) { Body shapeBody = shapes[i].Body; if (shapeBody.IsStatic() == false && shapeBody.GetMass() > 0.0f) { bool inside = shapes[i].TestPoint(p); if (inside) { body = shapes[i].Body; break; } } } if (body != null) { MouseJointDef md = new MouseJointDef(); md.Body1 = _world.GetGroundBody(); md.Body2 = body; md.Target = p; #if TARGET_FLOAT32_IS_FIXED md.MaxForce = (body.GetMass() < 16.0f)? (1000.0f * body.GetMass()) : 16000.0f; #else md.MaxForce = 1000.0f * body.GetMass(); #endif _mouseJoint = (MouseJoint)_world.CreateJoint(md); body.WakeUp(); } }
// We need separation create/destroy functions from the constructor/destructor because // the destructor cannot access the allocator or broad-phase (no destructor arguments allowed by C++). public void Create(BroadPhase broadPhase, Body body, Transform xf, FixtureDef def) { UserData = def.UserData; Friction = def.Friction; Restitution = def.Restitution; Body = body; _next = null; Filter = def.Filter; IsSensor = def.IsSensor; Shape = def.Shape.Clone(); Shape.ComputeMass(out _massData, def.Density); // Create proxy in the broad-phase. Shape.ComputeAABB(out Aabb, ref xf); ProxyId = broadPhase.CreateProxy(Aabb, this); }
/// <summary> /// Called when any shape is about to be destroyed due /// to the destruction of its parent body. /// </summary> public abstract void SayGoodbye(Fixture fixture);
public override void SayGoodbye(Fixture shape) { ; }
/// Called for each fixture found in the query. You control how the ray proceeds /// by returning a float that indicates the fractional length of the ray. By returning /// 0, you set the ray length to zero. By returning the current fraction, you proceed /// to find the closest point. By returning 1, you continue with the original ray /// clipping. /// @param fixture the fixture hit by the ray /// @param point the point of initial intersection /// @param normal the normal vector at the point of intersection /// @return 0 to terminate, fraction to clip the ray for /// closest hit, 1 to continue public abstract float ReportFixture(Fixture fixture, Vec2 point, Vec2 normal, float fraction);
void Break() { // Create two bodies from one. Body body1 = _piece1.GetBody(); Vec2 center = body1.GetWorldCenter(); body1.DestroyFixture(ref _piece2); _piece2 = null; BodyDef bd = new BodyDef(); bd.Position = body1.GetPosition(); bd.Angle = body1.GetAngle(); Body body2 = _world.CreateBody(bd); _piece2 = body2.CreateFixture(_shape2, 1.0f); // Compute consistent velocities for new bodies based on // cached velocity. Vec2 center1 = body1.GetWorldCenter(); Vec2 center2 = body2.GetWorldCenter(); Vec2 velocity1 = _velocity + Vec2.Cross(_angularVelocity, center1 - center); Vec2 velocity2 = _velocity + Vec2.Cross(_angularVelocity, center2 - center); body1.SetAngularVelocity(_angularVelocity); body1.SetLinearVelocity(velocity1); body2.SetAngularVelocity(_angularVelocity); body2.SetLinearVelocity(velocity2); }
/// <summary> /// Return true if contact calculations should be performed between these two shapes. /// If you implement your own collision filter you may want to build from this implementation. /// @warning for performance reasons this is only called when the AABBs begin to overlap. /// </summary> public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB) { Filter filter1 = fixtureA.GetFilterData(); Filter filter2 = fixtureB.GetFilterData(); if (filter1.GroupIndex == filter2.GroupIndex && filter1.GroupIndex != 0) { return filter1.GroupIndex > 0; } bool collide = (filter1.MaskBits & filter2.CategoryBits) != 0 && (filter1.CategoryBits & filter2.MaskBits) != 0; return collide; }
/// Creates a fixture and attach it to this body. Use this function if you need /// to set some fixture parameters, like friction. Otherwise you can create the /// fixture directly from a shape. /// This function automatically updates the mass of the body. /// @param def the fixture definition. /// @warning This function is locked during callbacks. public Fixture CreateFixture(FixtureDef def) { Box2DXDebug.Assert(_world.IsLocked() == false); if (_world.IsLocked() == true) { return null; } BroadPhase broadPhase = _world._contactManager._broadPhase; Fixture fixture = new Fixture(); fixture.Create(broadPhase, this, _xf, def); fixture._next = _fixtureList; _fixtureList = fixture; ++_fixtureCount; fixture.Body = this; bool needMassUpdate = fixture._massData.Mass > 0.0f || fixture._massData.I > 0.0f; // Adjust mass properties if needed. if (needMassUpdate) { ResetMass(); } // Let the world know we have a new fixture. This will cause new contacts // to be created at the beginning of the next time step. _world._flags |= World.WorldFlags.NewFixture; return fixture; }
/// Query the world for all shapes that potentially overlap the /// provided AABB. You provide a shape pointer buffer of specified /// size. The number of shapes found is returned. /// @param aabb the query box. /// @param shapes a user allocated shape pointer array of size maxCount (or greater). /// @param maxCount the capacity of the shapes array. /// @return the number of shapes found in aabb. public int Query(AABB aabb, Fixture[] fixtures, int maxCount) { //using (object[] results = new object[maxCount]) { object[] results = new object[maxCount]; int count = _broadPhase.Query(aabb, results, maxCount); for (int i = 0; i < count; ++i) { fixtures[i] = (Fixture)results[i]; } results = null; return count; } }
private Transform _xf; // the body origin transform #endregion Fields #region Constructors internal Body(BodyDef bd, World world) { _flags = 0; if (bd.IsBullet) { _flags |= BodyFlags.Bullet; } if (bd.FixedRotation) { _flags |= BodyFlags.FixedRotation; } if (bd.AllowSleep) { _flags |= BodyFlags.AllowSleep; } if (bd.IsSleeping) { _flags |= BodyFlags.Sleep; } _world = world; _xf.Position = bd.Position; _xf.R.Set(bd.Angle); _sweep.LocalCenter.SetZero(); _sweep.T0 = 1.0f; _sweep.A0 = _sweep.A = bd.Angle; _sweep.C0 = _sweep.C = Math.Mul(_xf, _sweep.LocalCenter); _jointList = null; _contactList = null; _prev = null; _next = null; _linearVelocity = bd.LinearVelocity; _angularVelocity = bd.AngularVelocity; _linearDamping = bd.LinearDamping; _angularDamping = bd.AngularDamping; _force.Set(0.0f, 0.0f); _torque = 0.0f; _sleepTime = 0.0f; _mass = 0; _invMass = 0.0f; _I = 0.0f; _invI = 0.0f; _type = BodyType.Static; _userData = bd.UserData; _fixtureList = null; _fixtureCount = 0; }
/// <summary> /// Query the world for all shapes that intersect a given segment. You provide a shap /// pointer buffer of specified size. The number of shapes found is returned, and the buffer /// is filled in order of intersection. /// </summary> /// <param name="segment">Defines the begin and end point of the ray cast, from p1 to p2. /// Use Segment.Extend to create (semi-)infinite rays.</param> /// <param name="shapes">A user allocated shape pointer array of size maxCount (or greater).</param> /// <param name="maxCount">The capacity of the shapes array.</param> /// <param name="solidShapes">Determines if shapes that the ray starts in are counted as hits.</param> /// <param name="userData">Passed through the worlds contact filter, with method RayCollide. This can be used to filter valid shapes.</param> /// <returns>The number of shapes found</returns> public int Raycast(Segment segment, out Fixture[] fixtures, int maxCount, bool solidShapes, object userData) { #warning "PTR" _raycastSegment = segment; _raycastUserData = userData; _raycastSolidShape = solidShapes; object[] results = new object[maxCount]; fixtures = new Fixture[maxCount]; int count = _broadPhase.QuerySegment(segment, results, maxCount, RaycastSortKey); for (int i = 0; i < count; ++i) { fixtures[i] = (Fixture)results[i]; } return count; }
new public static Contact Create(Fixture fixtureA, Fixture fixtureB) { return new CircleContact(fixtureA, fixtureB); }
/// <summary> /// Re-filter a fixture. This re-runs contact filtering on a fixture. /// </summary> public void Refilter(Fixture fixture) { Box2DXDebug.Assert(_lock == false); fixture.RefilterProxy(_broadPhase, fixture.Body.GetTransform()); }
public static new Contact Create(Fixture fixtureA, Fixture fixtureB) { return new PolyAndCircleContact(fixtureA, fixtureB); }
// TODO_ERIN adjust linear velocity and torque to account for movement of center. /// <summary> /// Compute the mass properties from the attached shapes. You typically call this /// after adding all the shapes. If you add or remove shapes later, you may want /// to call this again. Note that this changes the center of mass position. /// </summary> public void SetMassFromShapes() { Box2DXDebug.Assert(_world._lock == false); if (_world._lock == true) { return; } // Compute mass data from shapes. Each shape has its own density. _mass = 0.0f; _invMass = 0.0f; _I = 0.0f; _invI = 0.0f; Vector2 center = Vector2.zero; for (Fixture f = _fixtureList; f != null; f = f.Next) { MassData massData; f.ComputeMass(out massData); _mass += massData.Mass; center += massData.Mass * massData.Center; _I += massData.I; } // Compute center of mass, and shift the origin to the COM. if (_mass > 0.0f) { _invMass = 1.0f / _mass; center *= _invMass; } if (_I > 0.0f && (_flags & BodyFlags.FixedRotation) == 0) { // Center the inertia about the center of mass. _I -= _mass * Vector2.Dot(center, center); Box2DXDebug.Assert(_I > 0.0f); _invI = 1.0f / _I; } else { _I = 0.0f; _invI = 0.0f; } // Move center of mass. _sweep.LocalCenter = center; _sweep.C0 = _sweep.C = _xf.TransformPoint(_sweep.LocalCenter); BodyType oldType = _type; if (_invMass == 0.0f && _invI == 0.0f) { _type = BodyType.Static; } else { _type = BodyType.Dynamic; } // If the body type changed, we need to refilter the broad-phase proxies. if (oldType != _type) { for (Fixture f = _fixtureList; f != null; f = f.Next) { f.RefilterProxy(_world._broadPhase, _xf); } } }