用JAVA实现雷电小游戏
- 效果图如下:
- 实现雷电小游戏,主要创建了三个类:Ball类、BallJPanel类、BallJFrame类
Ball类中定义了敌方战机、子弹和我方子弹,将该三者都看成圆,即看成同一个类
Ball类中包含dr()<画出敌机及其子弹>、mv()<敌机及其子弹的移动>、isTouch()<判断子弹之间是否碰撞>方法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
57public class Ball {
int x,y;//圆角坐标
int r;
int ori;//方向 4向上 5向下
int type;//标记类型,0我方发出,1敌方发出
//awt包中Swing界面能识别图片的类
public static Image image_fire =
new ImageIcon("fire.gif").getImage();
public static Image image_el =
new ImageIcon("el_0.gif").getImage();
//构造器
public Ball(){
}
public Ball(int x, int y, int r, int ori, int type){
this.x = x;
this.y = y;
this.r = r;
this.ori = ori;
this.type = type;
}
//画在相应的JPanel中
public void dr(Graphics g){
switch (type){
case 0:
g.drawImage(image_fire,x,y,
2*r,2*r,null);
break;
case 1:
g.drawImage(image_el,x,y,
2*r,2*r,null);
break;
}
}
//判断两个球是否相遇
public boolean isTouch(Ball ball2){
boolean isTouch = false;
//第一个圆心坐标
int x1 = x + r;
int y1 = y + r;
//b2圆心坐标
int x2 = ball2.x + ball2.r;
int y2 = ball2.y + ball2.r;
double s = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
if (s<=r+ball2.r){
isTouch = true;
}
return isTouch;
}
//我方子弹或敌机及其子弹移动
public void mv(){
switch (ori){
case 4: y--;break;
case 5: y++;break;
}
}
}BallJPanel类中定义了画笔类、鼠标事件、监听器、多线程、我方飞机类等
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197/**
* @author threee
* @date 2020/2/14 - 13:20
* 单继承 多实现
* MouseMotionListener拖动,移动事件
* MouseListener鼠标点击事件
*/
public class BallJPanel extends JPanel
implements MouseListener, MouseMotionListener,Runnable {
//我方子弹集合
ArrayList<Ball> allBalls;
//敌方子弹飞机集合
ArrayList<Ball> allSnows;
//是否开火,true开火
boolean isFire;
//积分
int score;
//我方飞机图片
Image hero_img = new ImageIcon("hero.gif").getImage();
//监听:随时准备好,等待事件的触发,一旦触发,相应的方法会发生效果
//监听代码放在构造器中,表示BallJPanel一初始化就可监听了
public BallJPanel(){
//第一个this代表当前BallJPanel
//第二个this代表当前鼠标事件
this.addMouseListener(this);
this.addMouseMotionListener(this);
//我方飞机默认出现的位置
plane.x = 100;
plane.y = 400;
//得分默认为0
score = 0;
allBalls = new ArrayList<>();
allSnows = new ArrayList<>();
}
public void paint(Graphics g) {
super.paint(g);
//显示背景图
//通过当前类所有的目录取路径
URL imgURL = getClass().getResource("back.jpg");
ImageIcon icon = new ImageIcon(imgURL);
//放入图片
g.drawImage(icon.getImage(),0,0,400,600,this);
//我方飞机
g.drawImage(hero_img,plane.x,plane.y,200,100,null);
//积分
g.setColor(Color.red);
g.setFont(new Font("宋体",Font.BOLD,24));
g.drawString("积分",300,35);
g.drawString(String.valueOf(score),350,35);
g.drawString("生命",300,60);
g.drawString(String.valueOf(plane.life),350,60);
//假设allBalls有Ball时,每个ball要画出来
for (int i=0;i<allBalls.size(); i++){
Ball b = allBalls.get(i);
b.dr(g);
}
for (int i=0;i<allSnows.size(); i++){
Ball b = allSnows.get(i);
b.dr(g);
}
}
//线程需要做的事
public void run() {
//判断isFire是否为true
int count = 0;
while(true){
//通过count控制频率
count++;
if (count>=Integer.MAX_VALUE){
count = 0;
}
//不断落下的敌机
if(count%60 == 0){
Ball b = new Ball((int)(Math.random()*400),
-50,30,5,1);
allSnows.add(b);
}
//敌方飞机子弹下移
for (int i=0; i<allSnows.size(); i++){
Ball b1 = allSnows.get(i);
b1.mv();
if (b1.y>600){
allSnows.remove(b1);
}
}
//判断isFire是否为true
if (isFire && count%100 == 0){
Ball ball1 = new Ball(plane.x+100,plane.y+50,20,4,0);
allBalls.add(ball1);
}
//我方子弹上移
for (int i=0; i<allBalls.size(); i++){
Ball b2 = allBalls.get(i);
b2.mv();
if (b2.y<0){
allBalls.remove(b2);
}
}
//当我方子弹遇到敌机时,双方都消失,积分 +10
for (int i=0; i<allBalls.size(); i++){
for (int j=0; j<allSnows.size(); j++){
if ( i<allBalls.size() && j<allSnows.size()
&& allBalls.get(i).isTouch(allSnows.get(j))){
allBalls.remove(i);
allSnows.remove(j);
score += 10;
}
}
}
//我方战机碰撞敌方战机时,生命 -10
for (int i=0; i<allSnows.size(); i++){
if (i<allSnows.size() && plane.isCrash(allSnows.get(i))){
plane.life -= 10;
allSnows.remove(i);
if(plane.life <= 0){
plane.die = true;
//弹出信息提示框
JOptionPane.showMessageDialog(null,"GAME OVER!");
}
}
}
if (plane.die){
System.exit(0);
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
isFire = true;
}
public void mouseReleased(MouseEvent e) {
isFire = false;
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
//拖动
public void mouseDragged(MouseEvent e) {
//e是鼠标的实时位置
plane.x = e.getX()-100;
plane.y = e.getY()-50;
repaint();
}
public void mouseMoved(MouseEvent e) {
//e是鼠标的实时位置
// x = e.getX();
// y = e.getY();
// repaint();
}
}
class plane{
//我方飞机坐标
static int x,y;
//我方飞机生命值
static int life = 100;
//飞机是否死亡
static boolean die = false;
public static boolean isCrash(Ball ball2){
boolean isCrash = false;
int x1 = plane.x + 100;
int y1 = plane.y + 50;
int x2 = ball2.x + ball2.r;
int y2 = ball2.y + ball2.r;
double s = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
if (s<=30+ball2.r){
isCrash = true;
}
return isCrash;
}
}BallJFrame类中定义了主窗体,main方法。用sh()方法画出界面,构造器运行线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class BallJFrame extends JFrame {
BallJPanel jPanel;
public BallJFrame(){
jPanel = new BallJPanel();
this.add(jPanel);
Thread thread = new Thread(jPanel);
thread.start();
}
//写一个方法画出界面
public void sh(){
this.setSize(400,600);
this.setTitle("雷电");
//当点击JFrame关闭时,整个程序也随之关闭
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
BallJFrame jFrame = new BallJFrame();
jFrame.sh();
}
} - 本次实践知识总结:
- 把图片放入窗体中有两种方法:
(1)、通过URL查找当前类的目录路径,再赋给ImageIcon类的对象,再用画笔类drawImage方法画出 (图片放在当前类的同一个包下)
(2)、直接new一个ImageIcon类的对象赋给Image类的对象,再用画笔类drawImage方法画出(图片放在项目的根目录下)1
2
3
4
5//通过当前类所有的目录取路径
URL imgURL = getClass().getResource("back.jpg");
ImageIcon icon = new ImageIcon(imgURL);
//放入图片
g.drawImage(icon.getImage(),0,0,400,600,this);1
2
3
4
5
6
7
8
9//awt包中Swing界面能识别图片的类
public static Image image_fire =
new ImageIcon("fire.gif").getImage();
public static Image image_el =
new ImageIcon("el_0.gif").getImage();
g.drawImage(image_fire,x,y,
2*r,2*r,null);
g.drawImage(image_el,x,y,
2*r,2*r,null);- java中添加信息弹出框的方法:
1
JOptionPane.showMessageDialog(null,"GAME OVER!");
- 把图片放入窗体中有两种方法: