我想让球逐渐移动

当你按下其中一个方向键时,我试图让球逐渐移动,现在它只是传送。 我想要它,以便你可以看到它移动。 基于这个例子 ,我使用的是键绑定,并且有一个名为delta的变量会导致球移动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(); } }); } } 

任何动画的基本前提都是随着时间的推移而变化。

您需要能够在给定时间段内将球从位置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); tx += xDelta; ty += 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(); } }); } } 

看一眼 …

  • 如何使用Swing Timers
  • 时间框架
  • 三叉戟
  • 通用补间引擎

边注

做这个ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50); 在你的油漆方法是非常低效。 paint可以快速连续多次调用。 在任何可能的情况下,您都希望paint方法尽可能优化,在绘制方法中花费大量时间会使程序看起来很慢

有很多方法可以执行代码,而且我对环境不熟悉。 但基本上你使用击键设置运动方向,然后你有另一个例程,将球移向那个方向。 一步一步移动多少像素,步长需要多长时间就是你的速度。

如何使用键盘取决于游戏玩法。 按住加速,向右按下左键停止。 你想给它惯性吗? 即从右到左减慢向右运动到零然后开始向左。

各种选择,但诀窍是让球移动一个例程然后使用您的输入设备来控制方向,加速度等。

Interesting Posts