2013-02-25 4 views
3

나는 화살표 키 중 하나를 누르면 점차적으로 공을 만들기 위해 노력하고 있는데, 지금은 그냥 텔레포트의 종류이다. 나는 그것이 당신이 움직이는 것을 볼 수 있도록 그것을 원한다. 이 example을 기반으로, 키 바인딩을 사용하고 있으며 공을 50 픽셀 씩 이동시키는 delta라는 변수가 있지만 화살표 키 중 어느 방향 으로든 공이 50 픽셀 만 나오는 것처럼 나는 그것을 원합니다. 당신이 공을 걷어차는 것처럼 당신은 그것이 a 지점에서 b 지점으로가는 것을 볼 수 있습니다. 문제가 있다고 생각되는 89 행으로 이동하십시오.나는 점차적으로 공을 만들려고 노력하고있다.

package game; 

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
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.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

/** 
* @see https://stackoverflow.com/questions/6991648 
* @see https://stackoverflow.com/questions/6887296 
* @see https://stackoverflow.com/questions/5797965 
*/ 
public class LinePanel extends JPanel { 
myObject ball; 

private Point b1 = new Point(0,0); 


private MouseHandler mouseHandler = new MouseHandler(); 
private Point p1 = new Point(100, 100); 
private Point p2 = new Point(540, 380); 
private boolean drawing; 

public LinePanel() { 
    this.setPreferredSize(new Dimension(640, 480)); 
    this.addMouseListener(mouseHandler); 
    this.addMouseMotionListener(mouseHandler); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.setColor(Color.blue); 
    g2d.setRenderingHint(
     RenderingHints.KEY_ANTIALIASING, 
     RenderingHints.VALUE_ANTIALIAS_ON); 
    g2d.setStroke(new BasicStroke(8, 
     BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); 
    g.drawLine(p1.x, p1.y, p2.x, p2.y); 
    ball = new myObject(b1.x,b1.y,"Stuff/ball.png",50,50); 
    g.drawImage(ball.getImage(),ball.getX(),ball.getY(), ball.getWidth(),   ball.getHeight(), null); 
    repaint(); 
} 

private class MouseHandler extends MouseAdapter { 

    @Override 
    public void mousePressed(MouseEvent e) { 
     drawing = true; 
     p1 = e.getPoint(); 
     p2 = p1; 
     repaint(); 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     drawing = false; 
     p2 = e.getPoint(); 
     repaint(); 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (drawing) { 
      p2 = e.getPoint(); 
      repaint(); 
     } 
    } 
} 

private class ControlPanel extends JPanel { 

    private static final int DELTA = 50; 
// above is telling the ball to move by 50 pixels 
    // I want it to move by 50 pixels but gradually I dont want it to teleport 
    public ControlPanel() { 
     this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0)); 
     this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA)); 
     this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0)); 
     this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA)); 


    } 


    private class MoveButton extends JButton { 

     KeyStroke k; 
     int myX, myY; 

     public MoveButton(String name, int code, final int myX, final int myY) { 
      super(name); 
      this.k = KeyStroke.getKeyStroke(code, 0); 
      this.myX = myX; 
      this.myY = myY; 
      this.setAction(new AbstractAction(this.getText()) { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        LinePanel.this.b1.translate(myX, myY); 

        LinePanel.this.repaint(); 
       } 
      }); 
      ControlPanel.this.getInputMap(
       WHEN_IN_FOCUSED_WINDOW).put(k, k.toString()); 
      ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        MoveButton.this.doClick(); 
       } 
      }); 
     } 
    } 
} 



private void display() { 
    JFrame f = new JFrame("LinePanel"); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.add(this); 
    f.add(new ControlPanel(), BorderLayout.SOUTH); 
    f.pack(); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
} 

public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      new LinePanel().display(); 
     } 
    }); 
} 


} 
+4

각 키 동작에 대해 'javax.swing.Timer' [여기] (http://stackoverflow.com/q/9849950/230513)와 같이 중간 거리를 이동합니다. – trashgod

답변

2

코드를 작성하는 방법이 많고 환경에 익숙하지 않습니다. 하지만 기본적으로 키 스트로크를 사용하여 이동 방향을 설정 한 다음 그 방향으로 공을 움직이는 또 다른 루틴을 사용합니다. 얼마나 많은 픽셀을 한 단계로 이동하면 얼마나 걸리는지 당신의 속도가됩니다.

키보드 사용 방법은 게임 플레이에 달려 있습니다. 누르고 있으면 가속이되고 오른쪽으로 가면 왼쪽으로 멈 춥니 다. 관성을주고 싶니? 즉 오른쪽에서 왼쪽으로 이동하면 오른쪽으로 이동하여 0으로 이동 한 다음 왼쪽으로 이동하기 시작합니다.

모든 옵션의 종류 그러나 트릭은 방향, 가속도 등

6

어떤 애니메이션의 기본 전제는 시간이 지남에 따라 변화를 제어하기 위해 입력 장치를 사용하여 다음 공 하나 루틴을 이동하고있다.

주어진 시간 동안 위치 A에서 위치 B로 공을 이동할 수 있어야합니다. 그렇게하기 위해서는 그 기간 동안 공의 위치를 ​​업데이트하는 데 사용할 수있는 일종의 "시세 표시기"가 필요합니다. 일반적으로 25fps (또는 약 40 밀리 초)가 충분합니다.

Swing에서이를 안전하게 수행하려면 가장 쉬운 방법은 Swing Timer을 사용하는 것입니다. Thread을 사용할 수 있지만 업데이트를 UI에 다시 동기화해야 할 책임이 있으며 더 복잡한 경우이 단계에서 실제로 필요합니다.

이 예제에서는 점 A에서 점 B로 공을 이동하는 데 1 초의 시간을 사용합니다. 이것은 선형 애니메이션이므로 더 복잡한 솔루션을 얻으려면 적절한 애니메이션 프레임 워크를 조사해야합니다.

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
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.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.Timer; 

public class LinePanel extends JPanel { 

// myObject ball; 
    private Point b1 = new Point(0, 0); 
    private Point startPoint = new Point(0, 0); 
    private Point targetPoint = new Point(0, 0); 
    private MouseHandler mouseHandler = new MouseHandler(); 
    private Point p1 = new Point(100, 100); 
    private Point p2 = new Point(540, 380); 
    private boolean drawing; 

    private Timer animate; 
    private long startTime; 
    private int duration = 1000; 

    public LinePanel() { 
     this.setPreferredSize(new Dimension(640, 480)); 
     this.addMouseListener(mouseHandler); 
     this.addMouseMotionListener(mouseHandler); 
     animate = new Timer(40, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       long now = System.currentTimeMillis(); 
       long dif = now - startTime; 
       if (dif >= duration) { 
        dif = duration; 
        ((Timer)e.getSource()).stop(); 
       } 
       float progress = (float)dif/(float)duration; 
       b1 = calculateProgress(startPoint, targetPoint, progress); 
       repaint(); 
      } 
     }); 
     animate.setRepeats(true); 
     animate.setCoalesce(true); 
    } 

    public void moveBallTo(Point target) { 

     if (animate.isRunning()) { 
      animate.stop(); 
     } 

     startPoint = b1; 
     targetPoint = target; 

     startTime = System.currentTimeMillis(); 
     animate.start(); 

    } 

    public void moveBallBy(int xDelta, int yDelta) { 

     animate.stop(); 

     Point t = new Point(targetPoint == null ? b1 : targetPoint); 
     t.x += xDelta; 
     t.y += yDelta; 

     moveBallTo(t); 

    } 

    public Point calculateProgress(Point startPoint, Point targetPoint, double progress) { 

     Point point = new Point(); 

     if (startPoint != null && targetPoint != null) { 

      point.x = calculateProgress(startPoint.x, targetPoint.x, progress); 
      point.y = calculateProgress(startPoint.y, targetPoint.y, progress); 

     } 

     return point; 

    } 

    public int calculateProgress(int startValue, int endValue, double fraction) { 

     int value = 0; 
     int distance = endValue - startValue; 
     value = (int)Math.round((double)distance * fraction); 
     value += startValue; 

     return value; 

    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setColor(Color.blue); 
     g2d.setRenderingHint(
       RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 
     g2d.setStroke(new BasicStroke(8, 
       BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); 
     g.drawLine(p1.x, p1.y, p2.x, p2.y); 

     g.setColor(Color.RED); 
     g.drawOval(b1.x - 4, b1.y - 4, 8, 8); 
//  ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50); 
//  g.drawImage(ball.getImage(), ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight(), null); 
     repaint(); 
    } 

    private class MouseHandler extends MouseAdapter { 

     @Override 
     public void mousePressed(MouseEvent e) { 
      drawing = true; 
      p1 = e.getPoint(); 
      p2 = p1; 
      repaint(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      drawing = false; 
      p2 = e.getPoint(); 
      repaint(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      if (drawing) { 
       p2 = e.getPoint(); 
       repaint(); 
      } 
     } 
    } 

    private class ControlPanel extends JPanel { 

     private static final int DELTA = 50; 
// above is telling the ball to move by 50 pixels 
     // I want it to move by 50 pixels but gradually I dont want it to teleport 

     public ControlPanel() { 
      this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0)); 
      this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA)); 
      this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0)); 
      this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA)); 


     } 

     private class MoveButton extends JButton { 

      KeyStroke k; 
      int myX, myY; 

      public MoveButton(String name, int code, final int myX, final int myY) { 
       super(name); 
       this.k = KeyStroke.getKeyStroke(code, 0); 
       this.myX = myX; 
       this.myY = myY; 
       this.setAction(new AbstractAction(this.getText()) { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
//      LinePanel.this.b1.translate(myX, myY); 
         moveBallBy(myX, myY); 
         LinePanel.this.repaint(); 
        } 
       }); 
       ControlPanel.this.getInputMap(
         WHEN_IN_FOCUSED_WINDOW).put(k, k.toString()); 
       ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         MoveButton.this.doClick(); 
        } 
       }); 
      } 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("LinePanel"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.add(new ControlPanel(), BorderLayout.SOUTH); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new LinePanel().display(); 
      } 
     }); 
    } 
} 

한 번 봐 ...

옆면 참고

당신이 페인트 방법에 ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50);하는 것은 매우 비효율적입니다. paint은 여러 번 빠르게 호출 될 수 있습니다. 가능하다면 paint 메소드를 최대한 만들 수 있기를 원한다. 페인트 메소드에 많은 시간을 소비하면 프로그램이 느려질 것이다.

+0

+1에 대해 'javax.swing.Timer'; 원본에 대한 링크가 질문에 추가되었습니다. – trashgod

관련 문제