public void PreparePhysicsEngine(World.World worldState)
{
if (worldState.StaticGeometry.Revision != TerrainRevision)
UpdateTerrainBody(worldState.StaticGeometry);
TerrainRevision = worldState.StaticGeometry.Revision;
worldState.IsSomethingMoving = false;
// Add Bodies for new entities
var entities = worldState.Entities.ToArray();
foreach (var e in entities)
{
if (e.Disposed || e.Position.LengthSquared() > 100 * 100 || e.Position.Y < -10)
{
if (e.Position.Y < -10 && e as Ball != null) // the player drowned
Game.Services.GetService<Sound.SoundControl>().PlaySound(Sound.SoundControl.DrownSound);
RemoveEntity(e, worldState);
continue;
}
Body body = e.PhysicsBody;
if (body == null)
{
body = new Body(PhysicsWorld);
body.BodyType = e.IsStatic ? BodyType.Static : BodyType.Dynamic;
body.SleepingAllowed = true;
body.Awake = true;
body.CreateFixture(new CircleShape(e.Radius, 1.0f));
e.PhysicsBody = body;
EntityIdByPhysicsBody[body] = e.ID;
if (e is Ball)
{
body.Friction = 2.0f;
body.Restitution = 0.1f;
body.FixedRotation = true;
body.Mass = 10f;
}
if (e is Shot)
{
var shot = e as Shot;
body.Restitution = shot.Restitution;
body.OnCollision += (a, b, contact) =>
{
Vector2 normal;
FixedArray2<Vector2> points;
contact.GetWorldManifold(out normal, out points);
Fixture targetFixture;
if (contact.FixtureA.Body == shot.PhysicsBody)
targetFixture = contact.FixtureB;
else
targetFixture = contact.FixtureA;
if (TerrainBodies.Contains(targetFixture.Body))
{
// Shot collides with terrain
shot.OnTerrainCollision(worldState.StaticGeometry, points[0]);
}
else if (EntityIdByPhysicsBody.ContainsKey(targetFixture.Body))
{
int entityId = EntityIdByPhysicsBody[targetFixture.Body];
Entity entity = worldState.EntityById(entityId);
// Mutual collision
if (entity != null)
{
entity.OnEntityCollision(shot);
shot.OnEntityCollision(entity);
}
}
return true;
};
}
}
if (body.Position != e.Position || body.Rotation != e.Rotation)
body.SetTransform(e.Position, e.Rotation);
if (body.LinearVelocity != e.Velocity)
// Apparently, the physics engine likes applying an impulse better than overwriting the velocity.
// So, apply an impulse that changes the old velocity to the new one.
body.ApplyLinearImpulse(body.Mass * (e.Velocity - body.LinearVelocity));
if (body.LinearVelocity.LengthSquared() > 0.0001 || body.AngularVelocity > 0.001)
{
worldState.IsSomethingMoving = true;
}
}
}