1

English is not my native language, sorry for any mistakes. I have to make a Bubble Shooter game in Java. I want to use images for the bubbles and I want the images to be picked randomly. I used Random and ImageIcon classes. My program doesn't show anything when I compile it and I don't know where the problem is. I'm a beginner in Java.

This is the code for my Game class:

import java.awt.Graphics;
import java.awt.Image;
import java.util.Vector;

import javax.swing.JPanel;

public class Game extends JPanel{
  private static final long serialVersionUID = 1L;

  //what the balls are like
  public final static int START_BALLS=40;
  public static Vector<Ball> balls = new Vector<Ball>();
  private Image img;
  private Graphics graphics;

  public Game() {
    for(int i=0; i<START_BALLS; i++) {
      balls.add(new Ball());
    }
  }

  public void paint(Graphics g) {
    img = createImage(null);
    graphics = img.getGraphics();
    paintComponent(graphics);
    g.drawImage(img, 0, 0, null);
    repaint();
  }

  public void paintComponet(Graphics g) {
    for(int i=0; i<balls.size(); i++) {
      Ball b=(Ball)balls.get(i);
      b.draw(g);
    }
  }

  public static void main(String [] args) {
    new Frame();
    Game game = new Game();
    new Game();
    Window.window.add(game);
  }
}

and the class for the bubbles:

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.Random;

import javax.swing.ImageIcon;

public class Ball {
  Random random = new Random();
  final String[] image_paths = new String[] {"balls/peg_0.png",
            "balls/peg_1.png","balls/peg_2.png","balls/peg_3.png",
            "balls/peg_4.png","balls/peg_5.png"};

  String randomBalls;
  public Image image;

  public Ball(){
    randomBalls = image_paths[random.nextInt(image_paths.length)];
    ImageIcon poza = new ImageIcon(randomBalls);
    image=poza.getImage();
  }

  public void draw(Graphics g){
    g.drawImage(image, 0, 0, null, null);
  }
}

What is wrong with my program?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
nicoleta
  • 13
  • 4
  • The code works if you just put the filename without the randomness? Because there is nothing obviously wrong with what you have here. – Tim B Jan 09 '14 at 16:23
  • The main method seems a bit weird to me too. Shouldn't be something like Frame frame = new Frame(); frame.add(game); ? Without creating two instances of Game class? – Jiri Kusa Jan 09 '14 at 16:39
  • can someone give me an example of the paint method,how it shoul look like?i know that is maybe a stupid question,but i don't know how to do it.thanks for all your answers – nicoleta Jan 09 '14 at 17:05
  • Those 'answers' are comments. See my [actual answer](http://stackoverflow.com/a/21026597/418556) that shows a working example. – Andrew Thompson Jan 09 '14 at 17:13

1 Answers1

1

Look over my comments, look carefully at the comments in the code, see how I rearranged the organization of the classes.

Game demo

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.imageio.ImageIO;
import java.net.URL;

public class Game extends JPanel {

    Random random = new Random();
    final String[] image_path = new String[]{
        "https://i.stack.imgur.com/gJmeJ.png",
        "https://i.stack.imgur.com/IHARa.png",
        "https://i.stack.imgur.com/wCF8S.png",
        "https://i.stack.imgur.com/T5uTa.png"
    };
    private static final long serialVersionUID = 1L;
    //what the balls are like
    public final static int START_BALLS = 40;
    public static Vector<Ball> balls = new Vector<Ball>();
    private Image img;
    // A Graphics instance is typically transient.
    // There is rarely, if ever, a need to store them
    //private Graphics graphics;

    public Game() {
        for (int i = 0; i < image_path.length; i++) {
            balls.add(new Ball(image_path[i]));
        }
        //I have no idea what you were trying to achieve here, but it fails horribly
        // img = createImage(null);
        img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        // graphics = img.getGraphics();
        ActionListener al = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        };
        Timer timer = new Timer(400, al);
        timer.start();
    }

    @Override  // very handy!
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        // g.drawImage(img, 0, 0, null);  A JPanel IS A ImageObserver
        g.drawImage(img, 0, 0, this);
        Ball b = (Ball) balls.get(random.nextInt(4));
        b.draw(g);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame("Game");
                f.add(new Game());
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See https://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

class Ball {

    String randomBalls;
    public Image image;

    public Ball(String url) {
        try {
            image = ImageIO.read(new URL(url));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void draw(Graphics g) {
        g.drawImage(image, 0, 0, null, null);
    }
}

Tips

  • Exception in thread "AWT-EventQueue-0" java.lang.UnsupportedOperationException: getGraphics() not valid for images created with createImage(producer) at img = createImage(null); I have no idea what you thought that code statement does, but ..nothing good.
  • When doing custom painting in a JPanel, we should override only paintComponent(Graphics) and leave the paint(Graphics) method as it is. When overriding the former, immediately call the super method.
  • Adding a call to repaint() inside paint(Graphics) will cause an infinite loop.. If the code needs to loop, establish a Swing Timer to call repaint()
  • paintComponet(Graphics g) should be paintComponent(Graphics g) Use @Override notation when appropriate. It would have warned you of the incorrectly spelled method name.

More general tips

  1. For better help sooner, post an MCVE.
  2. One way to get image(s) for an example is to hot-link to the images seen in this answer.
  3. By the time of deployment, those images will likely become an . That being the case, they must be accessed by URL instead of File. See the info page for the tag, for a way to form an URL.
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433