我正在用Java开发游戏,其中一部分要求对象在屏幕顶部产生并继续下降。我有三个可能会产生的对象,以及三个可能产生的x
坐标,它们都存储在一个名为xCoordinate[]
的数组中。
其中一个对象是一个名为Enemy
的类,它继承了一个名为FallingThings
的类。在FallingThings类中,我有生成新对象的方法,我的敌人方法如下:
public static void generateNewEnemy() {
xIndexEnemyOld = xIndexEnemy;
xIndexEnemy = new Random().nextInt(3);
if (delayTimer == 0) {
while (xIndexEnemy == xIndexEnemyOld) {
xIndexEnemy = new Random().nextInt(3);
}
}
if (xIndexEnemy != xIndexMoney && xIndexEnemy != xIndexFriend) {
Enemy enemy = new Enemy(xCoordinates[xIndexEnemy]);
enemies.add((Enemy) enemy);
} else {
generateNewEnemy();
}
}
xIndexEnemy
表示xCoordinates数组的索引
xIndexMoney
和xIndexFriend
是其他两个对象的xCoordinates
数组的索引(与这些值的比较可确保一个对象不会直接在另一个对象之上生成)。
delayTimer
变量表示新对象生成之间的随机延迟,这是在我的主类中先前设置的
我将Enemy
对象的每个实例存储在ArrayList
中。
一切都有效,除了有时候一个物体会在它自身产生的事实(例如,延迟为0,所以两个敌人的物体直接在彼此之间产生,然后以相同的速度向下坠落同时)。
过去两天我一直试图解决这个问题,但我明白为什么我的代码现在无法正常工作。我甚至尝试实现碰撞检测以检查空间中是否已存在另一个对象,但这也不起作用。
我非常感谢任何建议和想法。
答案 0 :(得分:0)
如我所见,如果延迟== 0一切都很好,但如果没有,你有机会用相同的指数产生新的敌人。如果delayTimer!= 0,可能要调用return;
<强>已更新强>
在这种情况下看看你有什么: OldEnemyIndex = 1 NewEnemyIndex = random(3) - &gt; 1 DelayTimer = 2
然后你没有传递给你的if语句,然后在下一个如果一切正常,如果你的敌人与金钱或其他东西没有相同的索引,所以你用与之前相同的索引创建新的敌人
答案 1 :(得分:0)
<强> EDIT2 强>
您似乎仍然不了解您的功能问题。在另一个答案中解决了这个问题,但我会尽力使其更清楚。
public static void generateNewEnemy() {
xIndexEnemyOld = xIndexEnemy;
这是错的。如果尚未实际使用新索引,则无法设置旧索引。
xIndexEnemy = new Random().nextInt(3);
if (delayTimer == 0) {
while (xIndexEnemy == xIndexEnemyOld) {
xIndexEnemy = new Random().nextInt(3);
}
}
这实际上没问题。你得到一个索引,直到得到一个不同的索引。它可能不是最优雅的解决方案,但它可以完成这项工作。
if (xIndexEnemy != xIndexMoney && xIndexEnemy != xIndexFriend) {
Enemy enemy = new Enemy(xCoordinates[xIndexEnemy]);
enemies.add((Enemy) enemy);
} else {
generateNewEnemy();
}
}
这是你的问题(同时将Old索引设置回那里)。您不仅需要生成与旧索引不同的索引,还必须与IndexMoney和IndexFriend不同。
现在,如果,例如,IndexOld = 0,IndexMoney = 1和IndexFriend = 2,会发生什么?你必须生成一个与0不同的索引,所以你得到(例如)1。IndexMoney也是1,因此条件将失败并且你进行递归调用。 (为什么你甚至有一个递归的电话?)
OldIndex为0,现在在下一个调用中你将其设置为1.所以IndexOld = 1,IndexMoney = 1和IndexFriend = 2.你现在看到问题了吗?重叠的索引现在是错误的。无论需要多少次递归调用,新索引都只能为0。
你不止一次在脚下射击自己。递归调用不会导致无限循环(实际上是堆栈溢出),因为您正在更改Old索引。 (这又是在错误的地方)
如果条件正在进行,那么新生成的索引不能与之前的索引中的任何一个重叠。从你之前说的不是你想要的。
您可以像这样简化您的功能,
public static void generateNewEnemy() {
xIndexEnemy = new Random().nextInt(3);
if (delayTimer == 0) {
while (xIndexEnemy == xIndexEnemyOld) {
xIndexEnemy = new Random().nextInt(3);
}
}
Enemy enemy = new Enemy(xCoordinates[xIndexEnemy]);
enemies.add((Enemy) enemy);
xIndexEnemyOld = xIndexEnemy;
// Now that you used the new index you can store it as the Old one
}
会起作用吗?当delayTimer为0时,它肯定会避免重叠,但我不知道你的其余代码(我也不想),你做了什么。这是你应该知道的。
关于我的建议,它们是如何生成所需索引的替代方案。我假设您会知道如何在代码中使用它们,但在修复实际问题后,您仍然可以自由地尝试它们。
原始答案
这是一个建议。
你可以做的一件事就是让这些敌人从阵列中“借用”元素。假设你有一个数组,
ArrayList< Float > coordinates = new ArrayList< Float >();
// Add the coordinates you want ...
您可以选择其中一个索引,但请使用数组的最大大小,然后删除您选择的元素。通过这样做,您将删除其中一个索引选项。
int nextIndex = new Random().nextInt( coordinates.size() );
float xCoordinate = coordinates.get( nextIndex );
coordinates.remove( nextIndex ); // Remove the coordinate
稍后,当你完成了这个值(比如,当足够的时间过去,或者敌人死亡)时,你可以把它放回到数组中。
coordinates.add( xCoordinate );
现在该值再次可用,您无需为检查索引而烦恼。
嗯,这是我的建议的总体思路。您将不得不对其进行调整以使其按您所需的方式工作,特别是当您将值重新放入数组时,因为我不知道您可以在代码中执行此操作。
修改强>
另一种选择是,保留以前拥有的数组。无需从中删除任何值或任何内容。
如果要获取新坐标,请创建一个仅包含可用值的额外数组,即不会与其他对象重叠的值。
...
if (delayTimer == 0) {
ArrayList< Integer > availableIndexes = new ArrayList< Integer >();
for ( int i = 0; i < 3; ++i ) {
if ( i != xIndexEnemyOld ) {
availableIndexes.add( i );
}
}
int selectedIndex = new Random().nextInt( availableIndexes.size() );
xIndexEnemy = availableIndexes.get( selectedIndex );
}
// Else no need to use the array
else {
xIndexEnemy = new Random().nextInt( 3 );
}
...
现在你确定你得到的索引应该是不同的,所以不需要检查它是否重叠。 缺点是你必须创建这个额外的数组,但它会使你的条件更简单。
(我从你的代码中保留了“新的Random()”,但是其他答案/评论指的是你应该使用单个实例,请记住)