So I have an Entity
, which is responsible for providing an abstract base for other objects to inherit. (Like Actor
objects, which are people, Creature
objects, which are animals, etc.)
The Entity
provides a solid foundation for Actor
and Creature
to interact with, I'm just curious if it's not gone overboard or if I've missed something.
Library: Framework
(Client and Server)
The Entity
:
public abstract class Entity : ITrackableObject
{
protected bool _isMoving;
protected Size _size = new Size(32, 64);
private PointF _position;
public bool IsMoving { get { return _isMoving; } }
public Guid Id { get; set; }
public abstract EntityType EntityType { get; }
public GenderType Gender { get; set; }
public PointF Position { get { return _position; } set { if (_position != value) { var oldPosition = _position; _position = value; OnTrackableObjectChanged(new TrackableObjectChangedEventArgs(_position, value, Size, Size)); } } }
public Direction Direction { get; set; }
public Size Size { get { return _size; } }
public RectangleF Bounds { get { return new RectangleF(Position, Size); } }
public EntityProperties EntityProperties { get; set; }
public Color NameColor { get; set; }
public Point Home { get; set; }
protected List<IInstruction> _instructions = new List<IInstruction>();
public List<IInstruction> Instructions { get { return _instructions; } }
public Entity()
{
EntityProperties = new EntityProperties();
NameColor = Color.Preset.White;
_instructions = new List<IInstruction>();
}
public virtual void Update(UpdateState updateState)
{
foreach (IInstruction instruction in Instructions)
instruction.Update(updateState);
Move(updateState.Force);
}
public virtual void Move(Vector2F vector)
{
if (vector.R > 0)
_isMoving = true;
else
_isMoving = false;
float r = Math.Max(Math.Abs(vector.X), Math.Abs(vector.Y));
vector = Vector2F.FromRTheta(r, vector.Theta);
Position = new Evbpc.Framework.Drawing.PointF(Position.X + vector.X, Position.Y + vector.Y);
Direction? d = vector.GetDirection();
if (d.HasValue)
Direction = d.Value;
}
private void OnTrackableObjectChanged(TrackableObjectChangedEventArgs e) { var handler = _TrackableObjectChanged; if (handler != null) { handler(this, e); } }
private EventHandler<TrackableObjectChangedEventArgs> _TrackableObjectChanged;
PointF ITrackableObject.Position { get { return Position; } }
SizeF ITrackableObject.Size { get { return Size; } }
event EventHandler<TrackableObjectChangedEventArgs> ITrackableObject.TrackableObjectChanged { add { _TrackableObjectChanged += value; } remove { _TrackableObjectChanged -= value; } }
}
The UpdateState
is pretty simple:
public class UpdateState
{
public Vector2F Force { get; set; }
}
Then an Actor
comes along:
public abstract class Actor : Entity
{
public Inventory Inventory { get; set; }
public List<Injury> Injuries { get; private set; }
public Actor()
{
Injuries = new List<Injury>();
Inventory = new Inventory();
}
}
And a NonPlayableCharacter
:
public class NonPlayableCharacter : Actor
{
public sealed override EntityType EntityType { get { return EntityType.NonPlayableCharacter; } }
public NonPlayableCharacter(Point origin)
: base()
{
this.Position = origin;
_instructions.Add(new WanderInstruction(this, 10f, Point.Round(this.Position)));
}
public override void Update(UpdateState updateState)
{
base.Update(updateState);
}
}
And lastly, a Player
:
public class Player : Actor
{
public sealed override EntityType EntityType { get { return EntityType.Player; } }
}
Library: Framework.Xna
(Client)
Pretty simple. Until you get to the other player, which is in a different project:
public class Player : Framework.Entities.Actors.Player, IDrawableActor, IUpdateableActor
{
private Texture2D _texture;
public Texture2D Texture { get { return _texture; } set { _texture= value; } }
public void Draw(SpriteBatch s, GameTime gameTime)
{
int xSource = 0; // Down
if (Direction == Direction.Up)
xSource = 3; // Up
if (Direction == Direction.Left)
xSource = 6; // Left
if (Direction == Direction.Right)
xSource = 9;
if (IsMoving)
{
s.Draw(Texture,
new Microsoft.Xna.Framework.Rectangle((int)Position.X,
(int)Position.Y,
Size.Width,
Size.Height),
new Microsoft.Xna.Framework.Rectangle((xSource * Size.Width) + ((gameTime.TotalGameTime.Milliseconds / 125 % 3) * Size.Width),
Size.Height,
Size.Width,
Size.Height),
Microsoft.Xna.Framework.Color.White,
0,
new Microsoft.Xna.Framework.Vector2(0, 0),
//(e.Direction == Direction.Left ? SpriteEffects.FlipHorizontally : SpriteEffects.None),
SpriteEffects.None,
0);
}
else
{
s.Draw(Texture,
new Microsoft.Xna.Framework.Rectangle((int)Position.X,
(int)Position.Y,
Size.Width,
Size.Height),
new Microsoft.Xna.Framework.Rectangle((xSource * Size.Width),
0,
Size.Width,
Size.Height),
Microsoft.Xna.Framework.Color.White,
0,
new Microsoft.Xna.Framework.Vector2(0, 0),
//(e.Direction == Direction.Left ? SpriteEffects.FlipHorizontally : SpriteEffects.None),
SpriteEffects.None,
0);
}
}
public override void Update(UpdateState uState)
{
base.Update(uState);
}
}
There's an IDrawableActor
:
public interface IDrawableActor : IDrawableEntity
{
}
Finally, the IDrawableEntity
:
public interface IDrawableEntity
{
Texture2D Texture { get; set; }
void Draw(SpriteBatch s, GameTime gameTime);
}
My main concern is whether or not this is necessary. I have to split drawing code out of the main Player
class, so that the Client and Server can reference this library.
Obviously I'm interested in all suggestions, but of particular importance to me:
- In C# you can only inherit one class. The drawing code in
Framework.Xna.Player.Draw
would likely need to be duplicated for anything that is anIDrawableEntity
. Is this a good approach? - Should I create interfaces for
Entity
,Actor
,Framework.Player
andFramework.Xna.Player
? - At some point, I would like to expand
Entity
to also be able to represent objects. This would mean moving a lot of the code in thisFramework.Entity
class into aFramework.MovingEntity
. Are there any other concerns I should consider?
Entity
objects also includeCreature
objects, which are basically animals. Part of the systems to be implemented in this project include a dynamic animal/creature environment which does require a male and female creature to maintain population. \$\endgroup\$