Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - How to Create a MultiThreaded Game using SwingWorker

I want to Create a [1 Player vs PC] Game with Threads.

we have 10*10 two Colors Shapes in our board like this :

enter image description here

when the Player clicks on BLUE Circles , Their color turns into Gray.

at the other side PC should turn all RED Rectangles into Gray.

the WINNER is who Clears all his/her own Shapes Earlier.


Code for The Player works fine but, My Problem is in Implementing The PC side of the Game, as i read in this article i should use SwingWorker to Implement Threading in GUI. it's my first time using SwingWorkers and i don't know how it should be to works properly.

Here is my Codes :

The Main Class

public class BubblePopGame {

public static final Color DEFAULT_COLOR1 = Color.BLUE;
public static final Color DEFAULT_COLOR2 = Color.RED;

public BubblePopGame() {
    List<ShapeItem> shapes = new ArrayList<ShapeItem>();

    int Total = 10;
    for (int i = 1; i <= Total; i++) {
        for (int j = 1; j <= Total; j++) {
            if ((i + j) % 2 == 0) {

                shapes.add(new ShapeItem(new Ellipse2D.Double(i * 25, j * 25, 20, 20),
                        DEFAULT_COLOR1));
            } else {
                shapes.add(new ShapeItem(new Rectangle2D.Double(i * 25, j * 25, 20, 20),
                        DEFAULT_COLOR2));
            }
        }
    }

    JFrame frame = new JFrame("Bubble Pop Quest!!");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ShapesPanel panel = new ShapesPanel(shapes);
    frame.add(panel);
    frame.setLocationByPlatform(true);
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new BubblePopGame();
        }
    });
}

}

Shape Item Class

public class ShapeItem {

private Shape shape;
private Color color;

public ShapeItem(Shape shape, Color color) {
    super();
    this.shape = shape;
    this.color = color;
}

public Shape getShape() {
    return shape;
}

public void setShape(Shape shape) {
    this.shape = shape;
}

public Color getColor() {
    return color;
}

public void setColor(Color color) {
    this.color = color;
}

}

ShapesPanel Class

public class ShapesPanel extends JPanel {

private List<ShapeItem> shapes;
private Random rand = new Random();
private SwingWorker<Boolean, Integer> worker;

public ShapesPanel(List<ShapeItem> shapesList) {
    this.shapes = shapesList;
    worker = new SwingWorker<Boolean, Integer>() {            

        @Override
        protected Boolean doInBackground() throws Exception {
            while (true) {
                Thread.sleep(200);
                int dim = rand.nextInt(300);
                publish(dim);                
                return true;
           }
        }

        @Override
        protected void done() {
            Boolean Status;
            try {                    
                Status = get();
                System.out.println(Status);
                super.done();                    //To change body of generated methods, choose Tools | Templates.
            } catch (InterruptedException ex) {
                Logger.getLogger(ShapesPanel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(ShapesPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        @Override
        protected void process(List<Integer> chunks) {
            int mostRecentValue = chunks.get(chunks.size()-1);
            System.out.println(mostRecentValue);
                Color color2 = Color.LIGHT_GRAY;
                ShapeItem tmpShape = shapes.get(mostRecentValue);
                if(tmpShape.getColor()==Color.RED){
                    tmpShape.setColor(color2);
                }
                repaint();                
       }

    };
    worker.execute ();

    addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            Color color1 = Color.LIGHT_GRAY;
            for (ShapeItem item : shapes) {
                if (item.getColor() == Color.BLUE) {
                    if (item.getShape().contains(e.getPoint())) {
                        item.setColor(color1);
                    }
                }
            }
            repaint();
        }
    });
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g.create();

    for (ShapeItem item : shapes) {
        g2.setColor(item.getColor());
        g2.fill(item.getShape());
    }

    g2.dispose();
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(300, 300);
}

private Color getRandomColor() {
    return new Color(rand.nextFloat(), rand.nextFloat(),
            rand.nextFloat());
}

}

like image 985
Mahdi Rashidi Avatar asked Oct 31 '14 16:10

Mahdi Rashidi


People also ask

How do you create a multithreaded program in Java?

We create a class that extends the java. This class overrides the run() method available in the Thread class. A thread begins its life inside run() method. We create an object of our new class and call start() method to start the execution of a thread. Start() invokes the run() method on the Thread object.

Is Java Swing multi threaded?

This means that most Swing components are, technically, not threadsafe for multithreaded applications. Now don't panic: it's not as bad as it sounds because there is a plan. All event processing in AWT/Swing is handled by a single system thread using a single system event queue. The queue serves two purposes.

How many threads can concurrently Java?

concurrent package is 16.


1 Answers

If I understood your code correctly, you are making a game where the human player has to click as fast as possible on all of his shapes while the PC is randomly clicking on shapes as well. The first one to clear all of his shapes win.

If that is correct, you probably want to adjust your SwingWorker to

  • loop until the game is finished. Currently your loop exit the first time the end of the loop is reached due to the return statement
  • Since you are not doing anything with the boolean return value of the SwingWorker, you might as well let it return void
  • No need to call get in the done method. The moment that method is called, the SwingWorker has finished. You only seem interested in the intermediate results
  • In the process method, you might want to loop over all values. Note that the process method is not called each time you publish something. The values you publish are grouped and passed in bulk to the process method when the EDT (Event Dispatch Thread) is available
like image 175
Robin Avatar answered Sep 17 '22 13:09

Robin