Java-GUI编程之弹球小游戏

Java也可用于开发一些动画。所谓动画,就是间隔一定的时间(通常小于0 . 1秒 )重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画 。

​为了实现间隔一定的时间就重新调用组件的 repaint()方法,可以借助于 Swing 提供的Timer类,Timer类是一个定时器, 它有如下一个构造器 :
Timer(int delay, ActionListener listener): 每间隔 delay 毫秒,系统自动触发 ActionListener 监听器里的事件处理器方法,在方法内部我们就可以调用组件的repaint方法,完成组件重绘。

案例2:

​ 使用AWT画图技术及Timer定时器,完成下图中弹球小游戏。


演示代码2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class PinBall {

//桌面宽度
private final int TABLE_WIDTH = 300;
//桌面高度
private final int TABLE_HEIGHT = 400;


//球拍的高度和宽度
private final int RACKET_WIDTH = 60;
private final int RACKET_HEIGHT = 20;

//小球的大小
private final int BALL_SIZE = 16;

//定义小球纵向运行速度
private int ySpeed = 10;
//小球横向运行速度
private int xSpeed = 5;

//定义小球的初始坐标
private int ballX = 120;
private int ballY = 20;

//定义球拍的初始坐标,x坐标会发生变化,y坐标不会发生变化
private int rackeX = 120;
private final int RACKET_Y = 340;

//声明定时器
private Timer timer;

//定义游戏结束的标记
private boolean isLose = false;

//声明一个桌面
private MyCanvas tableArea = new MyCanvas();

//创建窗口对象
private Frame frame = new Frame("弹球游戏");

public void init(){
//设置桌面区域的最佳大小
tableArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
//把桌面添加到frame中
frame.add(tableArea);

//定义键盘监听器
KeyListener keyListener = new KeyAdapter(){

//监听键盘 ← → 按下操作,当指定的键按下时,球拍的水平坐标分别会增加或者减少
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode==KeyEvent.VK_LEFT){//←
//没有到左边界,可以继续向左移动
if (rackeX>0){
rackeX-=10;
}
}

if (keyCode==KeyEvent.VK_RIGHT){//→
//没有到右边界,可以继续向右移动
if (rackeX<TABLE_WIDTH-RACKET_WIDTH){
rackeX+=10;
}
}
}
};

//为窗口和tableArea分别添加键盘事件
frame.addKeyListener(keyListener);
tableArea.addKeyListener(keyListener);

//定义ActionListener,用来监听小球的变化情况
ActionListener timerTask = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//小球碰到左右边框
if (ballX<=0 || ballX>=TABLE_WIDTH-BALL_SIZE){
xSpeed=-xSpeed;
}
//小球的高度超出了球拍的位置,且横向不在球拍范围内,则游戏结束
if (ballY > RACKET_Y && (ballX<rackeX || ballX>rackeX+RACKET_WIDTH)){
//结束定时器
timer.stop();
//把游戏结束的标记设置为true
isLose = true;
//重绘界面
tableArea.repaint();

}
//如果小球横向在球拍范围内,且到达球拍位置或者到达顶端位置,则小球反弹
if (ballY<=0 || (ballY>=RACKET_Y-BALL_SIZE && ballX>=rackeX && ballX<=rackeX+RACKET_WIDTH)){
ySpeed=-ySpeed;
}

//更新小球的坐标
ballX+=xSpeed;
ballY+=ySpeed;

//重绘桌面
tableArea.repaint();
}
};

//设置定时器,定时任务就是timerTask
timer = new Timer(100,timerTask);
timer.start();

//设置frame最佳大小,并可视

frame.pack();
frame.setVisible(true);


}

public static void main(String[] args) {
new PinBall().init();
}

private class MyCanvas extends Canvas{

//重写paint方法,实现绘图
@Override
public void paint(Graphics g) {
//判断游戏是否结束
if (isLose){//结束
g.setColor(Color.BLUE);
g.setFont(new Font("Times",Font.BOLD,30));
g.drawString("游戏结束!",50,200);
}else{//没有结束

//设置颜色并绘制小球
g.setColor(Color.RED);
g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);

//设置颜色并绘制球拍
g.setColor(Color.PINK);
g.fillRect(rackeX,RACKET_Y,RACKET_WIDTH,RACKET_HEIGHT);
}

}
}
}
如果您有什么问题或建议可以在下方的评论区评论,我会及时回复的。
欢迎关注我的公众号,共同学习,共同提升!
您可以通过公众号向我留言,也可以通过邮箱(lklong@88.com)联系我