吃豆子打开/关闭嘴动画

我想用最简单的方法制作pacman开/关嘴动画。 这是我最近的代码:问题是,什么都没发生?

package ordner; import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class PacMan implements ActionListener { private JFrame frame; private DrawPanel panel; private void initGui() { frame = new JFrame("Pacman"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); panel = new DrawPanel(); frame.add(panel); panel.setBackground(Color.BLACK); frame.setSize(300, 300); frame.setVisible(true); } public static void main(String[] args) { PacMan pm = new PacMan(); pm.initGui(); } @Override public void actionPerformed(ActionEvent e) { panel.repaint(); } } 

这是我的绘图板:

 import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; public class DrawPanel extends JPanel { @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.yellow); g.fillArc(70,50,150,150,30,300); int i = 0; while ( i <= 60) { g.fillArc(70,50,150,150,30-i,300+i+i); try { Thread.sleep(25); } catch (Exception e) { Thread.currentThread().interrupt(); } i++; } } } 

while循环不影响任何东西,可能是什么原因?

像这样的东西可能适用于PacMan图像。 它使用基于Java 2D的Shape实例来表示forms,使用AffineTransform来生成不同的方向。

吃豆人 - 对吃豆人 - 下来
吃豆人 - 起来吃豆人 - 左

 import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.BufferedImage; import javax.swing.*; import java.io.*; import javax.imageio.ImageIO; class PacManShape { private double size; private double rotation; final int maxSize = 4; static File home = new File(System.getProperty("user.home")); static File images = new File(home, "images"); PacManShape(int size, double rotation) { this.size = size; this.rotation = rotation; } public Area getPacManShape(double jaws) { Area area = new Area(new Ellipse2D.Double(0d, 0d, size, size)); double x1 = size / 2 + (2d * size * Math.cos(jaws / 2d)); double y1 = size / 2 + (2d * size * Math.sin(jaws / 2d)); double x2 = x1; double y2 = size / 2 - (2d * size * Math.sin(jaws / 2d)); Polygon mouth = new Polygon(); mouth.addPoint((int) (size / 2), (int) (size / 2)); mouth.addPoint((int) x1, (int) y1); mouth.addPoint((int) x2, (int) y2); mouth.addPoint((int) (size / 2), (int) (size / 2)); area.subtract(new Area(mouth)); return area; } public BufferedImage getPacManImage(double angle, Color color) { BufferedImage bi = new BufferedImage( (int) size, (int) size, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = bi.createGraphics(); g2.setColor(color); g2.fillRect(0, 0, (int) size, (int) size); AffineTransform rotate = AffineTransform.getRotateInstance( rotation, size / 2, size / 2); g2.setTransform(rotate); Area pacMan = getPacManShape(angle); g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.YELLOW); float[] dist = {.15f, .9f}; Color[] colors = {Color.YELLOW, Color.ORANGE}; Point2D center = new Point2D.Double(size / 2, size / 2); RadialGradientPaint radial = new RadialGradientPaint( center, (float) ((size / 2) - 2f), dist, colors); g2.setPaint(radial); g2.fill(pacMan); GradientPaint gradient = new GradientPaint( 0, 0, new Color(255, 255, 225, 220), (int) (size / 3), 0, new Color(255, 255, 255, 0)); g2.setPaint(gradient); g2.fill(pacMan); g2.dispose(); return bi; } public void savePacManImage(int q, int num) throws IOException { double angle = Math.PI*2 / 3d * ((double) num / (double) maxSize); BufferedImage bi = getPacManImage(angle, Color.WHITE); images.mkdirs(); File img = new File(images, "PacMan-" + q + "x" + num + ".gif"); ImageIO.write(bi, "gif", img); } public static void main(String[] args) { try { for (int ii = 0; ii < 4; ii++) { PacManShape pms = new PacManShape(100, (double) ii * Math.PI / 2d); for (int jj = 0; jj <= pms.maxSize; jj++) { pms.savePacManImage(ii, jj); } } Desktop.getDesktop().open(images); } catch (IOException ex) { ex.printStackTrace(); } Runnable r = new Runnable() { @Override public void run() { JPanel gui = new JPanel(new BorderLayout()); gui.add(new PacManComponent()); JOptionPane.showMessageDialog(null, gui); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } } class PacManComponent extends JPanel { double angle = 0d; int preferredSize = 100; double diff = Math.PI / 8; boolean chomp = true; Timer timer; PacManComponent() { ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { repaint(); } }; timer = new Timer(180, listener); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(preferredSize, preferredSize); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); //double size = (getWidth() < getHeight() ? getWidth() : getHeight()); if (angle > 2 * Math.PI / 3) { chomp = true; } else if (angle < 0.01) { chomp = false; } if (chomp) { angle -= diff; } else { angle += diff; } PacManShape pms = new PacManShape(100, 0d); Image image = pms.getPacManImage(angle, new Color(0, 0, 0, 0)); g2.drawImage(image, 0, 0, this); g2.dispose(); } } 

如果您想在运行时转换和渲染图像,请尝试从使用部分透明度来柔化边缘的这一系列PNG格式图像开始。

吃豆人1吃豆子2吃豆子3吃豆子4

对于动画,您可以使用Swing Timer来移动Pacman图形,以及通过改变fillArc使用的参数来调整“嘴”打开的角度。

可以使用键绑定实现与KeyEvents交互以进行移动控制。

此外,我会将paintfunction移动到子类JComponentpaintComponent方法,以获得更好的绘制性能。

相关: 用Swing绘画


编辑:

当您启动Java时,首先要完成许多任务

  1. 使用静态Pacman图形创建基于JComponent的类。 将绘制逻辑移动到paintComponent
  2. 获取Swing Timerfunction。 遵循Oracle指南针指南 。
  3. 实现Key Bindings
  4. 其他function,如得分保持等。

2d动画: http : //en.wikipedia.org/wiki/File : The_Horse_in_Motion.jpg

伪代码:

 while programActive: deltatime = get_time_since_last_call() update_animation_frame(deltatime) image = get_animation_frame() draw_background() draw(image) enforce_framerate(24) 

与Java相比,在Pygame中学习和做这种事情会很容易,但不适合大型项目