如何仅将方法应用于阶段

时间:2015-10-19 19:41:34

标签: libgdx

我的游戏有一个名为Enemy的类,其扩展为Actor。另外,我有一个EnemyAffector类,其中包含影响Enemies的方法,大致如下:

class EnemyAffector {
    public void affect(Enemy enemy) { ... }
}

在我的Stage中,在act方法中,我想迭代所有Enemies并对其应用EnemyAffector。显而易见的方法是通过施放:

@Override
public void act() {
    super.act();
    for (Actor actor: getActors()) {
        if (actor instanceof Enemy) {
            enemyAffector.affect((Enemy)actor);
        }
    }
...
}

但是,传说使用instanceof should be avoided。因此,我考虑将Array添加到Enemies时添加Stage,即将Stage重新加载addActor public void addActor(EnemyProjectile pEnemyProjectile) { // add to Enemy Array } 。方法:

act

所以现在我的@Override public void act() { super.act(); for (Enemy enemy: enemyArray) { enemyAffector.affect(enemy); } ... } 方法看起来像这样:

instanceof

耶!没有Enemy

但是,此解决方案的问题在于,我始终需要在Array Actor和标准Array Enemies之间进行同步,因为Enemy Array Stage中的$ie.Document可能已从focus()中删除。

我的问题是,我可以采取一种不同的,更清洁的方法吗?

3 个答案:

答案 0 :(得分:1)

最简单的,我认为生成最少的代码行是使用 UserObject Actor字段,如:

    Actor actor = new Actor(); //or its children ofc
    actor.setUserObject("enemy");

    //...

    if( actor.getUserObject().equals("enemy") )
    {
        //yup this is enemy
    }

当然,由于OOP不是最好的解决方案,在某些情况下可能不是很灵活,但说实话,在这种情况下处理额外的数组等等只会使事情变得复杂。

请注意, UserObject 是对象类型,所以如果你想推送一些Java无法自己投射的东西,你必须自己投射它。

但是,如果您想要超级好,这是另一个更优雅的解决方案:

  • 您使用自己的 MyActor 类覆盖Actor类,并使用一些 customAction()方法,该方法不执行任何操作。你将继承这个类而不是现在的Actor
  • 在每个儿童课程中,该方法什么都不做,但在 Enemy 课程中,您正在实施功能
  • 在循环中,您正在转换为(MyActor)并调用customAction方法

    for (Actor actor: getActors()) {
        ((MyActor)actor).customAction();
    }
    

    customAction 方法有来自EnemyEffector的逻辑

如果继承从Actor继承的类(如Label类),这会产生一些问题,如果EnemyEffector逻辑正在使用Actor实例不应该知道的数据,因为它们是全局的,并且应该是'是冗余的(当然你也可以将信息作为customAction方法的参数传递)

答案 1 :(得分:1)

您可以使用可以添加到演员的UserObject

public enum ActorType
{
    PLAYER, ENEMY, ETC;
}

//...

Enemy enemy = new Enemy();

// Or set this in the constructor
enemy.setUserObject(ActorType.ENEMY);

for (Actor actor : actors)
{
    if (actor.getUserObject() == ActorType.ENEMY)
    {
        // Do stuff...
    }
}

或者将两个数组放在一个额外的类中,并添加添加/删除方法:

public class ActorManager
{
    private Array<Actor>    actors  = new Array<>();
    private Array<Enemy>    enemies = new Array<>();

    public void add(Actor actor)
    {
        actors.add(actor);
    }

    public void add(Enemy enemy)
    {
        actors.add(enemy);
        enemies.add(enemy);
    }

    public void remove(Actor actor)
    {
        actors.removeValue(actor, true);
    }

    public void remove(Enemy enemy)
    {
        actors.removeValue(enemy, true);
        enemies.removeValue(enemy, true);
    }

    // To make sure our backing arrays are not modified:

    public Array<Actor> getAll()
    {
        return new Array<>(actors);
    }

    public Array<Actor> getEnemies()
    {
        return new Array<>(enemies);
    }
}

答案 2 :(得分:1)

我很快遇到LibGDXActorStage的类似情况。我创建了自己的扩展Actor的子类,我将把它作为所有Actors的“基本Actor”对象。

这样,您可以设置在某些情况下由所有演员调用的方法。

class MyStage extends Stage
{
    public void addActor(MyActor pEnemyProjectile) { // call onAdd }

    //override other methods as necessary,
      //possibly getActors() to return Actors as MyActors, etc
}

class MyActor extends Actor
{

    public void update(double delta)
    {
        //I find it easiest to have "removal" code happen in the Actor's update method, then I can call onRemove()
        //This could happen by finding death conditions or just checking a "isDead" boolean.
    }

    public void onAdd()
    {
        //can set up a default behavior, or just override on other subclasses
    }

    public void onRemove()
    {
        //call for every Actor that gets removed - can extend and remove Enemies from an Enemy list if desired
    }

    //maybe it would be better to check if the Object can be Affected here?
      //rather than keeping and maintaining a separate list
    public boolean isAffected()
    {
        return false; //return true by Enemies
    }
}

class Enemy extends MyActor
{
    //implement onRemove, onAdd, etc..
}

如果效果更好,MyActor也可以创建为interface - 然后您可以轻松地为Label或其他LibGdx创建子类继承自Actor

的类

我个人选择让它成为一个子类,因为我可以创建更容易键入和调用的辅助方法 - 例如我的“运动”和“旋转”代码,它们不使用{{ 1}} Action附带的类。