我正在尝试为游戏设计几个课程,但我不确定我做得对。
我有两个课程:Actor
和Building
。
它们有几个子类:Policeman
,Fireman
和PoliceStation
,FireStation
。
我希望能够将所有这些项放在一个列表中以便稍后迭代,所以我添加了一个基类:GameEntity
。
所以我拥有的是:
public abstract class GameEntity:
{
public GameEntity()
{
}
}
public class Actor: GameEntity
{
public int _speed;
public TileSprite _UI;
public Actor()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoActing()
{
}
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
}
public class Building: GameEntity
{
public TileSprite _UI;
public Building()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoBuilding()
{
}
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
}
现在,我希望能够做到这一点:
List<GameEntity> Entities = new List<GameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation
Entities.Add(a1);
Entities.Add(b1);
foreach(GameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
//If Actor then do
ent.DoActing();
//If Building then do
ent.DoBuilding();
}
}
现在,为了做最后一点,我最好是实现一个包含OnClick
和CollidesWith
的接口,还是可以继承?
如果是这样,我该怎么做?
干杯。
答案 0 :(得分:2)
这只是为了给你一个想法,我想这就是你需要的。
public interface IGameEntity
{
bool CollidesWith();
void OnClick();
void DoActing();
}
public class Actor : IGameEntity { //Interface implemented }
public class Building: IGameEntity { //Interface implemented }
public class Policeman: IGameEntity { //Interface implemented }
public class Fireman: IGameEntity { //Interface implemented }
public class FireStation: IGameEntity { //Interface implemented }
在您的客户端对象中,只需执行以下操作:
List<IGameEntity> entities = new List<IGameEntity>()
{
new Actor(),
new Building(),
new Policeman(),
new Fireman(),
new Fireman()
};
foreach (IGameEntity entity in entities)
{
entity.CollidesWith();
entity.OnClick();
entity.DoActing();
}
答案 1 :(得分:1)
将虚拟doStuff()
添加到GameEntity
并将其覆盖在子类中,而不是使用DoActing
和DoBuilding
之类的唯一方法名称,然后从循环中调用它应该执行你想要什么。
答案 2 :(得分:1)
去这里的方法数量。 如果可以单击所有GameEntities,则可以将OnClick事件属性添加到基类。
如果不是,那么我将有一个接口IClick,然后在可点击的实体上实现它。
碰撞,取决于。 建筑物不会移动,因此它们不会与任何物体发生碰撞,但它们可能会发生碰撞,因此您可能需要做一个损坏程序,然后建议一个破坏的,例行的修理例程。
没有正确答案,但是 三个代码气味将是一个 没有任何内容的基类。
非常深的继承层次结构(我的书中有两个以上的级别引起怀疑) 所以如果你开始看到GameEntity - &gt; BuildingEntity - &gt; ActiveBuildingEntity - &gt;可修复的建筑实体,你将陷入混乱,即将变得更加混乱。
最重要的是一个没有做任何方法的基类只存在,因为你需要在某些后代中添加行为(覆盖)。
不要害怕拥有一些接口。 IClick,ICollision,IDamage,IRepair等。这比暗示建筑物可能撞到汽车更好。
答案 3 :(得分:1)
你可以这样做:
public interface IGameEntity
{
void OnClick();
bool CollidesWith(Vector2 pos);
void Do();
}
public abstract class Actor: IGameEntity
{
public int _speed;
public TileSprite _UI;
public virtual bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void OnClick();
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void Do();
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
//Do Acting for Police
}
}
public abstract class Building: IGameEntity
{
public TileSprite _UI;
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public abstract void OnClick();
public abstract void Do();
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
// Do Building
}
}
如果游戏实体只是一个界面,则无需将其作为抽象类。如果Actor和Building永远不能作为一个独立的对象存在,那么它们应该是抽象的。如果DoActing,DoBuilding和OnClick必须被基类覆盖,那么你可以在actor和Building中将它们标记为抽象。
我遵循norlesh的建议只有一种方法Do.你也可以让Actor和Building有自己的抽象方法,而IGameEntity则没有Do.然后你会放一个if语句并检查每个对象是否属于类型构建器,然后他们将运行构建,如果是类型actor,则运行act。
我认为使用一种方法的方法更好,因为你消除了一步。从设计的角度来看,我不确定,但无论如何对我来说都是一样的。
List<IGameEntity> Entities = new List<IGameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation();
Entities.Add(a1);
Entities.Add(b1);
foreach(IGameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
ent.Do();
}
}