using System.Collections.Generic;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using FarseerPhysics.Collision;
using FarseerPhysics.SamplesFramework;
namespace Labyrinth
{
public class Ball
{
private Body body;
private Category collidesWith;
private Category collisionCategories;
private Sprite sprite;
private PhysicsGameScreen screen;
private Vector2 velocityBeforeImpact;
private Vector2 velocityAfterImpact;
private Vector2 lastVelocityAfterImpact = Vector2.Zero;
private Vector2 deltaVelocity;
public event BeforeCollisionEventHandler beforeCollision;
public event AfterCollisionEventHandler afterCollision;
public delegate void BallCollisionEventHandler(float deltaVelocity);
public event BallCollisionEventHandler BallCollided;
public Ball(World world, PhysicsGameScreen screen, Vector2 startPosition, float radius, bool isStatic)
{
CreateObject(world, screen, ref startPosition, radius, isStatic);
}
private void CreateObject(World world, PhysicsGameScreen screen, ref Vector2 startPosition, float radius, bool isStatic)
{
this.screen = screen;
body = BodyFactory.CreateCircle(world, radius, 1f);
body.BodyType = BodyType.Dynamic;
body.Position = startPosition;
body.Restitution = .2f;
body.Friction = .2f;
body.CollisionCategories = Category.All;
body.CollidesWith = Category.All;
body.IsStatic = isStatic;
body.FixtureList[0].BeforeCollision = new BeforeCollisionEventHandler((fixtureA, fixtureB) =>
{
velocityBeforeImpact = fixtureA.Body.LinearVelocity;
if (beforeCollision != null)
{
beforeCollision(fixtureA, fixtureB);
}
return true;
});
body.FixtureList[0].AfterCollision = new AfterCollisionEventHandler((fixtureA, fixtureB, contact) =>
{
velocityAfterImpact = fixtureA.Body.LinearVelocity;
deltaVelocity = velocityAfterImpact - lastVelocityAfterImpact;
if (BallCollided != null)
{
BallCollided(deltaVelocity.Length());
}
if (afterCollision != null)
{
afterCollision(fixtureA, fixtureB, contact);
}
lastVelocityAfterImpact = velocityAfterImpact;
});
//GFX
AssetCreator creator = screen.ScreenManager.Assets;
sprite = new Sprite(creator.CircleTexture(radius, MaterialType.Dots, Color.DarkRed, 0.8f));
}
public Category CollisionCategories
{
get { return collisionCategories; }
set
{
collisionCategories = value;
body.CollisionCategories = collisionCategories;
}
}
public Category CollidesWith
{
get { return collidesWith; }
set
{
collidesWith = value;
body.CollidesWith = collidesWith;
}
}
public void Draw()
{
Draw(sprite.Texture, null, new Vector2(0,0));
}
public void Draw(Texture2D texture, Texture2D shadowTexture, Vector2 shadowOffset)
{
SpriteBatch batch = screen.ScreenManager.SpriteBatch;
DrawShadow(shadowTexture, shadowOffset, batch);
DrawObject(texture, batch);
}
private void DrawObject(Texture2D texture, SpriteBatch batch)
{
batch.Draw(texture, ConvertUnits.ToDisplayUnits(body.Position), null,
Color.White, 0f, sprite.Origin, 1f, SpriteEffects.None, 0f);
}
private void DrawShadow(Texture2D shadowTexture, Vector2 shadowOffset, SpriteBatch batch)
{
if (shadowTexture != null)
{
batch.Draw(shadowTexture, ConvertUnits.ToDisplayUnits(body.Position) - shadowOffset, null,
Color.White, 0f, sprite.Origin, 1f, SpriteEffects.None, 0f);
}
}
}
}