小弹球


                                  弹球的总结
     好吧,又是一次总结。
     这次讲述的是关于弹球的一些总结和想法。
     
    




   

首先,建立一个界面什么的就不用多说了,应该都知道了,反正我已经是知道了,那么,我就说一些在弹球上遇到的新问题和学到的新知识吧 !!!!!!!!!!!!!!!!
 


首先,我觉得最重要的当然就是线程了,在弹球这个阶段,我们学习的也就是线程。。。

Thread,这个类就是我们线程所需要用到的类了,需要注意的问题是,他的方法中有一个run方法,但是,这个方法却不能够像往常一样直接去调用这个方法,如果这样的话,就失去了最开始的线程的本质了。



在我的观点看来,线程的使用,可以让多个任务同时的进行,而不过像以前调用方法的时候,需要执行完那一个方法之后才会执行下一个方法。

而我们在使用的时候就需要去重写run的方法之后再用start()的方法去调用了。

感觉这一段没什么代码好写的,就没有贴什么代码上去了。

然后,在我们成功的使用了一个数组去解决小球的重绘和绘制问题之后,我们会很惊奇的发现,我们的屏幕会是一闪一闪的,造成这种问题的原因很简单,因为在我们重绘一个小球的时候,并没有去重绘别的小球,这样造成的结果就是,别的小球被在这个小球重绘的时候被刷掉了,然后轮到他们重绘的时候,又把自己给画上了,由于计算机极快的运算速度,所以在我们看来就是屏幕一闪一闪的样子了。这个问题最好的解决方法就是在别的面板上去重绘这些小球之后再画到面板上。。
简单的方法就是先将面板上的图形保存成图片,这个是Image类中的方法。
代码如下:


Image im = this.createImage(this.getPreferredSize().width,
this.getPreferredSize().height);
// 从图像上获取画布
Graphics2D gr = (Graphics2D) im.getGraphics();

super.paint(gr);

// 用创建图标的方法
ImageIcon ic = new ImageIcon("1.jpg");
// 绘制背景调用的方法
gr.drawImage(ic.getImage(), 1, 1, 398, 398, null);
// 绘制所有的小球
for (MarblesThread mbt : marbles) {
gr.setColor(mbt.color);
Ellipse2D.Double oval = new Ellipse2D.Double(mbt.x, mbt.y, 40,
40);
gr.fill(oval);
}
// 将图像绘制到JPanel上
g.drawImage(im, 0, 0, null);

这样的画,就算是在后台是一闪一闪的,但是在我们看的时候,他就是一个连续连贯的动作了。这样,就值得我们去注意一个问题了,我们在计算机中看到的所有的东西都是我们画上去了,所以,计算机并没有那个功能去像人一样做一个连贯的动作,只是很多的图片以极快的速度进行切换,才让我们觉得他们是连贯的,所以,当我们看到闪屏或者是不连贯的屏幕的时候,只要把他们之间切换的速度加快,或者是在后台将他们完成之后一起展现出来,这样就能形成一个连贯的图片了。

在画板的重绘中,我们还需要用到repaint()的方法,详细请参见JDK。



再之后,我觉得需要注意的问题就是怎么给按钮实现功能,让所有的小球能够暂停甚至是停止了。


简单的分析一下:
我们让小球进行运行时while语句的条件是true,所以我们想让小球停下来也要在这里做文章,但是,值得注意的是,我们不能够说是将这个线程停下来,而是要让他去空转,否我们实现的就不是暂停,而是停止了,因为同样一个线程只能够启动一次。

首先,我们说下停止的方法:
这个感觉没什么好说的,在我们最初设定的isStop=false的boolean量中,将判断条件改为
!isStop,当我们按停止的按钮的时候,就自动将判断的值改变,然后再清空队列就行了,真的没什么好说的。



然后,就是暂停和继续了,刚刚已经说了,我们是需要让线程去空转而不是停止,所以我们在这里就要将一个If条件句嵌套到while判断语句中去,这样的话,当满足条件的时候,我们就可以去执行,不满足条件的时候,我们就让他去空转,这样就实现了小球的暂停和继续了。
具体代码如下:
while (!isStop) {
if (!isSuspend) {
if (x <= 1 || x >= dim.width - marble - 1) {
mx = -mx;
}
if (y <= 1 || y >= dim.height - marble - 1) {
my = -my;
}

x += mx;
y += my;
my=my+1;
}
try {
Thread.sleep(30);
} catch (Exception ep) {
ep.printStackTrace();
}
}
至于怎么样去改变字面上字的细节就不详细说明了。



然后便是弹球碰撞的问题了,我把这个问题归结到算法类。

首先,我们需要注意的是,我们会存在两个小球同时出现在一起的情况,这个是之后必须要解决的问题,然后就是当小球碰撞之后,他们之间速度的变化的问题,在这里,我没有那个本事完全按照物理的方法来解决,因为我本身的物理就不是很好。所以首先,我们选择的是一个笨的方法,假设所有的小球移动的时候都是只有8个主要的方向的,并且碰撞的时候发生的速度的交换,这个代码可以自己想一下。但是后来我又发现,如果是这样的判断方法的话,我的小球在一起之后就在也分不开了,所以这样的算法显然并不是完全实用的,所以,在老师的指引下,我们采取了另外的一种方法,用角度来判断,因为,当用角度来判断的时候,小球之间就只存在左右之间的关系了,简单的说就是速度的变化不会再反复了,这样就能成功的实现了小球出现在一起之后立即分开了,而且也能少量的相似于真正的物理问题了。

具体代码如下:
public void crash() {
// 遍历数组,取出小球的对象
// 如果相碰的话
for (int i = 0; i < Marbles.marbles.size(); i++) {
MarblesThread mbt = Marbles.marbles.get(i);
// 判断取出的是不是小球的本身
if (!this.equals(mbt)) {
double redX = Math.abs((this.x + 20) - (mbt.x + 20));
double redY = Math.abs((this.y + 20) - (mbt.y + 20));
// 如果相碰
if (redX * redX + redY * redY <= 1600) {
double p1 = Math.atan((this.y - mbt.y) / (this.x - mbt.x));
if (this.x < mbt.x) {
this.mx = -Math.cos(p1);
this.my = -Math.sin(p1);
} else {
this.mx = Math.cos(p1);
this.my = Math.sin(p1);
}
}
}

}
}



猜你喜欢

转载自specialzheng-163-com.iteye.com/blog/1442784