我刚刚使用Java,LWJGL和Slick Util开始了一个新的2D游戏,但我似乎无法找到一个很好的方法来进行碰撞检测。 如果我想,使用Rectangle intersect方法检测2个实体之间的碰撞很容易,但它只能检查与您指定的某个区域的碰撞。 我原以为我可以创建每个实体及其坐标的列表,然后通过列表运行intersect方法,但是每次游戏更新时我会检查整个地图上每个实体的碰撞认为这样效率太低。
有谁知道创建碰撞检测的更有效方法?如果有某种方法我可以检查在角色移动的每一点是否都有一个实体可能是最好的。
如果我没有足够的信息,或者我说这个声音太混乱,请告诉我,我可以尝试澄清一些事情。另外作为一个附带问题,使用光滑的工具或光滑的2D相互之间有什么好处。谢谢你的帮助!
答案 0 :(得分:1)
解决这个问题的常用方法是场景图,即游戏世界对象的分层系统。
缩短:您在逻辑上将对象分组到节点下,并为节点分配一个包含其所有子节点和叶子(对象)的边界矩形。所有内容在一个主节点下再次分组以访问树。现在,您可以测试对象是否与节点发生冲突,通常从主节点开始。如果你受到了打击,你可以检查它的子节点并离开。
这需要一些时间来实现,但如果树结构/分组正确完成,可以减少CPU使用率。它还有一个好处,你可以实现局部变换,使对象相对移动更容易。
答案 1 :(得分:0)
因为我讨厌"通常的方式",我制作了所有坐标的数组,然后检查单个点是否达到了坐标。
以下是对我的代码进行略微修改以演示(它是3D):
for (CannonBall can : GameServer.ballss){ //Go through all cannonballs
if (can.owner != cl){ //Can.owner is the ship, cl is the player the cannonball is being checked with to see if colliding.
int distancex = (int) (can.x - cl.z);
int distancez = (int) (can.z - cl.x);
final int distancey = (int) (can.y - cl.y);
double xRot = Math.cos(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.sin(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
double zRot = Math.sin(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.cos(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
distancex = (int) xRot;
distancez = (int) zRot;
try{
if (true){ //Skip different coordinates for different ships for demonstration purposes
i = GameServer.coords[GameServer.DELTA + distancex][GameServer.DELTA + distancez][GameServer.DELTA + (distancey)];
}
if (i == 1){
if (can.owner != cl){
remcan.add(can);
if (can.type == 0){
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
if (can.type == 1){
double damage = (Math.random() * 500);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}else{
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
crash = true;
if (cl.damage < 1){
if (!cl.sinking){
cl.sinking = true;
}
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
GameServer.coords是一个int [] [] [],给出的坐标如下:
public static int[][][] coords;
public void CollisionSetup(){
try{
File f = new File("res/coords.txt");
String coords = readTextFile(f.getAbsolutePath());
for (int i = 0; i < coords.length();){
int i1 = i;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String x = coords.substring(i, i1).replace(",", "");
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String y = coords.substring(i, i1).replace(",", "");;
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String z = coords.substring(i, i1).replace(",", "");;
i = i1 + 1;
//buildx.append(String.valueOf(coords.charAt(i)));
////System.out.println(x);
////System.out.println(y);
////System.out.println(z);
//x = String.valueOf((int)Double.parseDouble(x));
//y = String.valueOf((int)Double.parseDouble(y));
//z = String.valueOf((int)Double.parseDouble(z));
double sx = Double.valueOf(x);
double sy = Double.valueOf(y);
double sz = Double.valueOf(z);
javax.vecmath.Vector3f cor = new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z));
//if (!arr.contains(cor)){
if (cor.y > 0)
arr.add(new javax.vecmath.Vector3f(cor));
if (!ship.contains(new Vector3f((int) sx, (int) sy, (int) sz)))
ship.add(new Vector3f((int) sx, (int) sy, (int) sz));
Float.parseFloat(z)));
}
}
public void setUpPhysics() {
//coords = new int[20][20];
coords = new int[80][80][80];
coords1 = new int[80][80];
//coords[-5 + DELTA][7 + DELTA] = 11;
for (javax.vecmath.Vector3f vec : arr){
coords[DELTA+(int) vec.x][DELTA+(int) vec.z][DELTA + (int) vec.y] = 1; //This is line 124
coords1[DELTA+(int) vec.x][DELTA+(int) vec.z] = 1;
}
}
虽然它对碰撞相互作用有限制,但它适用于炮弹与船碰撞并检查船的前部以查看它是否撞到了另一艘船。此外,它几乎不使用任何CPU。
不知道其他程序员对这种方法的看法。