在前面我们已经讲过了多线程的概念和具体的用法,那么接下来我们就用多线程来做一个具体的小项目吧——弹球小游戏
关于弹球,我们还是一样,先想清楚我们的弹球要有什么功能?
1.创立一个窗口
2.在窗口内任意点击位置会出现随机方向,随机速度的弹球
3.弹球碰到窗口边框反弹,任意两弹球碰撞反弹(交换速度
那么我们就开始吧
先要搞一个窗口吧,我们就直接上代码了
这个还是很容易看懂的
mport javax.swing.*;
import java.awt.*;
public class BallPalette extends JPanel {
private Graphics g;
private BallListen b;//传监听器
public void Palette() {
JFrame jf = new JFrame();
jf.setSize(500,500);//屏幕尺寸的
jf.setTitle("弹球小游戏一波");
//进程结束
jf.setDefaultCloseOperation(3);
//居中
jf.setLocationRelativeTo(null);
//设置背景色
jf.getContentPane().setBackground(Color.WHITE);
jf.setResizable(false);//设置窗口不可更改
jf.add(this, BorderLayout.CENTER);// 将面板添加到窗体上
jf.setVisible(true);//设置窗口可见(之前面板遮盖住了窗体。。。导致画面上无小球出现)
b= new BallListen();
jf.addMouseListener(b);//添加鼠标监听器
g=getGraphics();//获取画笔
bl.setG(g);//传画笔
}
public static void main (String []args ){
BallMain bm=new BallMain();
bm.Palette();
}
}
然后接下来就是弄一个监听器了,这个也比较简单,我就只弄一个鼠标点击的方法,获取点击的坐标,然后我们在这个类里面创建Ball类(下面会讲到这个类的)的队列,用来将每一次鼠标点击的坐标和每次随机产生的x,y方向的速度保存下来,还有画笔,并且将这些东西传到Ball类里面去(x,y需要作为起始画圆的坐标,Random用来作为随机速度,g用来画,list 用来判断小球碰撞的情况)
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;
public class BallListen extends MouseAdapter {
private Graphics g;
private int x,y;
private Ball ball;//小球对象
private ArrayListlist=new ArrayList<>();//创建小球队列,
private Random random =new Random();//设置随机速度与方向
public void setG(Graphics g) {
this.g = g;
}
public void mouseClicked(MouseEvent e) {
x=e.getX();//获取坐标
y=e.getY();
ball=new Ball(x,y,random.nextInt(20)-10,random.nextInt(20)-10,g,list);//速度范围-10到10,传到小球类里面去
list.add(ball);//添加到队列中去
}
}
前两个类放在一起看非常容易就能看懂了,然后我们要怎么做呢,我们需要一个小球类Ball,在这个类里面我们要实现画小球,小球移动,擦除小球移动痕迹的方法
好,我们把Ball的代码写出来
public class Ball {
private Graphics g;
private int x,y;
private int xspeed,yspeed;//速度
private ArrayList list;
public Ball(int x, int y, int xspeed, int yspeed, Graphics g, ArrayList list){//接收从Balllisten传过来的画笔,坐标,速度,队列
this.x=x;
this.y =y;
this.xspeed=xspeed;
this.yspeed=yspeed;
this.g=g;
this.list=list;
}
public void Sweep(Graphics g) {//擦除方法
g.setColor(Color.WHITE);//白色小球,与背景颜色一致
g.drawOval(x-20,y-60,40,40);//擦小球,-20与-60的原因是将鼠标点击点与圆的中点重合
}
public void Move() {//移动,撞击方法
x+=xspeed;//移动
y+=yspeed;
//碰到边框反弹
if(x<=20||x>=470){
xspeed=-xspeed;//反向速度
}
if (y<=60||y>=480){
yspeed=-yspeed;
}
// 小球和小球碰撞处理,比较圆心之间距离,遍历数组队列,找出当前球与其他球的圆心距离
for (int i = 0; i < list.size(); i++) {
Ball ball = (Ball) list.get(i);
if (ball != this) {//两个不同的小球的话
int xx = Math.abs(this.x - ball.x);
int yy = Math.abs(this.y - ball.y);
int xy = (int) Math.sqrt(xx * xx + yy * yy);// 两球圆心的距离
int tempx = 0;
int tempy = 0;
if (xy <= 40) {// 距离与相切的圆心距相比较,两球相碰
tempx = this.xspeed;
tempy = this.yspeed;
this.xspeed = ball.xspeed;// 交换速度
this.yspeed = ball.yspeed;
ball.xspeed = tempx;
ball.yspeed = tempy;
}
}
}
}
public void Draw(Graphics g) {//画球方法
g.setColor(Color.BLACK);//黑色小球
g.drawOval(x-20,y-60,40,40);//画小球
}
}
然后接下来就是最后的一个类了,BallRun类,用来实现不断画x,y经过move()方法而改变的新小球,擦除之前旧小球,形成小球不断移动的假象的线程类
来,我们也把这个类放出来(如果看不懂的可以先去看看线程的相关知识,我也写过一篇介绍线程的)
import java.awt.*;
import java.util.ArrayList;
public class BallRun implements Runnable {
private ArrayList list;
private Graphics g;
public BallRun(ArrayList list,Graphics g){//获取小球队列,和画笔
this.list=list;
this.g=g;
}
public void run() {
while (true) {//这个是必须的,保证线程一直在执行
System.out.println("线程执行" );
try {//抛出异常机制
for (int i = 0; i < list.size(); i++) {//遍历队列
Ball ball = (Ball) list.get(i);//取出小球,强制转型为Ball类
ball.Sweep(g);//擦除
ball.Move();//移动
ball.Draw(g);//画球
}
Thread.sleep(80);//睡眠80毫秒
} catch (InterruptedException en) {
en.printStackTrace();
}
}
}
}
但是大家可以看到,首先我们的BallRun还需要画笔和队列,还必须启动才行
于是我们的队列和画笔就在BallListen类里面的mouseClicked()方法里面获取,线程也在这个方法里启动,就是说,鼠标一点击就启动线程,如下
private BallRun ballRun;//先定义BallRun
...........
public void mouseClicked(MouseEvent e) {
x=e.getX();//获取坐标
y=e.getY();
ball=new Ball(x,y,random.nextInt(20)-10,random.nextInt(20)-10,g,list);//速度范围-10到10
list.add(ball);//添加到队列中去
ballRun =new BallRun(list,g);//将队列与画笔传到线程
Thread tr =new Thread(ballRun);//实例化,创立BallRun线程,就绪
tr.start();
}
就这样,我们的一个简易弹球小游戏就完成了,可以看看效果https://www.zhihu.com/video/992090301523161088
觉的不错的麻烦点波关注,谢谢大家,我还会更新的