-1

I want to make the pacman open/close mouth animation using the easiest method. Here is my recent code: The problem is, nothing is happening?

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();  
   }

 }

and here is my draw panel:

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++;




   } 
 }  

  }

The while loop doesn't affect anything, what could be the reason for that?

user1767316
  • 3,276
  • 3
  • 37
  • 46
Scary Mary
  • 11
  • 1
  • 5
  • 1
    See [here](http://stackoverflow.com/questions/13999506/threads-with-key-bindings/14001011#14001011) for an example of how to use animations (creating images using `drawImage`), game loop etc. also dont override `paint(..)` rather use `JPanel` and override `paintComponent` – David Kroukamp Jan 20 '13 at 16:51
  • I am not sure the purpose of your project, but in Gaming this kind of animations are achieved with a technique called Blitting. It basically works with an image file (spritesheet) where you have all the sequences of the animation and you use a system to recalculate viewport for the image over time, creating the animation. Pretty much all game frameworks support. – Luis Jan 20 '13 at 16:55
  • *"open/close mouth animation for pacman"* Whatever works to make the graphics, I would suggest to stitch them into 4 animations (one for each direction), make those into GIF and use the animated GIFs at run-time. – Andrew Thompson Jan 21 '13 at 09:21
  • Don't understand these downvotes. Everyone need to know how to animate a Pacman. –  Jan 22 '13 at 16:25

3 Answers3

8

Something like this might work for PacMan images. It uses a Java 2D based Shape instance to represent the form, and an AffineTransform to produce the different orientations.

PacMan - Right PacMan - Down
PacMan - Up PacMan - Left

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();
    }
}

If you wanted to transform & render images at run-time, try starting with this series of PNG format images that uses partial transparency to soften the edges.

PacMan 1 PacMan 2 PacMan 3 PacMan 4

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    I didn't study this in detail before upvoting. I just dissolved in giggles on reading `chomp = false`. Can't really explain why. – Dawood ibn Kareem Oct 04 '13 at 02:03
  • @DavidWallace Glad I could bring some mirth to your day. :) The usual way I do that is through the *design* of the code (which is typically 'non existent'). ;) – Andrew Thompson Oct 04 '13 at 02:09
3

For the animation, you could use a Swing Timer to move the Pacman graphic as well as adjusting the angle by which the "mouth" opens, by varying the parameters used by fillArc.

Interaction with KeyEvents for movement control can be acheived using Key Bindings.

Also, I would move the paint functionality to a paintComponent method in a sub-classed JComponent for better paint performance.

Related: Painting with Swing


Edit:

As youre starting Java there are a number of tasks to get working first

  1. Create the JComponent based class with a static Pacman graphic. Move your painting logic to paintComponent
  2. Get the Swing Timer functionality working. Follow the Oracle guide for Timers.
  3. Implement the Key Bindings
  4. Other functionality such as score keeping, etc.
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • 1
    Probably no need for any `JPanel` specific functionality so I guess `JComponent` should be ok – Reimeus Jan 20 '13 at 16:54
  • thank you for all your answers. I am a beginner in programming -> java. Can you give me some clear example how to do this? – Scary Mary Jan 20 '13 at 18:38
  • 1
    @ScaryMary There are a number of steps which you will have to learn first. I have outlined these in my update. Do each task one at a time. Post new questions if you have any specific issues. Hope this helps. – Reimeus Jan 20 '13 at 21:44
2

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

Pseudocode:

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

To learn and do this sort of thing in Pygame would be easy compared to Java, but unsuitable for larger projects