我定义了这个简单的方法:
public static boolean isBorder(int x, int y) throws CollisionDetectionException {
try {
if ( (levelItems[x][y] instanceof StaticGameObject && levelItems[x][y].isVisible()) ||
(levelItems[x-1][y] instanceof StaticGameObject && levelItems[x-1][y].isVisible()) ||
(levelItems[x][y+1] instanceof StaticGameObject && levelItems[x][y+1].isVisible()) ||
(levelItems[x][y-1] instanceof StaticGameObject && levelItems[x][y-1].isVisible()) ||
(levelItems[x-1][y-1] instanceof StaticGameObject && levelItems[x-1][y-1].isVisible()) ||
(levelItems[x-1][y+1] instanceof StaticGameObject &&levelItems[x-1][y+1].isVisible()) ||
(levelItems[x+1][y] instanceof StaticGameObject && levelItems[x+1][y].isVisible()) ||
(levelItems[x+1][y+1] instanceof StaticGameObject && levelItems[x+1][y+1].isVisible()) ||
(levelItems[x+1][y-1] instanceof StaticGameObject && levelItems[x+1][y-1].isVisible()) ) {
return true;
} else {
return false;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new CollisionDetectionException("Collision couldn't be checked because checking position " + x + "/" + y + " caluclated values below (0/0)");
}
}
如你所见,我有一个2维数组。现在我想检查一个特定的位置((x / y) - >方法参数),如果在2维数组的相邻字段中有任何可见的StaticGameObject。
levelItems数组由所谓的GameObject组成。 StaticGameObject是GameObject的直接子类。
任何提示如何改进此方法?
答案 0 :(得分:13)
向GameObject添加方法
bool isBorderObject() { return false; }
然后在StaticGameObject中重写
bool isBorderObject() { return true; }
将测试更改为
(levelItems[x][y].isBorderObject() && levelItems[x][y].isVisible())
此外,if可以嵌套为
for (int i = x-1; i <= x+1; ++i) {
for (int j = y-1; j <= y+1; ++j) {
GameObject item = levelItems[i][j];
if (item.isBorderObject() && item.isVisible())
return true;
}
}
return false;
答案 1 :(得分:3)
(免责声明:我参与了在很多移动设备上运行的Java游戏)
人们已经展示了如何简化所有这些 if 语句。我想补充一点,定义你自己的CollisionDetectionException可能完全有点过分了。
首先,在OO级别不存在这样的低级Java细节:异常,尤其是已检查的异常,是真正不必要的Java特性。一些非常好且非常令人印象深刻的Java框架主要与它们一样,就像Spring一样。然后,许多非常令人印象深刻和功能强大的应用程序,由数以百万计的代码行组成,运行得非常好,没有使用检查异常的概念,因为它们很好地用语言编写,没有这种类型的概念(再次:在OO级别不存在“已检查的异常”,因此任何OOA / OOD到OOP而不需要使用已检查的异常)。
在任何情况下:确实没有理由将ArrayIndexOutOfBoundException转换为您自己的特定已检查异常。这意味着您计划使用异常进行流量控制,这是一个 HUGE no-no。
然后,关于你的“isBorder”测试...你可能不需要那样。你认为你这样做,但你真的没有。你为什么想知道它是否是“边界”?为了检测碰撞,我想。
你正在使用静态方法来检测它是否是边界,静态是OO的反论点。重要的是您在对象之间传递的消息。您可能有所有对象响应某些 isCollidingWith(...)消息:“border”对象知道它们是边框,他们将知道如何处理 isCollidingWith(。 ..)消息。
然后你可以更进一步:你可以有一些 resolveCollisionWith(...)方法而不是 isCollidingWith(...)。
public class Wall implements MySuperAbstraction {
int wallHitPoints = 42;
boolean isWallStillUp = true;
void resolveCollisionWith( SomeObject o ) {
if ( o.isStrongEnoughToHarmWall ) {
wallHitPoints--;
isWallStillUp = wallHitPoints > 0;
}
}
}
这只是一段快速的代码,并没有处理 SomeObject 在他撞到墙壁时需要反弹的事实等等,但重点是:在OO对象中知道他们之间如何沟通。他们知道如何处理传递的各种信息。
如果你想做OO,那么我可以告诉你的是,Java的静态, instanceof 和已检查的异常绝对不是那样的。基本上,他们是OO的反论文:) ]
答案 2 :(得分:2)
这应该摆脱你拥有的极大if
块:
for(int col = x-1; col <= x+1; col++)
{
for(int row = y-1; row <= y+1; row++)
{
if(levelItems[row][col] instanceof StaticGameObject && levelItems[row][col].isVisible())
return true;
}
}
(这个解决方案只会减少疯狂if
,而不是摆脱instanceof
,正如你所看到的那样)
当然,在我的示例和你的示例中,都应该确保检查数组边界问题。
答案 3 :(得分:2)
对@ Lou的解决方案的修订,即有一个方法和一个循环。
for (int i = 0; i < 9; i++)
if (levelItems[x-1 + i/3][y-1 + i%3].isBorderObjectVisible())
return true;
return false;
答案 4 :(得分:1)
想想“控制倒置”。
作为示例,如何将此方法引入GameObject类:
public boolean
isBorder()
{
return false;
}
并在StaticGameObject类中重写:
public boolean
isBorder()
{
return self.isVisible();
}
简化上面的代码?
答案 5 :(得分:1)
另一个不错的技术是拥有一个返回相邻单元格集的函数。通过这种方式,您可以避免(或无论如何移动)双循环。更好地分离关注点;当你发现你的算法忘记了越界条件时,只有一个地方可以修复它。
public Set<GameObject> adjacentItems(int x, int y) {
Set<GameObject> set = new HashSet<GameObject>();
for (int i = -1; i < 2; ++i)
for (int j = -1; j < 2; ++j)
set.add(levelItems[x+i][y+j]);
return set;
}
public boolean isBorder(int x, int y) {
for (GameObject item : adjacentItems(x, y))
if (item.isBorder() && item.isVisible())
return true;
return false;
}
答案 6 :(得分:0)
不要让它变得更复杂。只需确保GameObject
的所有子类都实现isVisible
。这就是全部。
如果您需要同时区分可移动与不可移动,那么您需要两种方法:
isVisible - 可见或不可见
isMovable - 可移动或不移动
您永远不需要instanceof
。
[问题尚不清楚,但似乎StaticGameObject
类实际上意味着GameObject
的子类isMovable()
为false。]