上次已经完成了弹球碰壁问题,还没有发表,今天刚刚完成了弹球之间的碰撞。下面我来分析一下的弹球程序。
声明两个按钮,声明一个静态变量,m用来记录按钮的值
JButton a,b;
static int m=0;
创建一个队列,装入弹球的线程
public static java.util.ArrayList arr=new java.util.ArrayList();
显示界面的方法:在窗体上添加了2个面板,进度条、按钮都在面板1上,弹球在面板2 上运动。点击按钮会有不同的值,这个值会被控制进度条、控制弹球、和弹球的监听器类使用,以控制弹球运动和进度条。
public void showt(){
this.setTitle("弹球");
this.setSize(550,600);
JPanel p1=new JPanel(),
p2=new JPanel();//创建2个面板
//给面板设置位置
this.add(p1,BorderLayout.NORTH);
this.add(p2,BorderLayout.SOUTH);
p1.setBounds(0,0,550, 20);
p2.setBounds(0,20,550, 500);
JProgressBar p=new JProgressBar();//创建一个进度条对象
p.setMaximum(2000);//设置进度条的最大值是300
a=new JButton("开始");
b=new JButton("暂停");
//将进度条、按钮添加到面板1上
p1.add(p);
p1.add(a);
p1.add(b);
p1.setBackground(Color.blue);//面板1的背景为蓝色
this.setResizable(true);//是否能最大化
this.setDefaultCloseOperation(3);//关闭窗体是退出程序
this.setLocationRelativeTo(null);//窗体居中显示
this.setVisible(true);//窗体可见
this.validate();
//得到画布对象
Graphics g = this.getGraphics();
int a1=0,b1=1,c=2,d=3;
//创建线程
Tan t1=new Tan(a1,g);
arr.add(t1);//将线程1加入队列中
//启动线程
t1.start();
System.out.println("第一个线程已启动");
Tan t2=new Tan(b1,g);
arr.add(t2);//将线程2加入队列中
//启动线程
t2.start();//start()调用run()方法
System.out.println("第二个线程已启动");
Tan t3=new Tan(c,g);
arr.add(t3);//将线程3加入队列中
t3.start();//启动线程
System.out.println("第三个线程已启动");
Tan t4=new Tan(d,g);
arr.add(t4);//将线程4加入队列中
t4.start();//启动线程
System.out.println("第四个线程已启动");
Progressj tt=new Progressj(p);//创建控制进度条的线程
tt.start();//启动线程
Jian ji=new Jian(arr);//创建一个弹球的监视器线程对象
ji.start();//启动线程
System.out.println("监视线程已启动");
ActionListener ac=new ActionListener(){
public void actionPerformed(ActionEvent e){
if(e.getSource()==a){m=1;}//点击“开始”按钮,m的值为1
else if(e.getSource()==b){ m=0;}//点击“暂停”按钮,m的值为0
}
};
//给按钮添加监视器
a.addActionListener(ac);
b.addActionListener(ac);
}
进度条的类:这个类用来控制进度条
public class Progressj extends Thread{
JProgressBar p;
static int x=0;
public Progressj(JProgressBar p){
this.p=p;
}
public void run(){
jin();
}
public void jin(){
while(true){
p.setValue(x);//设置进度条的当前值
if(Mainr.m==1&&x<2000) {x+=5;
}
try{
Thread.sleep(200);
}catch(Exception e){
}
}
}
}
弹球运动的类:当弹球碰到壁后就改变运动方向,当不同方向的球碰撞后,就反方向运动。
注意:在每一个方向的弹球运动方法中,当弹球碰撞后(即t1为非零的值),要先改变t1的值,再调用弹球另一个方向运动的方法。因为每一个弹球的运动都是一个线程,在时间没有结束时吗,会不停的执行下去,若在调用弹球方向运动方法后改变t1的值为0,那么,弹球碰撞后会分开,但碰到壁后就停止消失,再两个弹球出现在碰撞的地方,分开,再运动。
public class Tan extends Thread {
int a;//a代表哪一个弹球线程
Graphics g;
int m,n,k;//k记录弹球的运动方法
int t1=0,t2,t3;
Color co;//弹球的颜色
public Tan(int a,Graphics g){
this.a=a;
this.g=g;
}
public void run(){
if(a==0) {
rightstoleft(505,60,Color.green);
}//右上角到左下角的初始球
if(a==1) {
leftstoright(5,60,Color.red);}//从左上角到右下角
if(a==2) {
rightsytoleft(505,555,Color.yellow);}//从右下角到左上角
if(a==3) {
leftsytoright(5,555,Color.pink);}//从左下角到右上角
}
//从右上角到左下角(x,y)为弹球的坐标,b代表哪个弹球
public void rightstoleft(int x,int y,Color c){
boolean a=true;
while(a){
g.clearRect(x+2, y-1, 40, 40);
g.setColor(c);
g.fillOval(x, y, 40, 40);
if(Mainr.m==1&&Progressj.x<2000) {x-=2;y++;}
if(x<=6&&x>=5&&y<555) {leftstoright(x,y,c); a=!a; }//然后左上右下,a的值变化,该方法执行结束,进行下一个方法
if(y==555&&x>5) {rightsytoleft(x, y,c);a=!a; } //从右下角到左上角
if(x==5&&y==555) {leftsytoright(x,y,c);a=!a; }//从左下角到右上角
//当弹球在此方向运动的时候发生碰撞:t1=1,则返回,即从左下方向右上方运动。
if(t1==1) {t1=0;leftsytoright(t2,t3,c);a=!a;}//要先将t1=0,再才能够调用弹球运动的方法
//暂停一下
try{ Thread.sleep(15);
}
catch(Exception e){
}
m=x;n=y;
k=1;co=c;
}
}
//从左上角到右下角
public void leftstoright(int x,int y,Color c){
boolean a=true;
while(a){
g.clearRect(x-2, y-1, 40,40);
g.setColor(c);
g.fillOval(x, y, 40, 40);
if(Mainr.m==1&&Progressj.x<2000) {
x+=2;y++;}
if(x>=504&&x<=505&&y<555) {rightstoleft(x,y,c); a=!a; }//然后右上左下
if(y==555&&x<505) {leftsytoright(x,y,c); a=!a; }//然后左下右上
if(x==505&&y==555) {rightsytoleft(x, y,c); a=!a; }//从右下角到左上角
//当弹球在此方向运动的时候发生碰撞:t1=2,则返回,即从右下方向左上方运动。
if(t1==2) {t1=0;rightsytoleft(t2,t3,c);a=!a; }
//暂停一下
try{ Thread.sleep(5);
}
catch(Exception e){
}
m=x;n=y;
k=2;co=c;
}
}
//从右下角到左上角
public void rightsytoleft(int x, int y,Color c){
boolean a=true;
while(a){
g.clearRect(x+1, y+2, 40, 40);
g.setColor(c);
g.fillOval(x, y, 40, 40);
if(Mainr.m==1&&Progressj.x<2000) {x--;y-=2;}
if(x==5&&y>60) {leftsytoright(x,y,c); a=!a; }//从左下角到右上角
if(x==5&&y==60) {leftstoright(x,y,c); a=!a; }//从左上角到右下角
if(y>=60&&y<=61&&x>5) {rightstoleft(x,y,c); a=!a; }//然后右上左下
//当弹球在此方向运动的时候发生碰撞:t1=3,则返回,即从左上方向右下方运动。
if(t1==3) {t1=0;leftstoright(t2,t3,c);a=!a; }
//暂停一下
try{ Thread.sleep(10);
}
catch(Exception e){
}
m=x;n=y;k=3;co=c;
}
}
//从左下角到右上角
public void leftsytoright(int x,int y,Color c){
boolean a=true;
while(a){
g.clearRect(x-2, y+1, 40, 40);
g.setColor(c);
g.fillOval(x, y, 40, 40);
if(Mainr.m==1&&Progressj.x<2000) {x+=2;y--;}
if(x>=504&&x<=505&&y>60) {rightsytoleft(x,y,c); a=!a; }//然后右下左上
if(x==505&&y==60) {rightstoleft( x,y,c); a=!a; }//然后右上左下
if(y==60&&x<505) {leftstoright(x,y,c); a=!a; }//从左上角到右下角
//当弹球在此方向运动的时候发生碰撞:t1=4,则返回,即从右上到左下运动。
if(t1==4) {t1=0;rightstoleft(t2,t3,c);a=!a; }
//暂停一下
try{ Thread.sleep(20);
}
catch(Exception e){
}
m=x;n=y;k=4;co=c;
}
}
//碰撞的情况方法
public void pu(int t1,int t2,int t3,Color c){
//t1为传过来的k,t2,t3为弹球的位置
this.t1=t1;
this.t2=t2;
this.t3=t3;
}
}
弹球的监听器线程:获得队列中的数据,比较两个弹球的坐标,看是否在碰撞区内,在碰撞区内,调用tan 线程内处理碰撞情况的方法。
public class Jian extends Thread{
java.util.ArrayList arr;
//传递队列
public Jian(java.util.ArrayList arr){
this.arr=arr;
}
public void run(){
bijiao();
}
public void bijiao(){
while(true){
for(int i=0;i
//获得弹球的运动方向值,坐标,颜色
int x1=t1.m,
y1=t1.n,
x2=t2.m,
y2=t2.n,
k1=t1.k,
k2=t2.k;
Color c1=t1.co,
c2=t2.co;
if(Mainr.m==1&&Progressj.x<2000){//在没有暂停并且时间还没有结束情况下
if(k1!=k2&&Math.abs(x1-x2)<=40&&Math.abs(y1-y2)<=40){//在碰撞区内
t1.pu(k1,x1,y1,c1);//调用tan类中的方法,用来实现碰撞
t2.pu(k2,x2,y2,c2);
}
}
}
}
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
下面这张图片是界面刚刚出来是弹球还没有运动是的图片
下面这张图片是弹球运动过程中,被暂停后图片。你可以看到图中的粉红色弹球和红色的弹球离得很近。她们是碰撞后刚刚分开的图片。
下面的这张图片是在弹球运动时,打印出的弹球运动位置。上面有一行显示了“1<<<<3>>>311与293相等”,是红球和粉红弹球碰撞是的结果311和293是代表两球的x 坐标,1和3 代表他们在队列中的位置。下面也显示了碰撞后他们各自的运动方向