2014-07-15 4 views
1

하나의 사각형이 다른 사각형과 충돌했다는 문제가 있습니다. 그래서 내 질문은 어떻게 충돌을 검사하는 intersect 메서드를 얻을 수 있습니까? 아니면이 상황에서 충돌을 처리 할 수있는 다른 방법이 있습니까?Slick2D 사각형 충돌 감지

플레이어의 캐릭터가 화면의 오른쪽에 있고 적이 왼쪽에있는 턴 기반 전투 게임 (파이널 판타지 또는 드래곤의 전설과 비슷합니다)을 만들고 있습니다. 플레이어와 적 각각이 차례로 공격을합니다. 따라서 플레이어가 공격을하면 스프라이트 애니메이션이 화면을 가로 질러 오른쪽에서 왼쪽으로 움직여 적, 공격 앞에서 멈출 때까지 시작 좌표로 돌아갑니다. 플레이어와 적 모두 주위에 각 캐릭터의 경계를 나타내는 직사각형이 그려져 있습니다.

플레이어가 앞으로 움직이면 적의 직사각형을 통과하고 그 안에 멈 춥니 다. 이 시점에서 콘솔에 "INTERSECT!"라고 출력되어야합니다. 두 직사각형 사이에 충돌이 있음을 보여주기 위해 불행히도 존재하지 않습니다.

클래스 내에서 불필요한 코드를 생략하고 내 문제와 관련된 코드를 제공하려했음을 유의하십시오. 이 내 플레이어 클래스에서 엿볼

public class GameClass extends BasicGame{ 
//other variable declarations 

public void init(GameContainer container) throws SlickException { 
player = new Player(); 
enemy = new Enemy(); 
skeleton = new Skeleton(); 
enemy = skeleton; 
playX = player.getStartX(); //700 
playY = player.getStartY(); //140 
playW = player.rect.getWidth(); //40 
playH = player.rect.getHeight(); //70 
enemyX = enemy.getStartX(); //100 
enemyY = enemy.getStartY(); //140 
enemyWidth = enemy.getWidth(); //50 
enemyHeight = enemy.getHeight(); //55 

SpriteSheet sheet = new SpriteSheet("data/homeranim.png", 36, 65); 
    anim = new Animation(); 
    for (int i=0;i<8;i++) { 
     anim.addFrame(sheet.getSprite(i,0), 150); 
    } 
} 

public void render(GameContainer container, Graphics g) 
     throws SlickException { 
anim.draw(playX,playY); // draws player animation 
skeletonAnim.draw(enemyX, enemyY); // draws enemy 
g.draw(player.rect); //draws player bounds 
g.draw(enemy.rect); //draws enemy bounds 
} 

public void update(GameContainer container, int delta) 
     throws SlickException { 
playerUpdate(delta); 
if (player.rect.intersects(enemy.rect)) { 
      System.out.println("INTERSECT!"); 

     System.out.println("Player minX: " + player.rect.getMinX()); 
     System.out.println("Player maxX: " + player.rect.getMaxX()); 
     System.out.println("Enemy minX: " + enemy.rect.getMinX()); 
     System.out.println("Enemy maxX: " + enemy.rect.getMaxX()); 
     } 
     } 

public void playerUpdate(int delta) { 
    if (playerForward == true){ 
     playX -= delta * 0.4f; 
     if (playX <= 140) { 
      playX = 140; 
      playerForward = false; 
      playerBackward = true;} 
    } 

    if (playerBackward == true) { 
     playX += delta * 0.4f; 
     if (playX >= 700) { 
      playX = 700; 
      playerBackward = false; 
      delay = 1250; 
    } 

public void keyReleased(int key, char c) { 
     if (key == Input.KEY_ENTER){ 
      playerForward = true;} 
} 
} 

:

public class Player { 

private int startX = 700; 
private int startY = 140; 
public Shape rect = new Rectangle(startX, startY, 40, 70); 
//plus getters and setters 
} 

그리고 내 전체 적 클래스 :

public class Enemy { 

private int startX, startY, width, height; 
public Shape rect = new Rectangle(startX, startY, width, height); 
// plus getters and setters 
    } 

내 해골

이것은, GameClass 내 진입 점입니다 클래스 확장 Enemy :

public class Skeleton extends Enemy { 

public Skeleton() { 
    // TODO Auto-generated constructor stub 
    setMaxHealth(120); 
    setStartX(100); 
    setStartY(140); 
    setWidth(50); 
    setHeight(55); 
} 

} 

참고 : g.drawRect()를 g.draw()로 전환 했으므로 적 사각형이 그려지지 않습니다. 시작 지점에서

사각형 경계 : http://i.imgur.com/QDDk858.png

사각형 바인딩 충돌이 있어야한다 : http://i.imgur.com/pOANfvN.png

나는 내 문제가 무엇인지를 보여 충분한 코드를 제공 한 바랍니다. 나는 운이없는 몇 시간 동안 인터넷을 뒤적 거리다. 제공해야하는 다른 코드가 있으면 언제든지 물어보십시오. 여러분의 도움과 성원에 진심으로 감사드립니다!

+0

그럼 정확한 문제는 무엇입니까? intersects 메서드가 실행되고 있지 않습니까? – 1337

+0

그리고 x 및 y 대신 centerX 및 centerY로 히트 박스를 만드는 이유는 무엇입니까? Rectangle 생성자의 인수는 가운데가 아니라 (startX, startY, width, height)입니다. 그래서 이것은 히트 박스가 상쇄 될 때 문제가 될 수 있습니다. – 1337

+0

정확하게, intersects 메서드가 트리거되지 않습니다. centerX와 centerY 변수는 직사각형이 오프셋이나 그 밖의 어떤 것도 그려지지 않기 때문에 이름이 잘못 지정되었습니다. 그것들은 startX와 startY를 나타냅니다. 편집 : startX, 등 centerX 변경했습니다 – Breezy

답변

1

히트 박스 위치 자체는 업데이트하지 않습니다.

당신이 그리는 :

g.drawRect(playX, playY, playW, playH); //draws player bounds 
g.drawRect(enemyX, enemyY, enemyW, enemyH); //draws enemy bounds 

그러나 이것은 플레이어/원수의 단지 위치의 실제 hitbox에서 아니고 hitboxes 자체가 때로 믿을 수있는 동안 여기에 그려진 사각형이 올바른 위치에있을 것입니다 '티.제대로

  • 형식 코드 : 당신을 위해, 자바에서 몇 가지 팁을 게임 개발에 새로운 것 같다로서, 또한

    public void update(GameContainer container, int delta) 
    { 
        playerUpdate(delta); 
    
        player.rect.setLocation(playX, playY); 
        enemy.rect.setLocation(enemyX, enemyY); // update the hitboxes to the new positions 
    
        if (player.rect.intersects(enemy.rect)) 
        { 
         System.out.println("INTERSECT!"); 
        } 
    } 
    
    public void playerUpdate(int delta) 
    { 
        if (playerForward == true) 
        { 
         playX -= delta * 0.4f; 
    
         if (playX <= 140) 
         { 
          playX = 140; 
          playerForward = false; 
          playerBackward = true; 
         } 
        } 
    
        if (playerBackward == true) 
        { 
         playX += delta * 0.4f; 
    
         if (playX >= 700) 
         { 
          playX = 700; 
          playerBackward = false; 
          delay = 1250; 
         } 
        } 
    } 
    
    public void keyReleased(int key, char c) 
    { 
        if (key == Input.KEY_ENTER) 
        { 
         playerForward = true; 
        } 
    } 
    

    :

    난 당신이 다음과 같이 제안

if, else, switch, while, for 등의 경우 항상 {...} 뒤에 넣으십시오. 적절한 줄 들여 쓰기.

  • 씽크 OO (객체 지향)는

이 사람은 매우 중요하다. 적과 플레이어 클래스는 둘 다 비슷한 종류의 엔티티 클래스를 확장해야합니다. 왜냐하면 두 클래스 모두 비슷한 동작 (코드 중복 방지)을 얻기를 원할 것이기 때문입니다. 수퍼 클래스와 유사한 동작을 요약하고 몇 가지 조정 가능한 매개 변수로 제어되는 동작을 단순화하는 등의 작업을 수행 할 수 있습니다.

예를 들어, 적과 플레이어의 위치를 ​​기본 클래스의 정적 정수로 저장합니다. 이것은 OO가 아닙니다. 위치를 원하는 방식으로 구현할 수있는 엔티티 클래스로 이동하십시오.

귀하의 갱신 (...) 메소드가 필요 결코에도 SlickException을 던졌습니다 아무 이유없이 예외를 던지지 마십시오.

  • 하는 캡슐화

이 초보자를 많이 할 무언가에 대한주의 : 그냥, 일부 매개 변수를 잡아 개인 (또는 어쩌면 대중)와 같은 클래스에 넣어와 getters- 생성 그들을위한 세터. 이것은 이 아니고 캡슐화입니다. 이것은 처음부터 공개하는 것만 큼 나쁜 것입니다.

하지만 모든 것을 공개하지 않는 이유는 무엇입니까?

우리는 나중에 변경하려는 것이있을 수있는 특정 구현 때문에 일부 사용자가 (심지어는 우리 자신이) 일부 매개 변수에 의존하는 것을 원하지 않습니다. 가능한 모든 값을 변경하기 만하면되는 것이 아니라, 캡슐화의 의미는 우리가 사용하게 될 구현의 종류와 독립적이며, 설정/변경할 수있는 것을 지키면서 코드의 유용성을 보호하는 것입니다.

  • 성능 문제

이것은 당신이 소프트웨어의 종류, 조심해야 할 부분 중 하나입니다 않습니다,하지만 당신은 종종 가장 크게 게임에서 결과를 볼 수 있습니다. 성과는 중요합니다! 그리고 이것으로 모든 세부 사항을주의해야한다는 의미는 아니지만 코드를 개선하고 고정시키는 방법에 대한 개요를 유지하십시오. 특히 update (..) 및 Slick2D에서 렌더링 (..).코멘트에서 논의 된 다른 문제에 대한 해결책으로 업데이트

: 그들이가 정수 0 기본적 당 값이 할당되지 않습니다으로

public class Enemy { 

    private int startX, startY, width, height; 
    public Shape rect = new Rectangle(startX, startY, width, height); 
    // plus getters and setters 
} 

폭과 높이 만 0이 될 수 있습니다, 그래서 적 사각형 히트 박스는 너비가 0이고 트리거하지 않습니다.

같은 시도 :이 작업을해야

public class Enemy { 

    private int startX, startY, width = 50, height = 70; 
    public Shape rect = new Rectangle(startX, startY, width, height); 
    // plus getters and setters 
} 

,하지만 당신은 아마 적 클래스에 모든 속성을 이동하고 생성자에 넣어해야합니다.

+0

예, 저는 Java 게임 개발을 처음 접했습니다! 유용한 팁을 주셔서 대단히 감사합니다. Entity superclass는 제가하려고하는 것에 대해 훨씬 더 좋은 아이디어가 될 것입니다. g.drawRect()를 g.draw (player.rect)로 바꾸려고 시도했지만 추천 한 두 개의 setLocation() 행을 추가했습니다. 불행히도 intersects 메서드가 트리거되지 않습니다. 나는 당신의 제안에 따라 조정을 계속할 것입니다. – Breezy

+0

@RookieCookie 흠 ... 이것은 정말 이상합니다. 일반적으로 intersects 메서드는 문제없이 작동합니다. 직사각형의 경계가 실제로 올바르게 업데이트되는지 살펴 보셨습니까? 그냥 player.rect.getMinX(), player.rect.getMaxX() ... 등등을 인쇄하고 그 내용을 게시하십시오. – 1337

+0

나는 동의한다, 나는 intersects 방법이 나에게 그런 두통을주지 않을 것이기를 바랐다! 내가 제안한 출력 라인과 사진을 업데이트했습니다. 마지막 코멘트에서 언급 한 내용이 맞는지 말해주세요. 현재 2 개의 링크 만 게시 할 수 있습니다 (충분한 담당자가 아님). – Breezy