阵列列表似乎在战斗逻辑中无法正常工作?

时间:2014-03-22 13:08:08

标签: java android

我正在为Android制作塔式进攻游戏,我在战斗系统中遇到了一些不寻常的行为。我有一个小兵穿过屏幕并与敌方单位相撞。他们参与战斗,但由于某种原因,敌人脱离战斗。

当生成单位时,它们存储在数组列表中。我使用一个lockedOn变量,该变量存储指向当前与之对抗的数组列表中的对象的指针。似乎当一个新的敌方单位产生时,它会对目前处于战斗中的敌人造成不利影响。当一个新项目被添加到数字列表中时,我不知道是否有东西正在改变对象的指针,这个项目锁定了仆从或什么。我已经尝试了我能想到的一切,但我无法缩小这个问题的范围。

我发布的代码中包含了许多额外的内容,以便于查看。我包括主要的游戏类和战士类的副本。冠军级别与战士相同,攻击和攻击速度值略有不同。

主要游戏类

public final List<Minion_Warrior> mWarriors;
public final List<Enemy_Champion> eChampions;

this.mWarriors = new ArrayList<Minion_Warrior>();
this.eChampions = new ArrayList<Enemy_Champion>();

public void update(float deltaTime) {

    removeDead();
    updateMinions(deltaTime);
    updateEnemies(deltaTime);
    updateTowers(deltaTime);
}

private void removeDead() {
    int len = mWarriors.size();
    for(int i = 0; i < len; i++) {
        Minion_Warrior warrior = mWarriors.get(i);
        if(warrior.canDie) {
            mWarriors.remove(warrior);
            warrior = null;
            len = mWarriors.size();
        }
    }
    len = eChampions.size();
    for(int i = 0; i < len; i++) {
        Enemy_Champion champion = eChampions.get(i);
        if(champion.canDie) {
            eChampions.remove(champion);
            champion = null;
            len = eChampions.size();
        }
    }
}

private void updateMinions(float deltaTime) {

    updateWarriors(deltaTime);
}

private void updateWarriors(float deltaTime) {
    // For each warrior
    int lenWar = mWarriors.size();
    for(int i = 0; i < lenWar; i++) {
        Minion_Warrior warrior = mWarriors.get(i);

        // If the warrior is alive
        if(warrior.isAlive) {

            // If the warrior has no current target
            if(warrior.lockedOn == null) {

                // Check each champion
                int lenChamp = eChampions.size();
                for(int j = 0; j < lenChamp; j++) {
                    Enemy_Champion champion = eChampions.get(j);

                    // If a champion is alive
                    if(champion.isAlive) {

                        // And the champion does not currently have a target
                        if(champion.lockedOn == null) {

                            // Has the champion collided with the warrior?
                            if(OverlapTester.overlapRectangles(champion.bounds, warrior.bounds)) {
                                warrior.lockedOn = champion;
                                champion.lockedOn = warrior;
                                warrior.state = warrior.MINION_STATE_COMBAT;    
                                champion.state = champion.ENEMY_STATE_COMBAT;
                                break;
                            }
                        }
                    }   
                }
            }
        }

        warrior.update(deltaTime);
    }
}

private void updateEnemies(float deltaTime) {   
    updateChampions(deltaTime);
}

private void updateChampions(float deltaTime) {
    int len = eChampions.size();
    for(int i = 0; i < len; i++) {
        Enemy_Champion champion = eChampions.get(i);
        champion.update(deltaTime);
    }
}

private void updateTowers(float deltaTime) {
    if(spawnEnemies) {          
        if(!tCastleCanDeploy) {
            tCastleTimer += deltaTime;
            if(tCastleTimer > 10) {
                tCastleTimer = 0;
                tCastleCanDeploy = true;
                tCastleQue = 3;
            }
        }
        else if(tCastleCanDeploy && !tCastleWaiting) {
            tCastleDeployTimer += deltaTime;
            if(tCastleDeployTimer > 2) {
                tCastleDeployTimer = 0;
                tCastleWaiting = true;
            }
        }
        else if(tCastleCanDeploy && tCastleWaiting) {
            if(tCastleQue == 3) {
                Enemy_Champion champion = new Enemy_Champion(145, 51 - 0.5f);
                eChampions.add(champion);
                tCastleQue -= 1;
                tCastleWaiting = false;
            }
            else if(tCastleQue == 2) {
                Enemy_Archer archer = new Enemy_Archer(145, 51 - 0.5f);
                eArchers.add(archer);
                tCastleQue -= 1;
                tCastleWaiting = false;
            }
            else if(tCastleQue == 1) {
                Enemy_Mage mage = new Enemy_Mage(145, 51 - 0.5f);
                eMages.add(mage);
                tCastleQue -= 1;
                tCastleWaiting = false;
            }
            else if(tCastleQue == 0) {
                tCastleWaiting = false;
                tCastleCanDeploy = false;
            }
        }
    }
}  

Minion_Warrior Class

public class Minion_Warrior extends DynamicGameObject {
    public static final float MINION_WIDTH = 4.0f;
    public static final float MINION_HEIGHT = 4.0f;
    public static final int MINION_STATE_DEPLOY = 0;
    public static final int MINION_STATE_ROUTE = 1;
    public static final int MINION_STATE_COMBAT = 2;
    public static final int MINION_STATE_DEATH = 3;
    public static final float MINION_VELOCITY = 1.75f;

    public enum Animation {STANDING, WALKING, ATTACKING, DYING}

    int life;
    int attack;
    float attackSpeed;
    float attackTimer;
    boolean canAttack;
    float deathTimer;
    boolean canDie;
    boolean isAlive;
    int state;
    int cost;
    float stateTime;
    public static Enemy_Champion lockedOn;
    Animation animation = Animation.WALKING;
    Rectangle collisionBox;

    public Minion_Warrior(float x, float y) {
        super(x, y, MINION_WIDTH, MINION_HEIGHT);
        life = 100;
        attack = 15;
        attackSpeed = 1.8f;
        attackTimer = 0;
        canAttack = true;
        deathTimer = 0;
        canDie = false;
        isAlive = true;
        state = MINION_STATE_DEPLOY;
        cost = 0;
        stateTime = 0;
        velocity.set(MINION_VELOCITY, 0);
        lockedOn = null;
    }

    public void update(float deltaTime) {
        // Adjust the collision detection box
        //collisionBox = new Rectangle(position.x + 1, position.y - 2, 1.1f, 1);
        //bounds = collisionBox;
        bounds.lowerLeft.set(position).sub(MINION_WIDTH / 2, MINION_HEIGHT / 2);

        switch(state) {

        case MINION_STATE_DEPLOY:
            // Move to lane
            if(position.x < 35 && position.y > World.LANE_1 + 1.5) {
                velocity.set(MINION_VELOCITY, -MINION_VELOCITY);
                position.add(velocity.x * deltaTime, velocity.y * deltaTime);
            } else {
                velocity.set(MINION_VELOCITY, 0);
                position.add(velocity.x * deltaTime, 0);
                state = MINION_STATE_ROUTE;
            }
            break;

        case MINION_STATE_ROUTE:
            canAttack = true;
            position.add(velocity.x * deltaTime, 0);
            break;

        case MINION_STATE_COMBAT:
            // If there is a target
            if(lockedOn.isAlive) {
                // If the minion can not attack
                if(!canAttack) {
                    attackTimer += deltaTime;
                    if(attackTimer > attackSpeed) {
                        attackTimer = 0;
                        canAttack = true;
                    }
                }
                // If the minion can attack
                else if(canAttack) {
                    animation = animation.ATTACKING;
                    canAttack = false;
                    lockedOn.life -= attack;
                }
                checkOpponent();
            } else {
                state = MINION_STATE_ROUTE;
            }
            break;

        case MINION_STATE_DEATH:
            animation = animation.DYING;
            if(!canDie) {
                deathTimer += deltaTime;
                if(deathTimer > 2) {
                    deathTimer = 0;
                    canDie = true;
                }
            }
        }

        stateTime += deltaTime;
    }

    private void checkOpponent() {
        if(lockedOn.life <= 0) {
            lockedOn.state = lockedOn.ENEMY_STATE_DEATH;
            lockedOn.isAlive = false;
            lockedOn.lockedOn = null;

            state = MINION_STATE_ROUTE; 
            animation = animation.WALKING;
            lockedOn = null;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

看起来你已将lockOn作为静态变量。通过阅读静态变量,我相信这意味着当你创建一个新的warrior并重置lockedOn时,你会影响所有人的所有lockedOn,因为lockedOn被应用于类而不是单个对象。因此,没有锁定的新对象将导致lockedOn对象为空并且离开。请尝试从动画类中删除静态,并告诉我它是否有效。

This is a good description of what I think is happening, see the code examples on counts