2017-12-04 23 views
0

플레이어가 장애물을 통해 다각형을 안내하는 Java에서 2D 게임을 만들고 있습니다. 다각형은 위아래로 움직이며 게임 세계는 좌우로 스크롤됩니다. 그 중심을 중심으로 회전하려면 다각형이 필요하지만, 점을 이동하기 때문에 끊임없이 점이 변환되기 때문에 움직입니다. 원래 중심점으로 다시 변환하려고 시도하고 회전 시키면 다시 작동하지 않습니다. 도형의 중심을 어떻게 구합니까? 화면의 중앙움직이는 모양을 중심으로 회전하십시오.

@Override 
public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2D = (Graphics2D)g; 

    Graphics g2 = g.create(); 
    Graphics2D copy = (Graphics2D)g2; 




    copy.rotate(-angleRad, xPos, yPos); 

    copy.translate(0, -moveY); 

    g2D.translate(-moveX, 0); 

    copy.draw(player.shape); 

    for (Rectangle2D.Double r: DronePilot.rocksFloorArray) { 
     g2D.draw(r); 
    } 
    for (Rectangle2D.Double r: DronePilot.rocksCeilArray) { 
     g2D.draw(r); 
    } 
    for (Rectangle2D.Double r: DronePilot.roomsArray) { 
     g2D.draw(r); 
    } 
} 

(X 좌표, Y 좌표)됩니다 여기

@Override 
public void actionPerformed(ActionEvent e) { 

    double theta = angleRad+90; 
    if (up == true) { 
     if (accelerating == false) { 
      time2 = 0; 
      moveX0 = moveX; 
      moveY0 = moveY; 
      accelerating = true; 
     } 
     time1++; 
     double t = time1/500; 
     if (accCount % 10 == 0) { 
      DronePilot.velocity++; 
     } 
     moveX = moveX0 + velX*Math.cos(theta)*t; 
     moveY = moveY0 + velY*Math.sin(theta)*t-(1/2d)*g*Math.pow(t, 2); 
     velX = (DronePilot.velocity)*Math.cos(theta); 
     velY = (DronePilot.velocity)*Math.sin(theta)-g*(t); 
     accCount++; 
    } else if (up == false){ 
     if (accelerating == true) { 
      time1 = 0; 
      moveX0 = moveX; 
      moveY0 = moveY; 
      accelerating = false; 
     } 
     time2++; 
     double t = time2/500; 
     moveX = moveX0 + velX*Math.cos(theta)*t; 
     moveY = moveY0 + velY*Math.sin(theta)*t-(1/2d)*g*Math.pow(t, 2); 
     accCount = 0; 
    } if (left == true) { 
     angleCount++; 
     if (angleCount % 2 == 0) { 
      angleDeg++; 
     } 
     angleRad = Math.toRadians(angleDeg); 
    } else if (right == true) { 
     angleCount--; 
     if (angleCount % 2 == 0) { 
      angleDeg--; 
     } 
     angleRad = Math.toRadians(angleDeg); 
    } 
    repaint(); 
} 
} 

그리고 내의 paintComponent 방법은 다음과 같습니다

은 2ms의 타이머에 내 움직임 계산이다.

+0

음에 영향을주지 않습니다.나는 당신이 먼저 위치를 번역하고 싶다고 가정 할 것이다. 이것은 중심 위치에 대해 객체를 회전시키는 것이 훨씬 더 쉽다. – MadProgrammer

+0

당신은 또한 모든 종류의 흥미를 유발할 수있는'g2D'와'copy'를 번역하고있는 것처럼 보인다. 바람직하지 않은) 이슈 – MadProgrammer

답변

1

변환은 (일반적으로) 당신의 위의 코드에서

public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2D = (Graphics2D)g; 

    Graphics g2 = g.create(); 
    Graphics2D copy = (Graphics2D)g2; 

    copy.rotate(-angleRad, xPos, yPos); 
    copy.translate(0, -moveY); 

    g2D.translate(-moveX, 0); 

    copy.draw(player.shape); 
    for (Rectangle2D.Double r: DronePilot.rocksFloorArray) { 
     g2D.draw(r); 
    } 
    for (Rectangle2D.Double r: DronePilot.rocksCeilArray) { 
     g2D.draw(r); 
    } 
    for (Rectangle2D.Double r: DronePilot.roomsArray) { 
     g2D.draw(r); 
    } 
} 

을 합성, 원래 Graphics 상황과 copy 모두를 번역하고 있습니다. 이 문맥에서는 copy은 원본의 영향을받지 않으며 원본은 copy에 의해 영향을받지 않지만 원본 컨텍스트는 공유 된 리소스이며 번역을 재설정하지 않으므로 계속해서 매번 번역 된 컨텍스트 (compounding).

일반적으로 엄밀히 말하자면 모든 변환을 한 복사본에 대해 수행하고 완료되면 처리하십시오. 예를 들어

...

Graphics2D g2d = (Graphics2D)g.create(); 
AffineTransform at = AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y); 
at.rotate(Math.toRadians(angle), player.getBounds2D().getCenterX(), player.getBounds2D().getCenterY()); 
g2d.setTransform(at); 
g2d.setColor(Color.RED); 
g2d.fill(player); 
g2d.setColor(Color.BLACK); 
g2d.draw(player); 
g2d.dispose(); 

이 기본적으로 플레이어의 위치로 물체의 위치를 ​​변환 한 후

당신은 또한 하나를 적용 할 수있는 개체의 중심에 대한 객체를 회전 해당 컨텍스트의 복사본을 만들고 복합화 된 다른 변환을 적용합니다 (따라서 컨텍스트 translate 하나의 컨텍스트에서 복사 한 다음 rotate 복사하고 첫 번째 번역은 여전히 ​​복사본에 적용됨)

(이 센터 지점의에 대해)을 Path2D를 사용
  • 을 플레이어 오브젝트를 번역하고 회전 할 Graphics 상황과 AffineTransform을 사용

    이 놀라운 간단한 예는 두 개의 기본 예제를 보여줍니다은 ...

    1. 변형 된 형태를 생성하는 이 예제는 두 개의 객체를 만들지 만, 하나의 AffineTransform을 번역하고 회전하여 한 번 적용 할 수 있습니다. 두 경우 모두

    는, 그들은`AffineTransform`를 사용하는 대신`Graphics` 컨텍스트를 번역의 원래 모양

    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.EventQueue; 
    import java.awt.Graphics; 
    import java.awt.Graphics2D; 
    import java.awt.Point; 
    import java.awt.Rectangle; 
    import java.awt.Shape; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.awt.geom.AffineTransform; 
    import java.awt.geom.Path2D; 
    import java.awt.geom.Rectangle2D; 
    import java.util.Random; 
    import javax.swing.JFrame; 
    import javax.swing.JPanel; 
    import javax.swing.Timer; 
    
    public class Test { 
    
        public static void main(String[] args) { 
         new Test(); 
        } 
    
        public Test() { 
         EventQueue.invokeLater(new Runnable() { 
          @Override 
          public void run() { 
           JFrame frame = new JFrame(); 
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
           frame.add(new TestPane()); 
           frame.pack(); 
           frame.setLocationRelativeTo(null); 
           frame.setVisible(true); 
          } 
         }); 
        } 
    
        public class TestPane extends JPanel { 
    
         private Shape player; 
         private Point playerPoint; 
         private float angle; 
         private float deltaZ = 1.0f; 
    
         private int deltaX, deltaY; 
    
         public TestPane() { 
          player = new Rectangle(0, 0, 20, 20); 
          playerPoint = new Point(80, 80); 
          Random rnd = new Random(); 
          deltaX = 1; 
          deltaY = -1; 
    
          Timer timer = new Timer(5, new ActionListener() { 
           @Override 
           public void actionPerformed(ActionEvent e) { 
            playerPoint.x += deltaX; 
            playerPoint.y += deltaY; 
    
            Shape rotatedPlayer = rotatedAndTranslatedPlayer(); 
            Rectangle2D bounds = rotatedPlayer.getBounds2D(); 
            if (bounds.getX() < 0.0) { 
             playerPoint.x = (int)(bounds.getX() * -1); 
             deltaX *= -1; 
            } else if (bounds.getX() + bounds.getWidth() >= getWidth()) { 
             playerPoint.x = getWidth() - (int)bounds.getWidth(); 
             deltaX *= -1; 
            } 
            if (bounds.getY() < 0) { 
             playerPoint.y = 0; 
             deltaY *= -1; 
            } else if (bounds.getY() + bounds.getHeight() > getHeight()) { 
             playerPoint.y = getHeight() - (int)bounds.getHeight(); 
             deltaY *= -1; 
            } 
            angle += deltaZ; 
            repaint(); 
           } 
          }); 
          timer.start(); 
         } 
    
         @Override 
         public Dimension getPreferredSize() { 
          return new Dimension(200, 200); 
         } 
    
         protected Shape rotatedAndTranslatedPlayer() { 
          Path2D.Double rotated = new Path2D.Double(player, AffineTransform.getRotateInstance(
            Math.toRadians(angle), 
            player.getBounds2D().getCenterX(), 
            player.getBounds2D().getCenterY())); 
          return new Path2D.Double(rotated, AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y));    
         } 
    
         // Simply paints the "area" that the player takes up when it's rotated and 
         // translated 
         protected void paintAutoTranslatedShape(Graphics2D g2d) { 
          g2d.setColor(Color.DARK_GRAY); 
          g2d.fill(rotatedAndTranslatedPlayer().getBounds2D()); 
         } 
    
         // Uses a AffineTransform to translate and rotate the player 
         protected void paintPlayer(Graphics2D g2d) { 
          AffineTransform at = AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y); 
          at.rotate(Math.toRadians(angle), player.getBounds2D().getCenterX(), player.getBounds2D().getCenterY()); 
          g2d.setTransform(at); 
          g2d.setColor(Color.RED); 
          g2d.fill(player); 
          g2d.setColor(Color.BLACK); 
          g2d.draw(player); 
         } 
    
         @Override 
         protected void paintComponent(Graphics g) { 
          super.paintComponent(g); 
          Graphics2D g2d = (Graphics2D) g.create(); 
          paintAutoTranslatedShape(g2d); 
          g2d.dispose(); 
          g2d = (Graphics2D) g.create(); 
          paintPlayer(g2d); 
          g2d.dispose(); 
         } 
    
        } 
    } 
    
  • +0

    다음 질문을 따르십시오 : Path2D 생성 및 드로잉, createTransformedShape 생성 및 드로잉, 그리고 AffineTransform을 그래픽 컨텍스트에 적용하고 드로잉하는 것의 차이점은 무엇입니까? 이 모든 것들이 테스트에서 다른 결과를주었습니다. – Denis

    +0

    셰이프를 변형하면 1 : 'AffineTransform'을 기반으로 변형 된 셰이프의 복사본을 생성합니다. 다른 셰이프에는 영향을 미치지 않으며 원본 셰이프에도 영향을 미치지 않습니다. 2 : 조심하지 않으면 문제가 될 수있는 '그래픽'컨텍스트에 영향을주지 않습니다. 3 : 경계를 확인한 것처럼'Graphics' 컨텍스트가 필요없이 변환 된 모양을 결정할 수 있습니다. 단점은 다른 개체를 만드는 것입니다. 빠른 변경을 많이하는 경우 GC가 할 일이 많아 성능에 영향을 미칠 수 있습니다. – MadProgrammer

    0

    OpenGL에서 pushMatrix()popMatrix()을 사용하여 변환 상태를 저장합니다. 여기에 그 등가물이 Graphics.create()Graphics.dispose()

    Graphics g1 = g.create(); 
    //do transformations 
    g1.dispose(); 
    
    Graphics g2 = g.create(); 
    //do other stuff 
    g2.dispose();