2014-09-15 1 views
1

방금 ​​Java, LWJGL 및 Slick Util을 사용하여 새로운 2D 게임을 시작했지만 충돌 감지를 수행하는 좋은 방법을 찾지 못했습니다. 원한다면 Rectangle intersect 메서드로 두 엔티티 간의 충돌을 쉽게 감지 할 수 있지만 지정한 특정 영역 만 충돌을 확인할 수 있습니다. 나는 모든 엔티티의 목록과 그 좌표를 생성 된 것으로 만들 수 있다고 생각했다. 그런 다음 목록을 통해 intersect 메서드를 실행했지만 게임이 업데이트 될 때마다 전체지도의 모든 엔티티와 충돌하는지 확인했다. 너무 비효율적이라고 생각합니다.2D 게임에서 충돌을 효과적으로 구현하려면 어떻게해야합니까?

누구든지 충돌 검색을 만드는보다 효율적인 방법을 알고 있습니까? 캐릭터가 움직일 때마다 엔티티가 있는지를 확인할 수있는 방법이 있다면 그것은 아마도 최고 일 것입니다.

정보가 충분하지 않거나이 소리를 너무 혼란스럽게 만들면 알려 주시면 문제를 명확히 할 수 있습니다. 또한 부차적 인 질문으로, 매끈한 util 또는 매끄러운 2D를 서로 사용하는 것의 이점은 무엇입니까? 도와 주셔서 감사합니다!

답변

1

이 문제를 해결하는 일반적인 방법은 장면 그래프로, 게임 세계의 객체를 계층 적으로 체계화하는 것입니다.

thisthis을 볼 수 있습니다.

단축 : 노드 아래에 객체를 논리적으로 그룹화하고 모든 하위 노드와 잎 (객체)을 포함하는 경계 사각형을 노드에 할당합니다. 모든 것이 트리에 액세스하기 위해 하나의 주 노드 아래에 다시 그룹화됩니다. 이제 주 노드에서 시작하여 노드와의 충돌에 대해 객체를 테스트 할 수 있습니다. 적중을 당하면 하위 노드와 나뭇잎을 확인합니다.

구현하는 데 다소 시간이 걸리지 만 트리 구조/그룹화가 올바르게 완료되면 CPU 사용량을 줄일 수 있습니다. 또한 서로 상대적으로 움직이는 객체를 쉽게 만드는 로컬 변환을 구현할 수 있다는 이점이 있습니다.

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를 사용합니다.

그런 방법으로 다른 프로그래머의 의견을 모릅니다.

관련 문제