这是我为创建pacman而编写的程序。我现在希望吃豆子从一个随机的起点到一个随机的目标点直线移动。 你能建议怎么做。
import javax.swing.JFrame;
/**
* Main class for pacman example. All it does is create a frame and put
* the pacman panel in it.
*/
public class PacmanGUI extends JFrame{
private Pacman pc;
public PacmanGUI(){
super("Pacman");
pc = new Pacman();
this.getContentPane().add(pc);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new PacmanGUI();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* Pacman class that extends JPanel and paints a pacman animation.
* It uses Timers and Actionlistener to do the Animation.
*
*/
public class Pacman extends JPanel implements ActionListener{
private int figureSize = 50;
private static final int DELAY = 200;
private double mouthOpenPercentages[] = {.1,.5};
private Timer animationTimer;
private int mouthState = 0;
private Point pacManPosition;
/**
* No args constructor that starts the animation.
*/
public Pacman(){
startAnimation();
}
/**
* Overriden paintComponent method that paints pacman.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
pacManPosition = new Point(this.getWidth()/2 - figureSize/2,
this.getHeight()/2 - figureSize/2);
g.fillRect(0,0,this.getWidth(), this.getHeight());
drawPacMan(g);
mouthState = (++mouthState) % mouthOpenPercentages.length;
}
/**
* Stops the animation by stopping the animation timer.
*/
public void stopAnimation(){ animationTimer.stop(); }
/**
* Method do deal with actionevents that are triggered. In this
* case we only have actionevents being triggered from our timer
* and by the more usual case of a button click.
*/
public void actionPerformed(ActionEvent e){ repaint(); }
/**
* Gets the size that this component would like to be.
*/
public Dimension getPreferredSize(){ return new Dimension(400,400); }
/**
* Gets the minimum size for this component.
*/
public Dimension getMinimumSize(){ return new Dimension(200,200); }
/**
* Starts the animation by setting a timer. When this timer goes
* off the actionPerformed method will be triggered, which in
* turn triggers the painting.
*/
private void startAnimation(){
if (animationTimer == null){
mouthState = 0;
animationTimer = new Timer(DELAY, this);
animationTimer.start();
} else { //continue animating..
if (!animationTimer.isRunning())
animationTimer.restart();
}
}
/**
* Draws our little pacman on the given graphics canvas.
* @param g
*/
private void drawPacMan(Graphics g){
Color c = g.getColor();
g.setColor(Color.yellow);
g.fillOval(pacManPosition.x, pacManPosition.y, figureSize, figureSize);
//Change color back to original and draw pacman's mouth
g.setColor(c);
//calculate mouth offsets
int yOffset = (int)((figureSize/2)*mouthOpenPercentages[mouthState]);
//draw the mouth cutout.
int x[] = {pacManPosition.x + figureSize/2, pacManPosition.x + figureSize, pacManPosition.x + figureSize};
int y[] = {pacManPosition.y + figureSize/2,
pacManPosition.y + figureSize/2 + yOffset,
pacManPosition.y + figureSize/2 - yOffset};
g.fillPolygon(x, y, x.length);
}
}
答案 0 :(得分:1)
您必须同时管理两个动画。
第一个,你已经编码,打开和关闭吃豆子的嘴。
第二个动画负责将吃豆子从一个地方移动到另一个地方。
我建议你创建一个Sprite类。 Sprite类负责保持精灵的当前位置,精灵的下一个位置以及精灵移动的速度。
你会扩展Sprite以获得一个Pacman类,以及一个包含4个实例的Chaser类。
Pacman班负责口腔动画。
追逐者类将负责决定是否追捕吃豆子,或逃离吃豆子。
除非覆盖一个或多个组件类,否则不应扩展Java Swing组件。你应该使用Swing组件。
您应该始终在事件调度线程(EDT)上启动Swing GUI。您可以通过执行SwingUtilities的invokeLater方法来完成此操作。
您应该拥有一个与GUI组件分开的GUI模型。我定义的三个类将是GUI模型的一部分。你还需要摆出一个迷宫。
祝你的项目好运。
答案 1 :(得分:1)
在Pacman
类中,您需要再创建2个值来存储起点和终点。您已经声明了private Point pacManPosition;
,因此我也将其声明为Point
。您最初要将pacManPosition
设置为起点。
Point start = // random start point
Point end = // random end point
Point pacManPoint = new Point(start);
现在你要确定你希望Pacman移动的速度,比方说每帧2个像素。
int speed = 2;
为了确定每帧移动吃豆子的数量,我们需要做一些计算。首先,获取线的距离 -
double distance = Math.sqrt(Math.pow(end.x - start.x, 2) +
Math.pow(end.y - start.y, 2));
然后我们计算以我们想要的速度走这段距离需要多少帧。
int totalFrames= (int)Math.round(distance / speed);
添加一个帧计数器 -
int frame = 0;
现在,查看您的paintComponent
方法。现在,每次绘制时,您都会将pacManPosition
设置为同一点(面板的中心)。你想在这里做的是每帧更新pacManPosition
,直到它到达结束位置。你在paintComponent
做了类似的事情,你每次都要更新mouthState
以获得动画效果。对于动画位置,它看起来像 -
if (frame < totalFrames) {
pacManPosition.x = start.x + frame * (end.x - start.x) / totalFrames;
pacManPosition.y = start.y + frame * (end.y - start.y) / totalFrames;
frame++;
}
这只是进行动画动画的一种方式,它假设了几个方面 - 速度恒定,无需避开障碍物,无需玩家控制。 totalFrames中的计算并不精确 - 它将pacMan移动到接近终点,但不能保证它会在那里完全结束。它还与帧速率有关,这有缺点。根据具体情况,还有很多其他方法可以做到这一点。