static class EntityManager
{
static private List WorldEntityList = new List ();
static public void AddEntityToWorld( DynamicSprite NewEntity )
{
if(!(WorldEntityList.Contains(NewEntity)) )
WorldEntityList.Add (NewEntity);
}
///
/// Update all entity in the game
///
static public void Update( GameTime gameTime )
{
if ( WorldEntityList.Count > 0 )
{
foreach ( DynamicSprite Entity in WorldEntityList )
{
// if the Entity is no more active no more visible delete it
if ( !(Entity.IsActive && Entity.IsVisible) )
{
WorldEntityList.Remove(Entity) ;
}
if ( Entity.IsActive )
{
Entity.Update (gameTime);
if ( Entity.IsVisible )
{
// Get the index of area of each corner of the sprite
Entity.AddNewAreaLocationIndex (AreaManager.GetAreaIndex (Entity.UpperLeftCorner));
AreaManager.GetArea (Entity.UpperLeftCorner).AddEntity(Entity);
Entity.AddNewAreaLocationIndex (AreaManager.GetAreaIndex (Entity.UpperRightCorner));
AreaManager.GetArea (Entity.UpperRightCorner).AddEntity (Entity);
Entity.AddNewAreaLocationIndex (AreaManager.GetAreaIndex (Entity.BottomLeftCorner));
AreaManager.GetArea (Entity.BottomLeftCorner).AddEntity (Entity);
Entity.AddNewAreaLocationIndex (AreaManager.GetAreaIndex (Entity.BottomRightCorner));
AreaManager.GetArea (Entity.BottomRightCorner).AddEntity (Entity);
}
}
}
}
}
///
/// Draw all entity in the game
///
static public void Draw( SpriteBatch spriteBatch, GraphicsDevice gpdevice )
{
if ( WorldEntityList.Count > 0 )
foreach ( DynamicSprite Entity in WorldEntityList )
if ( Entity.IsVisible )
Entity.Draw (spriteBatch,gpdevice);
}
}
static class AreaManager
{
// The number of area in horiztontal and vertical side
static private int m_NumberOfAreaHorizontaly;
static private int m_NumberOfAreaVerticaly;
static private float m_EntityPositionXToAreaIndexFactor;
static private float m_EntityPositionYToAreaIndexFactor;
// list of the area
static private List AreaInGameWorld = new List ();
///
/// Get the number of area in horizontal side
///
static public int NumberOfAreaHorizontaly
{
get { return m_NumberOfAreaHorizontaly ; }
}
///
/// Get the number of area in Vertival side
///
static public int NumberOfAreaVerticaly
{
get { return m_NumberOfAreaVerticaly; }
}
#region Methods
///
/// Install the manager by putting the area in place
///
static public void InstallAreaManager( GraphicsDevice graphicDevice, int NewAreaInHorizotal,
int NewAreaInVertical, Rectangle NewAreaSize )
{
m_NumberOfAreaHorizontaly = NewAreaInHorizotal;
m_NumberOfAreaVerticaly = NewAreaInVertical;
// because multiplication is faster than devision☺
m_EntityPositionXToAreaIndexFactor = ( 1 / NewAreaSize.Width );
m_EntityPositionYToAreaIndexFactor = ( 1 / NewAreaSize.Height );
// put in place the Area
for(int i = 0; i < NewAreaInVertical;i++)
for ( int j = 0; j < NewAreaInHorizotal; j++ )
{
Rectangle newrect = new Rectangle (( j * NewAreaSize.Width )+2,
( i * NewAreaSize.Height )+2, NewAreaSize.Width, NewAreaSize.Height);
AreaInGameWorld.Add (new WorldArea (graphicDevice, newrect));
}
}
///
/// retur the Index of area in the list by referd index i,j
///
static public int GetAreaIndexFromXY(int NewIndexJ,int NewIndexI)
{
return ( ( NewIndexI * AreaManager.NumberOfAreaHorizontaly ) + NewIndexJ );
}
///
/// return the Index Of Area refered by X and Y entity position
///
public static int GetAreaIndex( int NewEntityPositionX, int NewEntityPositionY )
{
return (int)(
( NewEntityPositionX * m_EntityPositionXToAreaIndexFactor )*
m_NumberOfAreaVerticaly+ (NewEntityPositionY * m_EntityPositionYToAreaIndexFactor)
);
}
///
/// return the Index Of Area refered by X and Y entity position
///
public static int GetAreaIndex( Vector2 NewPosition )
{
return (int)(
( NewPosition.X * m_EntityPositionXToAreaIndexFactor ) *
m_NumberOfAreaVerticaly + ( NewPosition.Y * m_EntityPositionYToAreaIndexFactor )
);
}
///
/// return the Index Of Area refered by X and Y entity position
///
public static int GetAreaIndex( Rectangle NewPosition )
{
return (int)(
( NewPosition.X * m_EntityPositionXToAreaIndexFactor ) *
m_NumberOfAreaVerticaly + ( NewPosition.Y * m_EntityPositionYToAreaIndexFactor )
);
}
///
/// retur the area refered by X and Y entity position
///
public static WorldArea GetArea( Rectangle NewPosition )
{
return AreaInGameWorld[(int)(
( NewPosition.X * m_EntityPositionXToAreaIndexFactor ) *
m_NumberOfAreaVerticaly + ( NewPosition.Y * m_EntityPositionYToAreaIndexFactor )
)];
}
///
/// retur the area refered by X and Y entity position
///
public static WorldArea GetArea( Vector2 NewPosition )
{
return AreaInGameWorld[(int)(
( NewPosition.X * m_EntityPositionXToAreaIndexFactor ) *
m_NumberOfAreaVerticaly + ( NewPosition.Y * m_EntityPositionYToAreaIndexFactor )
)];
}
///
/// retur the area in the list by referd index i,j
///
public static WorldArea GetArea( int NewIndexI, int NewIndexJ )
{
return AreaInGameWorld[( NewIndexI * m_NumberOfAreaVerticaly ) + NewIndexJ];
}
///
/// retur All the area in a List
///
public static List GetAreaList( )
{
return AreaInGameWorld;
}
///
/// Update All The Area
///
static public void Update( GameTime gametime )
{
foreach ( WorldArea area in AreaInGameWorld )
{
area.Update (gametime);
}
}
///
/// Draw All Area
///
static public void Draw( SpriteBatch spriteBatch )
{
foreach ( WorldArea area in AreaInGameWorld )
{
area.Draw (spriteBatch);
}
}
#endregion
}
class WorldArea
{
//The limite of the area (x,y,width,Heigth)
private Rectangle m_AreaBound;
//The limite of the area (x,y,width,Heigth)
private Rectangle m_ShowedArea;
// This will be used when we draw the Area
private Texture2D m_SurfaceToDraw;
//The color of showen area
private Color m_ColorOfTheArea = Color.Blue;
// All entity in the area
private List EntityIntheArea = new List ();
#region Get/Set
///
/// The Area size and position
///
public Rectangle Area
{
get
{
return m_AreaBound;
}
}
///
/// the surface represeting the area when it will be drawen
///
public Texture2D Surface
{
get
{
return m_SurfaceToDraw;
}
}
///
/// The color of the Area Surface
///
public Color AreaColor
{
get
{
return m_ColorOfTheArea;
}
set
{
m_ColorOfTheArea = value;
}
}
#endregion
#region Constructor
///
/// Creat new WorldArea
///
public WorldArea( GraphicsDevice NewGraphicDevice, int NewX, int NewY, int NewWidth, int NewHeight )
{
m_AreaBound = new Rectangle (NewX, NewY, NewWidth, NewHeight);
m_ShowedArea = new Rectangle (m_AreaBound.X + 1, m_AreaBound.Y + 1,
m_AreaBound.Width - 1, m_AreaBound.Height - 1);
m_SurfaceToDraw = new Texture2D (NewGraphicDevice, 1, 1);
m_SurfaceToDraw.SetData (new Color[] { m_ColorOfTheArea });
}
///
/// Creat new WorldArea
///
public WorldArea( GraphicsDevice NewGraphicDevice, Rectangle NewRect )
{
m_AreaBound = NewRect;
m_ShowedArea = new Rectangle (m_AreaBound.X + 1, m_AreaBound.Y + 1,
m_AreaBound.Width - 1, m_AreaBound.Height - 1);
m_SurfaceToDraw = new Texture2D (NewGraphicDevice, 1, 1);
m_SurfaceToDraw.SetData (new Color[] { m_ColorOfTheArea });
}
#endregion
#region Methods
///
/// Add Entity to the Area Entity list
///
public void AddEntity( DynamicSprite NewEntity )
{
if ( !( EntityIntheArea.Contains (NewEntity) ) )
EntityIntheArea.Add (NewEntity);
}
///
/// Update the Area
///
public void Update( GameTime gameTime )
{
if ( EntityIntheArea.Count > 0 )
{
for ( int i = 0; i < EntityIntheArea.Count; i++ )
{
//Do not check collision betwen the same object
int EntityItSelfIndex = i;
for ( int j = 0; j < EntityIntheArea.Count; j++ )
{
if ( j != EntityItSelfIndex )
{
if ( EntityIntheArea[j].CollisionBox.Intersects (EntityIntheArea[i].CollisionBox) )
CollisionManager.AddCollisionUnite (EntityIntheArea[j], EntityIntheArea[i]);
}
}
}
}
// the Entity list it will update evrey frame,
//we should clear it after checking all entity collision possibility
EntityIntheArea.Clear ();
}
///
/// Draw The Area
///
public void Draw( SpriteBatch spriteBatch )
{
spriteBatch.Draw (m_SurfaceToDraw, m_ShowedArea, m_ColorOfTheArea);
}
#endregion
}
class CollisionUnite
{
// the tow entity to collide, we name it "Collision Unite"
private DynamicSprite m_EntityA = null;
private DynamicSprite m_EntityB = null;
#region Set/Get
///
/// The First Entity in a collision event
///
public DynamicSprite EntityA
{
get
{
return m_EntityA;
}
set{
m_EntityA = value;
}
}
///
/// The Second Entity in a collision event
///
public DynamicSprite EntityB
{
get
{
return m_EntityB;
}
set
{
m_EntityB = value;
}
}
#endregion
#region Constructor
///
/// Creat a Empty Collision unite
///
public CollisionUnite( )
{
m_EntityA = null;
m_EntityB = null;
}
///
/// Creat a defined Collision unite
///
public CollisionUnite(DynamicSprite NewEntityA, DynamicSprite NewEntityB )
{
m_EntityA = NewEntityA;
m_EntityB = NewEntityB;
}
#endregion
}
static class CollisionManager
{
// store all Collidable Sprite
static private Queue CollisionEventList = new Queue ();
///
/// Add Collision unite to the Queue event
///
static public void AddCollisionUnite( CollisionUnite NewCollsionUnite )
{
if ( !( CollisionEventList.Contains (NewCollsionUnite ) ) && NewCollsionUnite!=null )
CollisionEventList.Enqueue (NewCollsionUnite);
}
///
/// Add Collision unite to the Queue event
///
static public void AddCollisionUnite( DynamicSprite NewEntityA, DynamicSprite NewEntityB )
{
if ( !(CollisionEventList.Contains (new CollisionUnite (NewEntityA, NewEntityB))) )
CollisionEventList.Enqueue ( new CollisionUnite(NewEntityA, NewEntityB) );
}
///
/// execut all Collision in the que
///
static public void ExecuteCollisionEvent( )
{
foreach(CollisionUnite collisionUnite in CollisionEventList )
{
collisionUnite.EntityA.OnCollide (collisionUnite.EntityB);
collisionUnite.EntityB.OnCollide (collisionUnite.EntityA);
}
CollisionEventList.Clear ();
}
}
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D TankSprite;
DynamicSprite Tank;
DynamicSprite Tank2;
DynamicSprite Tank3;
public Game1( )
{
graphics = new GraphicsDeviceManager (this);
Content.RootDirectory = "Content";
}
protected override void Initialize( )
{
// TODO: Add your initialization logic here
TankList = new List ();
randomValue = new Random ();
this.IsMouseVisible = true;
base.Initialize ();
}
protected override void LoadContent( )
{
spriteBatch = new SpriteBatch (GraphicsDevice);
TankSprite = Content.Load (@"Textures\MulticolorTanks");
Tank = new DynamicSprite (GraphicsDevice, TankSprite);
Tank.Sprite.AddAnimation ("green", 0, 0, 32, 32, 8, 0.1f);
Tank.Sprite.AutoRotate = true;
Tank.Position = new Vector2 (100, 100);
Tank.Traget = Tank.Position;
Tank.AddPathNode (200, 200);
Tank.AddPathNode (300, 300);
Tank.AddPathNode (400, 200);
Tank.AddPathNode (200, 100);
Tank.Speed = 3.0f;
Tank.IsLoopingPath = true;
Tank.IsCollisionBoxVisible = true;
Tank.ResizeCollisionBox (5, 5);
////////////////////////////////////////////////////
EntityManager.AddEntityToWorld (Tank);
////////////////////////////////////////////////////
Tank2 = new DynamicSprite (GraphicsDevice, TankSprite);
Tank2.Sprite.AddAnimation ("yellow", 0, 64, 32, 32, 8, 0.1f);
Tank2.Position = new Vector2 (400, 200);
Tank2.Traget = Tank2.Position;
Tank2.IsCollisionBoxVisible = true;
Tank2.ResizeCollisionBox (5, 5);
////////////////////////////////////////////////////
EntityManager.AddEntityToWorld (Tank2);
////////////////////////////////////////////////////
Tank3 = new DynamicSprite (GraphicsDevice, TankSprite);
Tank3.Sprite.AddAnimation ("yellow", 0, 64, 32, 32, 8, 0.1f);
Tank3.Position = new Vector2 (200, 200);
Tank3.Traget = Tank3.Position;
Tank3.IsCollisionBoxVisible = true;
Tank3.ResizeCollisionBox (5, 5);
////////////////////////////////////////////////////
EntityManager.AddEntityToWorld (Tank3);
////////////////////////////////////////////////////
//********************************
AreaManager.InstallAreaManager (GraphicsDevice, 8, 5, new Rectangle (0, 0, 100, 100));
//********************************
}
protected override void Update( GameTime gameTime )
{
////////////////////////////////////////////////////
EntityManager.Update (gameTime);
AreaManager.Update (gameTime);
CollisionManager.ExecuteCollisionEvent();
////////////////////////////////////////////////////
base.Update (gameTime);
}
protected override void Draw( GameTime gameTime )
{
GraphicsDevice.Clear (Color.CornflowerBlue);
spriteBatch.Begin ();
EntityManager.Draw (spriteBatch,GraphicsDevice);
spriteBatch.End ();
base.Draw (gameTime);
}
}
///
/// Update the Area
///
public void Update( GameTime gameTime )
{
/**
* in this loop we check the collision of object with other objects
* we check collision only betwen object with i index and object with i+1 index
* exemple to demonstrate the utility :
* check collision betwen Object[0] and Object[1]
* check collision betwen Object[0] and Object[2]
* check collision betwen Object[0] and Object[3]
*
* we dont need to check collision betwen Object[1] and Objetc[0] any more because its already checked when we
* was in Object[0] check for collision routine
* if we have N object, we will have : 1+2+...+n-1 calcule
* exemple : we Have 4 Objects : Obj[0],Obj[1],Obj[2],Obj[3]
* Object | Collision with
* --------------------------
* Obj[0] | Obj[1],Obj[2],Obj[3]
* Obj[1] | Obj[2],Obj[3]
* Obj[2] | Obj[3]
* Obj[3] | non need for check
*
* we have : 4 Objects thant we need : 1+2+3 = 6 collision check
* with simple collision check we will need : (4x4)-4 = 12 collision check
*
* we save 6collision check with this solution !
**/
if ( EntityIntheArea.Count > 0 )
{
for ( int i = 0; i < EntityIntheArea.Count; i++ )
{
//Do not check collision betwen the same object
int EntityItSelfIndex = i;
for ( int j = ( EntityItSelfIndex + 1 ); j < EntityIntheArea.Count; j++ )
{
if ( EntityIntheArea[i].CollisionBox.Intersects (EntityIntheArea[j].CollisionBox) )
CollisionManager.AddCollisionUnite (EntityIntheArea[i], EntityIntheArea[j]);
}
}
}
// the Entity list it will update evrey frame, we should clear it after checking all entity collision possibility
EntityIntheArea.Clear ();
}
الشرح مع الدالة لكن ساعيده هنا :private List EntityIntheArea = new List ();
private List EntityIntheArea = new List (1300);