2013-02-25 46 views
3

我試圖讓一個球,當你按下一個箭頭鍵逐漸移向,現在它那種只是瞬間移動。我希望它能讓你看到它移動。在此基礎上example,我使用的鍵綁定,並且存在會由50個像素的球移動變量叫做增量,但就像我說皮球稍稍出現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 2013-02-26 00:04:24

回答

2

很多方法來做代碼,我不熟悉環境。 但基本上你使用擊鍵來設置運動的方向,然後你有另一個例程來移動球的方向。一步移動多少個像素,步驟需要多長時間纔是您的速度。

您如何使用鍵盤是下到遊戲。按住加速按鈕,向右按時停止按鈕。你想給它慣性嗎?即從右到左慢動作到右邊爲零然後開始向左。

有各種各樣的選擇,但訣竅是讓移動球一個例程,然後用你的輸入設備來控制方向,加速度等

6

任何動畫的基本前提是隨着時間的變化。

你需要能夠從位置A球在給定的時間內移動到位置B。要做到這一點,你需要某種「代幣」,可以用來更新那段時間內球的位置。一般來說,25fps(或大約40毫秒)就足夠了。

要在Swing安全做到這一點,最簡單的解決方法是使用一個Swing Timer。您可以使用Thread,但是隨後您需要負責將更新同步回UI,並且在此階段確實需要更多的複雜性。

本例中使用1秒的時間把球從A點移動到B點。這是一個線性的動畫,你會需要調查一個適當的動畫框架,以獲得更復雜的解決方案。

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方法儘可能優化,因爲在繪製方法上花費了很多時間會讓你的程序看起來很慢

+0

對於'javax.swing.Timer',+1;鏈接到原來添加到問題。 – trashgod 2013-02-26 10:15:57