我正在为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;
}
}
}
答案 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