2017-12-04 6 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); 
    } 
} 

(XPOS、YPOS)されています。ここ

@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(); 

これは、基本的にはプレイヤーの位置にオブジェクトの位置を変換して、あなたは、また、1を適用することができ、オブジェクト

を中心オブジェクトを回転させますそのコンテキストのコピーを作成し、複合化される別の変換を適用します(translateを1つのコンテキストにコピーしてコピーしてからrotateコピーし、最初の変換はまだコピーに適用されます)

変形形状を生成する Path2Dを使用したプレイヤオブジェクトを翻訳して回転させるように Graphicsコンテキストと AffineTransformを使用して

この信じられないほど簡単な例2つの基本的な例を示しています...

  1. (それは、中心点だ程度)
  2. (この例では2つのオブジェクトを作成しますが、1つのAffineTransformを翻訳して回転して1回適用することができます)。どちらの場合も

、彼らは `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:気をつけなければ問題を引き起こす可能性のある 'Graphics'コンテキストには影響しません。 3:境界をチェックしたように、 'Graphics'文脈を必要とせずに変形された形状について決定することができます。欠点は、別のオブジェクトを作成していることです。多くの変更をすばやく行っている場合、これはパフォーマンスに影響する可能性があります。 – 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(); 
関連する問題