Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
277 views
in Technique[技术] by (71.8m points)

swing - repeating animation using java.swingTimer

I am writing the code of Game bean machine (Galton box) using animated graphics. I am using swing.Timer to make the red ball move, by letting the Timer object take an ActionListener.

Here is the output: The red ball here is moving randomly : http://imgur.com/J9Xq0t5&HIv1udp And here it reaches the bottom: http://imgur.com/J9Xq0t5&HIv1udp#1

The problem is that I want to make several balls moving not only 1 but I actually cannot, I tried to put the Timer object in a loop but it only speeded up the ball motion.

Here is the code I wrote:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.Scanner;
import javax.swing.*;


public class GameBean extends JFrame{
private int nSlots;
private int balls;

public GameBean (int nSlots, int balls){
    this.balls=balls;
    this.nSlots=nSlots;
    Timer timer=new Timer(500,new RandomListener());

    timer.start();

    JPanel panel = new JPanel();

    this.add(canvas); 
}

Ball canvas = new Ball();


 public static void main(String[] args) {

    Scanner input=new Scanner(System.in);

    System.out.println("Please enter number of slots: ");
    int nSlots=input.nextInt();

    JFrame frame = new GameBean (nSlots, 5);

    frame.setTitle("Bean Game Machine");
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setSize(300, 500);
    frame.setVisible(true);

   }
 class RandomListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
         canvas.moveRandom();
    }
}


class Ball extends JPanel{
    Random rand=new Random();
    private int n;
    private int raduis = 10;
    private int moveRaduis=12;
    private int L = 0;
    private int R = 0;
    private int D = 0;


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

        g.setColor(Color.RED);

        g.fillOval(getWidth()/2 -raduis/2  + R + L, 0 + D , moveRaduis, moveRaduis);

        repaint();
        int  i=0;
        int width=(getWidth()/8);
        int space=(getWidth()-nSlots*30)/2;
        g.setColor(Color.BLACK);
        for(i=0;i<=nSlots;i++){
            g.drawLine(space+(30*i),getHeight()-balls*(raduis) ,space+(30*i) ,getHeight() );
            if(i!=0 && i!=nSlots)
                g.fillOval(space+(30*i)-5, getHeight()-balls*(raduis)-5, 10, 10);
            if(i==0){
                g.drawLine(space,getHeight()-balls*(raduis) , space+((nSlots)*15)-(raduis/2)-15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2);
                g.drawLine(space+((nSlots)*15)-(raduis/2)-15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 , space+((nSlots)*15)-(raduis/2)-15 , getHeight()/2-nSlots*nSlots);//vertical line

            }
            if(i==nSlots){
                g.drawLine(space+(30*i), getHeight()-balls*(raduis), space+((nSlots)*15)+(raduis/2)+15, getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2);
                g.drawLine(space+((nSlots)*15)+(raduis/2)+15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 , space+((nSlots)*15)+(raduis/2)+15 , getHeight()/2-nSlots*nSlots);//vertical line

            }

        }


        int o=1;
        for(i=1;i<=nSlots-2;i++){
            int k=2;
            for(int j=i;j<=nSlots-2;j++){
                g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(balls*raduis)-(30*o)-raduis/2, raduis, raduis); 
                k=k+2;   
             }o++;
        }

      }

    public void moveRandom(){

        n=1+rand.nextInt(100);
        if(n<=51){
            D+=15;

            if(D<=(getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2))//if(D<=14*15)
                L=0;
            else if(D>getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 && D<getHeight()-balls*(raduis))
            {
                D+=15;
                L-=15;

            }
            else if(D>=getHeight()-balls*(raduis))
            {
                if(D==31*15)D-=15;
                D=D;

            }

        }
        else if (n>=51 && n<=100){
            D+=15;
            if(D<=getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2)
                R=0;
            else if(D>getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 && D<getHeight()-balls*(raduis))
                {
                D+=15;
                R+=15;
            }
            else if(D>=getHeight()-balls*(raduis)){

                if(D==31*15)D-=15;
                D=D;

            }

        }

    }
    } 

    }

Any HELP please ! Thanks all..

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's a suggestion.

Don't make each ball extends JPanel. Just make it a class for holding/manipulating/drawing the state.

Ball.java (notice Java naming convention)

public class Ball {
    int x, y; // and whatever other state you need

    public Ball(int x, int y {}  // or however you want to construct the ball

    public void draw(Graphics g) {
        // draw ball here
    }
    public void move() {
        // do calculations to move here
    }
}

Then just have one BallPanel class that extends JPanel and do the painting there. Just hold a List<Ball> in the class and you can call each Ball's draw() method in the paintComponent and each Ball's move() method in the Timer. You could even dynamically add balls to be animated by just adding a new Ball to the list. Something like

public class BallPanel extends JPanel {
    private List<Ball> balls;  // create the list

    public BallPanel() {
        Timer timer = new Timer(40, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                for (Ball ball: balls) {
                    ball.move();
                }
                repaint();
            }
        });
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Ball ball : balls) {
            ball.draw(g);
        }
    }
}

This way you don't have to worry above separate timers and layering panels.

See a bunch of complete example, using this technique, here and here and here and here and here and here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...