3

我正在使用 Xna/C# 开发一个基本游戏和 2D 引擎,并且我正在尝试简化其中的一些内容。我有一个来自引擎的 Entity2D 基类和两个特定于从它继承的游戏的类:Tower 和 Enemy。在我的引擎中,我不想有两个单独的列表,一个用于塔,一个用于敌人,我想将它们组合成一个通用列表。然后,我遇到了何时需要从列表中返回塔或从列表中返回敌人的问题。我知道我可以使用引擎对象的类型转换:

class Entity2D {...} //engine object
class Tower : Entity2D {...} //game specific
class Enemy : Entity2D {...} //game specific

//In engine:
public Entity2D GetEntity(int index) { ...return objects[index];}

//Somewhere in the game
{
    Enemy e = GetEntity(0) as Enemy;
    if(e != null)
        //Enemy returned

    Tower t = GetEntity(0) as Tower;
    if(t != null)
        //Tower returned
}

当然,这似乎真的很低效。

我还is稍微研究了关键字,它似乎是这样工作的:

Entity2D entity = GetEntity(0);
if(entity is Tower)
{
    Tower t = (Tower)entity;
    t.DoTowerThings();
}

仍然会导致返回一个基础对象并使用更多内存来创建第二个对象并对其进行类型转换。

如果有办法做这样的事情,那就太好了:

//In engine:
public T GetEntity(int index) 
{ 
    if(T == Tower) //or however this would work: (T is Tower), (T as Tower), etc
        return objects[index] as Tower;
    else if(T == Enemy) 
        return objects[index] as Enemy;
    else return null;
}

Enemy e = GetEntity(0);

但这打破了引擎和游戏分开的引擎部分

我正在寻找最清晰且内存效率最高的方法来解决这个问题,同时仍然让 Entity2D 基于引擎并完全避免在引擎中使用 Tower 或 Enemy。

欢迎大家提出意见!

谢谢!

4

3 回答 3

1

就快到了!

//In engine:
public T GetEntity<T>(int index) where T : Entity2D
{ 
    return objects[index] as T;
}
//Somewhere else:
Enemy e = GetEntity<Enemy>(0);

注意:如果objects[index]不是 a T,它将返回null

但是,如果这是我的游戏,我只会为每种类型的对象保留单独的列表。

于 2013-06-23T19:42:21.010 回答
0

你可以这样做,(Github 上的完整代码

public T GetEntity<T>(int index) where T : Entity2D
{
    return list.ElementAt(index) as T;
}

如果元素不是预期的类型,它将返回 null。

Tower t = GetEntity<Tower>(0);
于 2013-06-23T19:44:17.783 回答
0

如果您必须消除返回值的歧义,那么代码的结构很糟糕,对象在逻辑上并不相似,并且最好有两个列表,每种类型都有一个单独的访问器。

但是,如果类型非常相似并且您只需很少在它们之间消除歧义,那么请执行以下操作:-

abstract class GameEntity : Entity2D
{
  abstract public void TowerOnlyFunction (args); // need to look up exact syntax, but you get the idea
  abstract public void EnemyOnlyFunction (args);

  void CommonFunctions (args);
}

class Tower : GameEntity
{
  public void TowerOnlyFunction (args)
  {
    // code
  }
  public void EnemyOnlyFunction (args)
  {
    // empty
  }
}

class Enemy : GameEntity
{
  public void TowerOnlyFunction (args)
  {
    // empty
  }
  public void EnemyOnlyFunction (args)
  {
    // code
  }
}

//Somewhere in the game
void DoSomethingWithTower ()
{
  GameEntity e = GetEntity(0);
  e.TowerOnlyFunction ();
}
于 2013-06-23T19:55:58.280 回答