我的游戏有一个名为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()
中删除。
我的问题是,我可以采取一种不同的,更清洁的方法吗?
答案 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)并调用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)
我很快遇到LibGDX
和Actor
类Stage
的类似情况。我创建了自己的扩展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
附带的类。