当你按下其中一个方向键时,我试图让球逐渐移动,现在它只是传送。我想要它,以便你可以看到它移动。基于这个example,我正在使用键绑定,并且有一个名为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();
}
});
}
}
答案 0 :(得分:7)
任何动画的基本前提都是随着时间的推移而改变。
您需要能够在给定时间段内将球从位置A移动到位置B.要做到这一点,你需要某种“自动收报机”,可以用来更新那段时间内球的位置。一般来说,25fps(或大约40毫秒)就足够了。
为了在Swing中安全地实现这一点,最简单的解决方案是使用Swing Timer
。你可以使用Thread
,但是你负责将更新同步回用户界面,而且在这个阶段真的需要更复杂的。
此示例使用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();
}
});
}
}
看看......
旁注
在你的paint方法中执行此ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50);
是非常低效的。可以快速连续多次调用paint
paint
。在任何可能的情况下,您希望{{1}}方法尽可能优化,在绘制方法中花费大量时间会使程序看起来很慢
答案 1 :(得分:2)
有很多方法可以执行代码,而且我不熟悉环境。 但基本上你使用击键来设定运动方向,然后你有另一个程序将球移向那个方向。一步一步移动多少像素,步长需要的是你的速度。
你如何使用键盘取决于游戏玩法。按住加速,向右按下左键停止。你想给它惯性吗?即从右到左减慢向右运动到零,然后开始向左。
各种选项,但诀窍是将球移动一个例程,然后使用输入设备控制方向,加速度等。