我正在用Java编写一个简单的皮卡丘游戏,我使用swing.Timer和JProgress Bar,我的代码是这样的:
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);
}
这里的“src”是一个扩展JFrame以显示我写的游戏的类,'n'是一个级别上的皮卡丘碎片的数量。它工作得很好但是在我添加“计时器”之后,出现了很多问题:
我设置变量't'按级别更改,但似乎它不起作用(我测试了值,它是正确的值,但似乎'计时器'无法得到它)。如果我点击更多的东西,时间用得太快,速度更快,即使我把它设置得更长,它也没有改变任何东西。
当我第二次点击“新游戏”时,计时器跑得更快。但如果我关闭程序然后再次运行,时间会恢复正常。
如果时间用完,然后我再次点击“新游戏”按钮,它会显示1秒钟,然后返回“游戏结束屏幕”。有时候它会起作用,但会出现“IndexArrayOutOfBounds”Ecception。
我想使用“暂停”按钮,这意味着计时器必须暂停然后继续运行。无论如何我能做到吗?
我猜我的问题是基于代码
if (val <= 0) {
scr.gameOver();
scr.timer = null;
return;
}
如果计时器用完,会出现Game Over屏幕。但我是新手,我无法理解我的工作方式,所以我自己也想不出任何解决方案,或者可能不是问题。
希望我能从你们那里得到一些帮助。非常感谢:)
答案 0 :(得分:2)
您的问题是您没有使用正确的架构模式。您应该将业务逻辑与演示文稿分开。您还应该在模型中存储变量(如time_left
),而不是在控制器中(即ActionListener
)。请阅读:Model View Controller模式。这是一个基本模式,它将解决你的大部分问题。
Editor.java - 主要类
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 - 实现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
}
}
正如你所看到的,我有一个地方(Controller.java
),我在那里创建了听众并添加了
这些是视图中的组件。您创建了相同侦听器的多个实例并失去了控制权。
此外,我的ActionListener
(ViewControlListener.java
)包含模型和视图的实例,因此它可以更新模型和刷新视图中的变量。
现在更多关于你的应用程序。你需要线程(不是真正的动作监听器)来减少时间变量和更新视图以显示实际状态(但仅当游戏处于活动状态时)。
因此,您可以使用setter和getter在模型leftTime
和isActive
变量中创建:
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;
}
创建每秒减少时间的线程并重新绘制视图:
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();
}
}
}
}
然后在Controller中创建并启动该线程:
public class Controller {
public Controller(Model model, View view) {
view.addViewControlListener(new ViewControlListener(model, view));
...
Timer timer = new Timer(model, view);
timer.start();
}
}
在视图中,您将添加一些显示模型剩余时间的组件,就是它。
PS不要忘记在游戏开始时设置leftTime
。