对于我在单一游戏中制作的大学项目,我有一本字典,其中引用了我的游戏中的所有不同实体。我使用的层次结构是:组件<---- Entity <---- Enemy <---- Sawblade. I am defining the references like so:
{
"Sawblade",
new Sawblade(new Dictionary<string, Animation>
{
{"Moving", AllAnimations["SawBladeMoving"] },
}, 100f, -1, 2)
},
在主要游戏更新方法中,我使用以下方法循环遍历所有当前实体:
foreach (Component entity in entities[game.currentDungeon.currentFloor])
{
entity.Update(_gametime);
}
到目前为止,这效果非常好,它使用敌人类中的更新方法更新敌人,并使用其自己的更新类更新其他实体。但是我需要锯片类来运行这个更新方法,而不是一般敌人类中的更新方法:
public override void Update(GameTime gameTime)
{
if (GameManager.CheckTileCollisions(new Rectangle(Edge.X + (int)Velocity.X, Edge.Y, Edge.Width, Edge.Height))) Velocity = new Vector2(-Velocity.X, Velocity.Y);
if (GameManager.CheckTileCollisions(new Rectangle(Edge.X, Edge.Y + (int)Velocity.Y, Edge.Width, Edge.Height))) Velocity = new Vector2(Velocity.X, -Velocity.Y);
animationManager.LateUpdate(gameTime);
}
锯片更新方法(应该运行什么)^
public override void Update(GameTime gameTime)
{
if(Health <= 0) GameManager.RemoveEntity(this);
if(Target is not null)
{
// TEMP PATHFINDING
if(Target.Position.X == Position.X) Velocity = new Vector2(0, 0);
else if (Target.Position.X > Position.X) Velocity = new Vector2(1, 0);
else Velocity = new Vector2(-1, 0);
if (Target.Position.Y == Position.Y) Velocity = new Vector2(Velocity.X, 0);
else if (Target.Position.Y > Position.Y) Velocity = new Vector2(Velocity.X, 1);
else Velocity = new Vector2(Velocity.X, -1);
}
}
敌人更新方法(正在运行什么)^
我不明白为什么对于每个其他实体,程序都会运行最高级别的覆盖,但对于此类,它的行为就好像锯片覆盖甚至不存在一样。有人对可能导致这种情况的原因有任何想法吗?
我已经尝试过:
foreach (Component entity in entities[game.currentDungeon.currentFloor])
{
if (entity is Sawblade) ((Sawblade)entity).Update(_gametime);
else entity.Update(_gametime);
}
看看错误是否是我不明白该实体是锯片类型,但它仍然拒绝确认覆盖。
课程:
成分:
public abstract class Component
{
public virtual Vector2 Position { get; set; }
public Vector2 Size { get; set; }
public Rectangle Edge => new Rectangle(Position.ToPoint(), Size.ToPoint());
public Component Parent { get; set; }
public bool IsSelected { get; set; }
public abstract void Update(GameTime gameTime);
public abstract void LateUpdate(GameTime gameTime);
public abstract void Draw(SpriteBatch spriteBatch);
}
实体:
public class Entity : Component
{
protected Vector2 Velocity { get; set; }
public Direction direction;
protected AnimationManager animationManager;
protected Dictionary<string, Animation> animations;
public Item itemContents;
public override Vector2 Position { get => base.Position; set { base.Position = value; if (animationManager != null) animationManager.Position = value; } }
public float LinearSpeed { get; set; }
public Texture2D Texture { get; protected set; }
public Entity(Texture2D texture, float speed)
{
Position = Vector2.Zero;
Texture = texture;
Size = new Vector2(texture.Width, texture.Height);
Velocity = Vector2.Zero;
LinearSpeed = speed;
direction = Direction.Down;
}
public Entity(Dictionary<string, Animation> animations, float speed)
{
Position = Vector2.Zero;
this.animations = animations;
LinearSpeed = speed;
Velocity = Vector2.Zero;
Size = new Vector2(animations[animations.First().Key].frameWidth, animations[animations.First().Key].frameHeight);
animationManager = new AnimationManager(animations.First().Value);
direction = Direction.Down;
}
public Entity(Animation animation, float speed) : this(new Dictionary<string, Animation> { { "Idle", animation } }, speed)
{
}
public override void Update(GameTime gameTime)
{
}
public override void LateUpdate(GameTime gameTime)
{
// Physics
Position += Velocity * LinearSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
if (animationManager != null)
{
animationManager.LateUpdate(gameTime);
if (animations.ContainsKey("WalkDown")) SetAnimations();
}
}
public void DrawEditor(SpriteBatch spriteBatch)
{
if (animationManager is not null)
{
animationManager.Stop();
animationManager.Draw(spriteBatch, Color.Gray);
}
else spriteBatch.Draw(Texture, Edge, Color.Gray);
}
public override void Draw(SpriteBatch spriteBatch)
{
if(animationManager is not null) animationManager.Draw(spriteBatch, Color.White);
else spriteBatch.Draw(Texture, Edge, Color.White);
}
protected virtual void SetAnimations()
{
if (Velocity.Y > 0 && Velocity.X == 0)
{
animationManager.Play(animations["WalkDown"]);
direction = Direction.Down;
}
else if (Velocity.Y < 0 && Velocity.X == 0)
{
animationManager.Play(animations["WalkUp"]);
direction = Direction.Up;
}
if (Velocity.X < 0)
{
animationManager.Play(animations["WalkLeft"]);
direction = Direction.Left;
}
else if (Velocity.X > 0)
{
animationManager.Play(animations["WalkRight"]);
direction = Direction.Right;
}
else if (Velocity.Y == 0) animationManager.Stop();
}
public virtual void Activate(Player activator)
{
}
public virtual void Activate(Dungeon dungeon)
{
}
public virtual Entity Clone(Entity copy)
{
copy.Position = this.Position;
copy.direction = this.direction;
if (animationManager is not null) copy.animationManager = this.animationManager.Clone();
copy.animations = this.animations;
if(itemContents is not null) copy.itemContents = this.itemContents.Clone();
copy.Size = this.Size;
copy.Parent = this.Parent;
copy.Velocity = this.Velocity;
copy.Texture = this.Texture;
copy.IsSelected = this.IsSelected;
copy.LinearSpeed = this.LinearSpeed;
return copy;
}
public virtual Entity Clone()
{
Entity copy;
if (animationManager is not null) copy = new Entity(animations, LinearSpeed);
else copy = new Entity(Texture, LinearSpeed);
return Clone(copy);
}
public void Serialize(BinaryWriter writer)
{
}
public void Deserialize(BinaryReader reader)
{
}
}
敌人:
public class Enemy : Entity
{
public int Health { get; set; }
public int Damage { get; set; }
public bool IsAlive { get; set; }
Component Target;
public Enemy(Texture2D texture, float speed, int hp, int dmg) : base(texture, speed)
{
Health = hp;
Damage = dmg;
}
public Enemy(Dictionary<string, Animation> _animations, float speed, int hp, int dmg) : base(_animations, speed)
{
Health = hp; Damage = dmg;
}
public void SetTarget(Component target)
{
Target = target;
}
public override void Update(GameTime gameTime)
{
if(Health <= 0) GameManager.RemoveEntity(this);
if(Target is not null)
{
// TEMP PATHFINDING
if(Target.Position.X == Position.X) Velocity = new Vector2(0, 0);
else if (Target.Position.X > Position.X) Velocity = new Vector2(1, 0);
else Velocity = new Vector2(-1, 0);
if (Target.Position.Y == Position.Y) Velocity = new Vector2(Velocity.X, 0);
else if (Target.Position.Y > Position.Y) Velocity = new Vector2(Velocity.X, 1);
else Velocity = new Vector2(Velocity.X, -1);
}
}
public override void Activate(Player activator)
{
IsAlive = false;
}
public override Entity Clone()
{
Enemy copy;
if (animationManager is not null) copy = new Enemy(animations, LinearSpeed, Health, Damage);
else copy = new Enemy(Texture, LinearSpeed, Health, Damage);
copy.Health = Health;
copy.Damage = Damage;
copy.IsAlive = IsAlive;
return Clone(copy);
}
}
锯片:
public class Sawblade : Enemy
{
public Sawblade(Dictionary<string, Animation> _animations, float speed, int hp, int dmg) : base(_animations, speed, hp, dmg)
{
Random rng = new Random();
Velocity = new Vector2((float)rng.NextDouble(), (float)rng.NextDouble());
animationManager.Play(_animations["Moving"]);
}
public override void Update(GameTime gameTime)
{
if (GameManager.CheckTileCollisions(new Rectangle(Edge.X + (int)Velocity.X, Edge.Y, Edge.Width, Edge.Height))) Velocity = new Vector2(-Velocity.X, Velocity.Y);
if (GameManager.CheckTileCollisions(new Rectangle(Edge.X, Edge.Y + (int)Velocity.Y, Edge.Width, Edge.Height))) Velocity = new Vector2(Velocity.X, -Velocity.Y);
animationManager.LateUpdate(gameTime);
}
}
找到了解决方案,这是因为在将实体添加到实体列表时,我调用了clone()方法,该方法在sawblade中没有被重写,所以它只是将sawblade返回为敌人类型。
将该方法添加到锯片中并解决了问题
public override Entity Clone()
{
Sawblade copy = new Sawblade(animations, LinearSpeed, Health, Damage);
return base.Clone(copy);
}