这是我在同一领域遇到的第二个问题。。。第一个我甚至不知道我是怎么解决的。坐标系也是双坐标系。
这是物理类的"更新"代码,将由世界上的所有对象(玩家、敌人、物品)继承。所有这些对象都必须能够服从与世界的碰撞,所以……当它们具有xSpeed或ySpeed时,如果对象碰到实体(称为状态2)世界瓦片,这部分代码将运行以应用并"捕捉"对象到正确的空间。每个世界平铺为20x20像素。
问题:它工作得很好,除了。。。
如果捕捉到正确的磁贴,则无法向上或向下移动。(尽管你可以向左移动,然后向上或向下移动)
如果捕捉到底部磁贴,则无法向左或向右移动。(尽管你可以向上移动,然后向左或向右移动)
if(xSpeed<0){
try{
int dest = hitbox.x + (int)(xSpeed/20*tick);
if(Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2 || Ids.tiles[world[dest/20][(hitbox.y+hitbox.width)/20]].getState() == 2){
hitbox.x = (int)Math.ceil(dest/20.)*20;
xSpeed = 0;
}else{
hitbox.x += (int)(xSpeed/20*tick);
}
}catch(Exception e){
hitbox.x += (int)(xSpeed/20*tick);
}
}else if(xSpeed>0){
try{
int dest = hitbox.x+hitbox.width+(int)(xSpeed/20*tick);
if(Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2 || Ids.tiles[world[dest/20][(hitbox.y + hitbox.width)/20]].getState() == 2){
hitbox.x = dest/20*20 - hitbox.width;
xSpeed = 0;
}else{
hitbox.x += (int)(xSpeed/20*tick);
}
}catch(Exception e){
hitbox.x += (int)(xSpeed/20*tick);
}
}
if(ySpeed<0){
try{
int dest = hitbox.y + (int)(ySpeed/20*tick);
if(Ids.tiles[world[hitbox.x/20][dest/20]].getState() == 2 || Ids.tiles[world[(hitbox.x + hitbox.width)/20][dest/20]].getState() == 2){
hitbox.y = (int)Math.ceil(dest/20.)*20;
ySpeed = 0;
}else{
hitbox.y += (int)(ySpeed/20*tick);;
}
}catch(Exception e){
hitbox.y += (int)(ySpeed/20*tick);;
}
}else if(ySpeed>0){
try{
int dest = hitbox.y + hitbox.height + (int)(ySpeed/20*tick);
if(Ids.tiles[world[hitbox.x/20][dest/20]].getState() == 2 || Ids.tiles[world[(hitbox.x + hitbox.width)/20][dest/20]].getState() == 2){
hitbox.y = dest/20*20 - hitbox.height;
ySpeed = 0;
}else{
hitbox.y += (int)(ySpeed/20*tick);;
}
}catch(Exception e){
hitbox.y += (int)(ySpeed/20*tick);;
}
}
考虑右边缘(向右移动)碰撞时会发生什么。此条件通过:
Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2
假设CCD_ 1是5。那么一旦hitbox.x
为15,这将返回true。但随后将hitbox.x
重置为dest/20*20 - hitbox.width
,结果正好是它已经在的位置。然后,在垂直方向上,如果对象移动,则其最右侧边缘已经与瓷砖碰撞,因此无法移动。
要解决这个问题,在使用点击框查找网格位置时,从点击框大小中减去1个像素——当然是在除法之前。
如果您使用浮点坐标,那么您可以使用Math.ceil((hitbox.x + hitbox.width)/20.0) - 1
来产生类似的效果,而不需要任意的ε。