Question

I'm trying to make a game like bejeweled or candycrush for homework. It's almost over. but I have a little problem. Now, when I clicked, buttons that have the same icon are popping up and the above pictures are coming instead of exploding. but it's going too fast. How can I slow this event? Or can I add effects?

public class ButtonActionListener implements ActionListener {
public JButton previousButton = null;
public int numP, numC;
public JButton[] buttons=butondeneme.getButton();

@Override
public void actionPerformed(ActionEvent e){


    // TODO Auto-generated method stub
    JButton currentButton = (JButton)e.getSource();

    if (previousButton == null) {
        previousButton = currentButton;
        return;
    }

    int numP=Integer.parseInt(((JButton)previousButton).getActionCommand());
    int numC=Integer.parseInt(((JButton)currentButton).getActionCommand());

    //change picture of icons that clicked
    if (numP==(numC+1) || numP==(numC-1) || numP==(numC+8) || numP==(numC-8) ){
        Icon previousIcon = previousButton.getIcon();
        Icon currentIcon = currentButton.getIcon();
        currentButton.setIcon(previousIcon);
        previousButton.setIcon(currentIcon);
        previousButton = null;

    }
    else
        previousButton=null;

    Random r = new Random();
    int a = r.nextInt(64);
    int b = r.nextInt(64);
    int c = r.nextInt(64);

    //buttons that have same picture are explode.
    for(int i=0; i<63; i++){
        if(buttons[i].getIcon().toString()==buttons[i+1].getIcon().toString() && 
                buttons[i+1].getIcon().toString()== buttons[i+2].getIcon().toString() ){                                            
            //System.out.println("slm");
            if(i > 7){
                buttons[i].setIcon(buttons[i-8].getIcon());
                buttons[i+1].setIcon(buttons[i-7].getIcon());
                buttons[i+2].setIcon(buttons[i-6].getIcon());

                for(int j = i; j > 0; j=j-8){
                    if(j > 7){
                        buttons[j].setIcon(buttons[j-8].getIcon());
                        buttons[j+1].setIcon(buttons[j-7].getIcon());
                        buttons[j+2].setIcon(buttons[j-6].getIcon());
                    }
                    else{
                        buttons[j].setIcon(buttons[a].getIcon());
                        buttons[j+1].setIcon(buttons[b].getIcon());
                        buttons[j+2].setIcon(buttons[c].getIcon());
                    }

                }
            }
            else{
                buttons[i].setIcon(buttons[a].getIcon());
                buttons[i+1].setIcon(buttons[b].getIcon());
                buttons[i+2].setIcon(buttons[c].getIcon());
            }
        }
    }

}

}    

In this class, I created frame, buttons and random icon.

public class butondeneme extends JFrame{

private JPanel grid;
public String comand;
public static JButton[] buttons;
public String imgName;

public butondeneme(){

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 640, 640);
grid=new JPanel();
grid.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
grid.setLayout(new GridLayout(8,8,5,5));    
buttons = new JButton[64];


   //Creating random image for buttons
   ActionListener buttonActionListener = new ButtonActionListener();
     for (int i = 0; i<buttons.length; i++) {

            Random r = new Random();
            int a = r.nextInt(9)+1;
            switch(a){
            case 1 : buttons[i]=new JButton(new ImageIcon("img//Cakal.png"));
                    break;
            case 2 : buttons[i]=new JButton(new ImageIcon("img//BugsBunny.png"));
                    break;
            case 3 : buttons[i]=new JButton(new ImageIcon("img//Pig.png"));
                    break;
            case 4 : buttons[i]=new JButton(new ImageIcon("img//Taz.png"));
                    break;
            case 5 : buttons[i]=new JButton(new ImageIcon("img//Sam.png"));
                    break;
            case 6 : buttons[i]=new JButton(new ImageIcon("img//DuffyDuck.png"));
                    break;
            case 7 : buttons[i]=new JButton(new ImageIcon("img//Tweety.png"));
                    break;
            case 8 : buttons[i]=new JButton(new ImageIcon("img//Slyvester.png"));
                    break;
            case 9 : buttons[i]=new JButton(new ImageIcon("img//RoadRunner.png"));
                    break;
            }

            //Adding number to find easily
            comand=Integer.toString(i);

            //Get ImageIcon name
            imgName=((ImageIcon)buttons[i].getIcon()).toString();

            buttons[i].addActionListener(buttonActionListener);
            buttons[i].setActionCommand(comand);

            grid.add(buttons[i]);

      }


add(grid);


}

static JButton[] getButton(){
return buttons;
}

public static void main(String[] args){
    butondeneme erdem=new butondeneme();
    erdem.setVisible(true);
}

}

Was it helpful?

Solution

When you want to add a delay to such an "animation", then you have to use Thread.sleep(ms).

But this code is contained in the actionPerformed method, so you can't use Thread.sleep(ms) directly, because this would block the Event-Dispatch-Thread (EDT) and the GUI would become inresponsive.

So you have to perform this "animation" with an own Thread.

But you may not call Button#setIcon(...) on a different thread than the EDT.

So the actual solution is a bit tricky here - you have to "ping-pong" the responsibility between the two threads (alternatively, you could use a javax.swing.Timer, but I think this might require even more restructuring of your original code... Although I did not entirely understand what you are doing there (that is, which icons you are changing there for which reason)).

However, the general structure of such an approach could roughly look like this:

@Override
public void actionPerformed(ActionEvent e){

    ...
    //buttons that have same picture are explode.
    startAnimation();
}


private void startAnimation()
{
    Thread t = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            runAnimation();
        }
    });
    t.start();
}

private int a;
private int b;
private int c;
private void runAnimation()
{
    Random r = new Random();
    a = r.nextInt(64);
    b = r.nextInt(64);
    c = r.nextInt(64);

    for(int i=0; i<63; i++)
    {
        final int iFinal = i;
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                doAnimationStep(iFinal);
            }
        });

        try
        {
            Thread.sleep(100);
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
            return;
        }
    }
}

private void doAnimationStep(int i)
{
    String s0 = buttons[i].getIcon().toString();
    String s1 = buttons[i+1].getIcon().toString();
    String s2 = buttons[i+2].getIcon().toString();
    if(s0.equals(s1) && s1.equals(s2))
    {
        //System.out.println("slm");
        if(i > 7){
            buttons[i].setIcon(buttons[i-8].getIcon());
            buttons[i+1].setIcon(buttons[i-7].getIcon());
            buttons[i+2].setIcon(buttons[i-6].getIcon());

            for(int j = i; j > 0; j=j-8){
                if(j > 7){
                    buttons[j].setIcon(buttons[j-8].getIcon());
                    buttons[j+1].setIcon(buttons[j-7].getIcon());
                    buttons[j+2].setIcon(buttons[j-6].getIcon());
                }
                else{
                    buttons[j].setIcon(buttons[a].getIcon());
                    buttons[j+1].setIcon(buttons[b].getIcon());
                    buttons[j+2].setIcon(buttons[c].getIcon());
                }

            }
        }
        else{
            buttons[i].setIcon(buttons[a].getIcon());
            buttons[i+1].setIcon(buttons[b].getIcon());
            buttons[i+2].setIcon(buttons[c].getIcon());
        }
    }
}

BTW: You should not compare String objects with if (string0==string1) ... but always with if (string0.equals(string1)) ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top