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
193 views
in Technique[技术] by (71.8m points)

java - How can I use Program a game after swing.Timer stopped?

I'm writing a simple pikachu game in Java, and I use swing.Timer with JProgress Bar, my code is like this:

public static void TimeBarListener(final View scr){
    ActionListener updateProBar = new ActionListener() {
        @Override
            public void actionPerformed(ActionEvent actionEvent) {
            int val = scr.timeBar.getValue();
            if (val <= 0) {
                scr.gameOver();
                scr.timer = null;
                return;
            }
            scr.timeBar.setValue(--val);
        }
    };
    int t = n*400;
    scr.timer = new Timer(t, updateProBar);
}

The "src" here is a class which extends JFrame to display the game I wrote, and 'n' is the number of pikachu pieces on a level. It works perfectly but after I add "timer", there are lots of problems occured:

  1. I set the variable 't' change by level, but seems like it doesn't work ( I test the value, it was the right value but seems like 'timer' could'n get it). The time ran out too fast, faster if I click more on the pieces, and even if I set it longer it didn't change anything.

  2. When I clicked "New Game" the second times, timer ran out even faster. But if I close the programs and then run again, the time return normal.

  3. If the time ran out and then I click the "New Game" button again, It appears for 1 second then return to the "Game Over screen". Sometimes it works, but "IndexArrayOutOfBounds" Ecception appears.

  4. I want to use the "Pause" button, which means that timer must pause and then continue to run, too. Is there anyway that I can do it?

I guess my problems are based on the code

            if (val <= 0) {
                scr.gameOver();
                scr.timer = null;
                return;
            }

which makes the Game Over screen appears if the timer run out. But I'm new to this and I cant understand how I works, so I can't think of any solutions myself, or maybe it's not the problem.

Hope that I'll get some helps from you guys. Thanks a lot :)

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

Your problem is that you don't use correct architecture pattern. You should separate your business logic from your presentation. Also you should store variables (like time_left) in model, not in the controller (i.e. ActionListener). Please read about: Model View Controller pattern. It's a basic pattern and it'll solve most of yours problems.

Basic Example

mvc

Editor.java - main class

public class Editor {
    public static void main(String[] args) {
        Model model = new Model();
        View view = new View(model);
        new Controller(model, view);
    }
}

View.java

public class View extends JFrame {

    private Model model;
    private JButton btn;

    public View(Model model) {
        this.model = model;
        this.btn = new JButton("Test");
    }

    public void addViewControlListener(ActionListener al){
        btn.addActionListener(al);
    }
}

Controller.java

public class Controller {
    public Controller(Model model, View view) {
        view.addViewControlListener(new ViewControlListener(model, view));
    }
}

ViewControlListener.java - implements ActionListener

public class ViewControlListener implements ActionListener {

    private Model model;
    private View view;

    public ViewControlListener(Model model, View view){
        this.model = model;
        this.view = view;
    }

    public void actionPerformed(ActionEvent e) {
        //update model
        //refresh view
    }

}

As you can see I have the one place (Controller.java) where I create listeners and add
these to components in view. You created multiple instances of the same listeners and lost control.

Also my ActionListener (ViewControlListener.java) holds instances of model and view, so it can update variables in model and refresh view.

Your application

And now something more about your application. You need thread (not realy action listener) that would decrement time variable and update view to show actual state (but only when game is active).

So you could create in model leftTime and isActive variables with setters and getters:

private int leftTime;
private boolean isActive;

public int getLeftTime() {
    return leftTime;
}

public void setLeftTime(int leftTime) {
    this.leftTime = leftTime;
}

public void decLeftTime() {
    this.leftTime--;
}

public boolean isActive() {
    return isActive;
}

public void setActive(boolean isActive) {
    this.isActive = isActive;
}

And create thread that decrement time every second and repaint the view:

public class Timer extends Thread {

    private Model model;
    private View view;

    public Timer(Model model, View view) {
        this.model = model;
        this.view = view;
    }

    public void run() {
        while(true) { //could be better
            if(model.isActive()) {
                model.decLeftTime();
                view.repaint();
            }
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Then create and start that thread in Controller:

public class Controller {
    public Controller(Model model, View view) {
        view.addViewControlListener(new ViewControlListener(model, view));
        ...
        Timer timer = new Timer(model, view);
        timer.start();
    }
}

In view you would add some component that shows left time from model and that's it.

PS do not forget set leftTime on game start.


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

...