我正在为课程做一个编程项目。我们正在编制游戏突破,包括一个球,一个球拍,四个边缘和砖块。当检测到碰撞时,球从不同的物体上反弹并且每个物体在其自身上执行不同的操作。下面是我的代码,目前无法正常工作。我正在尝试使用对象的位置(它的中心点)来构造一个有界框和每个边(顶部,底部,左边,右边)的值来计算框是否命中。我在脑海中想到,可能有两种类型的碰撞,一种是角落撞击,一种是一种物体撞击另一种物体中间的某处。如果可以,请查看我的代码并提供帮助。我不知道是否有更好的方法来做我正在尝试做的事情,但我目前无法正常工作并且几乎一直都会返回真值。
这是代码的一部分,它检查每个能够与可能发生碰撞的其他对象发生碰撞的对象。它还会移动每个物体并勾选游戏的时钟。
/**
* Tell the GameWorld that the "game clock" has ticked. A clock tick in the GameWorld has the
* following effects: (1) all movable objects are told to update their positions according to there
* current heading and speed, (2) the "elapsed game time" is incremented by one and (3) all Items are
* checked for a collision.
*/
public void tickClock() {
gameClock++;
Iterator theElements0 = listOfGameObjects.getIterator();
while (theElements0.hasNext()){
GameObject gObj = (GameObject) theElements0.getNext();
if ( gObj instanceof IMovable){
IMovable mObj = (IMovable)gObj;
mObj.move(gameClock);
}
}
Iterator theElements1 = listOfGameObjects.getIterator();
while (theElements1.hasNext()){
GameObject gObj0 = theElements1.getNext();//get a collidable object.
if(gObj0 instanceof ICollider){
ICollider curObj = (ICollider) gObj0;
//check if this object collides with any OTHER object.
Iterator theElements2 = listOfGameObjects.getIterator();
while(theElements2.hasNext()){
GameObject gObj1 = theElements2.getNext();
if(gObj1 != curObj && gObj1 instanceof ICollider) {
ICollider otherObj = (ICollider) gObj1;
if (curObj.collidesWith(otherObj)){
curObj.handleCollision(otherObj);
}
}
}
}
}
setChanged();
notifyObservers();
}
这是代码的一部分,用于确定对象是否与另一个对象发生冲突,以及如果它有相应的操作。这部分代码具体来自于球对象,因此当它碰到砖块时执行的动作是ySpeed被反转。
public boolean collidesWith(ICollider otherObj) {
GameObject gObj = (GameObject) otherObj;
//this collider
int r1 = (int) (getX() + getWidth()/2);
int l1 = (int) (getX() - getWidth()/2);
int t1 = (int) (getY() + getHeight()/2);
int b1 = (int) (getY() - getHeight()/2);
//the other collider
int r2 = (int) (gObj.getX() + gObj.getWidth()/2);
int l2 = (int) (gObj.getX() - gObj.getWidth()/2);
int t2 = (int) (gObj.getY() + gObj.getHeight()/2);
int b2 = (int) (gObj.getY() - gObj.getHeight()/2);
//corner collision check
if(r1>l2 && t2>b1 && t1>t2 && b1>b2){
System.out.println("Corner Collision check 1");
return true;
}
if(r2>l1 && t2>b1 && t1>t2 && b1>b2){
System.out.println("Corner Collision check 2");
return true;
}
if(r2>l1 && t1>b2 && t2>t1 && b2>b1){
System.out.println("Corner Collision check 3");
return true;
}
if(r1>l2 && t1>b2 && t2>t1 && b2>b1){
System.out.println("Corner Collision check 4");
return true;
}
//middle collision check
if(l1>l2 && r1<r2 && t1<t2 && b1<b2){
System.out.println("middle collision check 1");
return true;
}
if(l1>l2 && r1<r2 && t1>t2 && b1>b2){
System.out.println("middle Collision check 2");
return true;
}
if(l1<l2 && r1<r2 && t1<t2 && b1>b2){
System.out.println("middle Collision check 3");
return true;
}
if(l1>l2 && r1>r2 && t1<t2 && b1>b2){
return true;
}
return false;
}
public void handleCollision(ICollider otherObject) {
if(otherObject instanceof Brick){
System.out.println("Brick Hit");
ySpeed = -(ySpeed);
}
}
答案 0 :(得分:9)
您只需要检查边界框的边。一些伪代码可能看起来像。
if Rect1[RIGHT] < Rect2[LEFT] or
Rect1[LEFT] > Rect2[RIGHT] or
Rect1[TOP] < Rect2[BOTTOM] or
Rect1[BOTTOM] > Rect2[TOP]
then return false
else return true
这要说的是,如果X或Y坐标系上存在任何可能存在的间隙,那么就不可能发生碰撞。这是SAT (Separating Axis Theorem)
的非常简单版本在视觉上看起来像这样的小图像,同样的想法也适用于此。
这应该意味着类似于以下内容应该起作用。请注意我没有测试它,但可以引导你朝正确的方向发展。
public boolean collidesWith(ICollider otherObj) {
GameObject gObj = (GameObject) otherObj;
//this collider
int r1 = (int) (getX() + getWidth()/2);
int l1 = (int) (getX() - getWidth()/2);
int t1 = (int) (getY() + getHeight()/2);
int b1 = (int) (getY() - getHeight()/2);
//the other collider
int r2 = (int) (gObj.getX() + gObj.getWidth()/2);
int l2 = (int) (gObj.getX() - gObj.getWidth()/2);
int t2 = (int) (gObj.getY() + gObj.getHeight()/2);
int b2 = (int) (gObj.getY() - gObj.getHeight()/2);
if (r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2)
return false;
else
return true;
/* Or could be shortened down to
return !(r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2) */
}
代码的减少,你不会说;)