2014-03-24 3 views
0

나는 아래쪽으로 게임을 만들고있어 원수가 화면을 가로 질러 원을 그리며 움직 이길 원합니다. 지금 그들은 화면의 두 가장자리 사이를 직선으로 움직입니다. 한 모서리에서 시작 위치를 생성 한 다음 화면의 어딘가에서 임의의 위치를 ​​찾고 이동 속도를 계산하면 속도 변수로 각도의 sin/cos을 곱합니다.Java에서 보간을 위해 두 점 사이의 호 만들기

이들을 포인트로 사용하여 이들 사이에 호를 생성하고이를 사용하여 내 적을 이동 시키려합니다. 어떤 종류의 스플라인이 속임수를 쓰는 것 같지만 Im을 만드는 방법을 완전히 모르거나, 내 캐릭터를 보간하기 위해 그것을 사용하는 방법을 더 중요하게 생각하지 않았습니다. 나는이 시점에서 프로그래밍보다는 수학 문제가 더 중요하다고 생각하지만 누군가가 어쨌든 도울 수 있기를 바랍니다. 감사.

+0

아무 것도 시도해 보지 않으셨습니까? – bjb568

답변

0

예, 스플라인이 적용됩니다. 특히 나는 큐빅 스플라인을 추천 할 것입니다. 왜냐하면 나중에 다른 모양을 원한다면, 아마도 스트리트 파이터 스타일 어퍼컷을 원한다면 같은 코드를 다시 사용할 수 있기 때문입니다. 나는 큐빅 스플라인이 괜찮은, 일반적인 해결책이라는 것을 기억합니다.

큐빅 스플라인을 해결할 때 나는 당신에게 맞는 의사 코드로 Google을 추천합니다. 이것은 비행 중에 적절한 입체 스플라인을 일반적으로 일반적으로 풀고 싶을 때만 가능합니다.

실제로, 원하는 모양이 거의 항상 같다고 상상해보십시오. 그렇다면 일반적으로 스플라인의 몇 가지 일반적인 경우를 해결하고이를 빠른 데이터 구조로 저장하여 성능을 향상시킬 수 있습니다. 예를 들어, y=x에 대해, 필요한 정보 (전처리 된)를 유지하는 적절한 어레이는 x[0] = 1,x[1] = 1,x[2] = 2 ... x[n] = n이 될 것이다.

실제로, 간단한 두 점 스플라인을 모델링하는 방정식을 생각해 볼 수 있습니다. 3 차 방정식에는 4 개의 미지수가 있습니다. 따라서 적어도 두 개의 데이터 요소가 있습니다. 시작 지점과 끝 지점입니다. 또한 점프 할 때 파생물을 계산할 수 있습니다. 네 번째 요점은 그가 점프하기를 원하는 다른 점이나 그가 착륙 할 때 파생 된 점을 사용할 수 있습니다. 그런 다음 https://www.wolframalpha.com/을 사용하여 방정식을 푸십시오. 또는 방정식을 사용하여 입방체를 푸십시오.

당신이 할 수있는 또 다른 일은 2 차 방정식 + 중력 + 바람 저항을 사용하여 호를 계산하는 것입니다. 다시 말하지만 Google은이를 해결하는 방법을 알고 있습니다. 이 페이지는 트릭을 수행 할 수있는 것처럼 빨리 발견 한 것입니다. http://www.physicsclassroom.com/class/vectors/Lesson-2/Non-Horizontally-Launched-Projectiles-Problem-Solv

0

스플라인을 사용하려는 경우 이미 Java에서 사용할 수있는 Path2D 클래스를 사용할 수 있습니다. 넌 선분

  • 그래서 차 곡선 세그먼트를 추가 차원 곡선

  • 를 첨부이 조립을 부가 특정 지점
  • 이동

    • 의해 임의의 경로를 조립할 수 경로는 쉬워야합니다. 화면 왼쪽 경계의 임의 지점에서 시작하여 화면 오른쪽 경계의 임의 지점에서 끝나는 2 차 곡선을 만들면됩니다. 제어점 (양쪽 끝)은 화면 중앙의 임의 위치에 점을 사용할 수 있습니다.

      (일반 : 경로를 일반 Path2D으로 표시 할 때 적을위한 경로를 디자인 할 때 상당히 자유롭게 생각할 수 있습니다. 원 또는 지그재그로 실행할 수 있으며, 네가 좋아하는 것처럼 ...)

      여기 더 까다로운 것은 원수를 에 따라 경로를 따르도록하는 것입니다.

      첫 번째 단계는 너무 까다 롭지 않습니다. PathIterator으로이 길을 걸을 수 있습니다. 그러나이 PathIterator은 단일 세그먼트, 즉 2 차 곡선 만 반환합니다. 이 문제는 플랫 화PathIterator을 만들어 완화 할 수 있습니다. 이렇게하면 모든 커브가 선분으로 변환됩니다 (해상도가 높을 수 있으므로 모서리를 알 수 없습니다).

      그러나 이제는 매우 까다로운 부분이 있습니다. 이러한 선분을 반복 할 때 이동 속도가 달라질 수 있습니다. 원본 이차 곡선의 곡률에 따라 생성되는 선분이 더 많거나 적을 수 있습니다. 최악의 경우, 3 개의 포인트가 모두 한 라인에있을 때, 오직 하나의 라인 세그먼트가 생성 될 것이고 적을 한 번에 전체 스크린으로 걸을 것입니다. 따라서이 경로가 일정한 속도로 통과하는지 확인해야합니다. 경로를 반복 할 때 얼마나 멀리 걷었는지 계산해야하며 가능하면 경로의 두 지점 사이의 위치를 ​​보간해야합니다.

      나는 예제를 빨리 만들었습니다. 확실히 방탄은 아니지만 출발점으로 사용할 수 있습니다.

      import java.awt.BorderLayout; 
      import java.awt.Color; 
      import java.awt.Graphics; 
      import java.awt.Graphics2D; 
      import java.awt.RenderingHints; 
      import java.awt.Shape; 
      import java.awt.event.ActionEvent; 
      import java.awt.event.ActionListener; 
      import java.awt.geom.Path2D; 
      import java.awt.geom.PathIterator; 
      import java.awt.geom.Point2D; 
      import java.util.ArrayList; 
      import java.util.List; 
      import java.util.Random; 
      
      import javax.swing.JButton; 
      import javax.swing.JComponent; 
      import javax.swing.JFrame; 
      import javax.swing.JPanel; 
      import javax.swing.SwingUtilities; 
      import javax.swing.Timer; 
      
      
      public class SplineMovementTest 
      { 
          public static void main(String[] args) 
          { 
           SwingUtilities.invokeLater(new Runnable() 
           { 
            @Override 
            public void run() 
            { 
             createAndShowGUI(); 
            } 
           }); 
          } 
      
          private static PathFollower pathFollower; 
      
          private static void createAndShowGUI() 
          { 
           JFrame frame = new JFrame(); 
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
           frame.getContentPane().setLayout(new BorderLayout()); 
      
           final Random random = new Random(0); 
      
           final SplineMovementPanel p = new SplineMovementPanel(); 
      
           JButton generateButton = new JButton("Generate"); 
           generateButton.addActionListener(new ActionListener() 
           { 
            @Override 
            public void actionPerformed(ActionEvent e) 
            { 
             Shape spline = generateSpline(p, 
              random.nextDouble(), 
              random.nextDouble(), 
              random.nextDouble()); 
             p.setSpline(spline); 
             pathFollower = new PathFollower(spline); 
             p.repaint(); 
            } 
           }); 
           frame.getContentPane().add(generateButton, BorderLayout.NORTH); 
           startAnimation(p); 
      
           frame.getContentPane().add(p, BorderLayout.CENTER); 
           frame.setSize(800, 800); 
           frame.setLocationRelativeTo(null); 
           frame.setVisible(true); 
          } 
      
          private static Shape generateSpline(
           JComponent c, double yLeft, double yCenter, double yRight) 
          { 
           Path2D spline = new Path2D.Double(); 
           double x0 = 0; 
           double y0 = yLeft * c.getHeight(); 
           double x1 = c.getWidth()/2; 
           double y1 = yCenter * c.getHeight(); 
           double x2 = c.getWidth(); 
           double y2 = yRight * c.getHeight(); 
           spline.moveTo(x0, y0); 
           spline.curveTo(x1, y1, x1, y1, x2, y2); 
           return spline; 
          } 
      
          private static void startAnimation(final SplineMovementPanel p) 
          { 
           Timer timer = new Timer(20, new ActionListener() 
           { 
            double position = 0.0; 
      
            @Override 
            public void actionPerformed(ActionEvent e) 
            { 
             position += 0.005; 
             position %= 1.0; 
             if (pathFollower != null) 
             { 
              Point2D point = pathFollower.computePointAt(
               position * pathFollower.getPathLength()); 
              p.setObjectLocation(point); 
             } 
            } 
           }); 
           timer.start(); 
          } 
      } 
      
      class PathFollower 
      { 
          private final List<Point2D> points; 
          private final double pathLength; 
      
          PathFollower(Shape spline) 
          { 
           points = createPointList(spline); 
           pathLength = computeLength(points); 
          } 
      
          public double getPathLength() 
          { 
           return pathLength; 
          } 
      
          Point2D computePointAt(double length) 
          { 
           if (length < 0) 
           { 
            Point2D p = points.get(0); 
            return new Point2D.Double(p.getX(), p.getY()); 
           } 
           if (length > pathLength) 
           { 
            Point2D p = points.get(points.size()-1); 
            return new Point2D.Double(p.getX(), p.getY()); 
           } 
           double currentLength = 0; 
           for (int i=0; i<points.size()-1; i++) 
           { 
            Point2D p0 = points.get(i); 
            Point2D p1 = points.get(i+1); 
            double distance = p0.distance(p1); 
            double nextLength = currentLength + distance; 
            if (nextLength > length) 
            { 
             double rel = 1 - (nextLength - length)/distance; 
             double x0 = p0.getX(); 
             double y0 = p0.getY(); 
             double dx = p1.getX() - p0.getX(); 
             double dy = p1.getY() - p0.getY(); 
             double x = x0 + rel * dx; 
             double y = y0 + rel * dy; 
             return new Point2D.Double(x,y); 
            } 
            currentLength = nextLength; 
           } 
           Point2D p = points.get(points.size()-1); 
           return new Point2D.Double(p.getX(), p.getY()); 
          } 
      
          private static double computeLength(List<Point2D> points) 
          { 
           double length = 0; 
           for (int i=0; i<points.size()-1; i++) 
           { 
            Point2D p0 = points.get(i); 
            Point2D p1 = points.get(i+1); 
            length += p0.distance(p1); 
           } 
           return length; 
          } 
      
          private static List<Point2D> createPointList(Shape shape) 
          { 
           List<Point2D> points = new ArrayList<Point2D>(); 
           PathIterator pi = shape.getPathIterator(null, 0.1); 
           double coords[] = new double[6]; 
           while (!pi.isDone()) 
           { 
            int s = pi.currentSegment(coords); 
            switch (s) 
            { 
             case PathIterator.SEG_MOVETO: 
              points.add(new Point2D.Double(coords[0], coords[1])); 
      
             case PathIterator.SEG_LINETO: 
              points.add(new Point2D.Double(coords[0], coords[1])); 
            } 
            pi.next(); 
           } 
           return points; 
          } 
      
      } 
      
      
      class SplineMovementPanel extends JPanel 
      { 
          void setSpline(Shape shape) 
          { 
           this.spline = shape; 
          } 
      
          void setObjectLocation(Point2D objectLocation) 
          { 
           this.objectLocation = objectLocation; 
           repaint(); 
          } 
          private Shape spline = null; 
          private Point2D objectLocation = null; 
      
      
          @Override 
          protected void paintComponent(Graphics gr) 
          { 
           super.paintComponent(gr); 
           Graphics2D g = (Graphics2D)gr; 
           g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON); 
      
           if (spline != null) 
           { 
            g.setColor(Color.BLACK); 
            g.draw(spline); 
           } 
      
           if (objectLocation != null) 
           { 
            g.setColor(Color.RED); 
            int x = (int)objectLocation.getX()-15; 
            int y = (int)objectLocation.getY()-15; 
            g.fillOval(x, y, 30, 30); 
           } 
          } 
      
      
      }