package myball;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.util.*;
import java.math.*;


/** *//**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2007</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/

public class Ball ...{
int x_pos;
int y_pos;
int x_speed;
int y_speed;
int radius;
Color c;
Random rnd;

public Ball(int x,int y,int mvx,int mvy,int mr,Color mcolor) ...{
x_pos=x;
y_pos=y;
x_speed=mvx;
y_speed=mvy;
radius=mr;
c=mcolor;

}

public Ball() ...{
rnd=new Random();
x_pos=((rnd.nextInt()))%(int)99+10;
y_pos=(rnd.nextInt())%(int)99+10;
x_speed=(rnd.nextInt())%(int)5+5;
y_speed=(rnd.nextInt())%(int)5+5;
radius=5+(rnd.nextInt())%(int)5;
c=Color.red;
}

public void move()...{
x_pos=x_pos+x_speed;
y_pos=y_pos+y_speed;
}

public void drawball(Graphics g)...{
g.setColor(c);
g.fillOval(x_pos-radius,y_pos-radius,2*radius,2*radius);

}

public void setVX(int mvx)...{
x_speed=mvx;
}

public void setVY(int mvy)...{
y_speed=mvy;
}

public void setXPos(int x)...{
x_pos=x;
}

public void setYPos(int y)...{
y_pos=y;
}

}
package myball;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.util.*;


public class BallApplet extends Applet implements Runnable ...{
int x_pos=50;
int y_pos=50;
int x_speed=0;
int y_speed=0;
int radius=10;
int maxspeed=5;
int appletsize_x=300;
int appletsize_y=300;
Random rnd;
private Image dbImage;
private Graphics dbg;
AudioClip bounce;
AudioClip hit;
Image backImage;
ArrayList ball=new ArrayList();

public void init()...{
rnd=new Random();
x_speed=(rnd.nextInt())%maxspeed;
y_speed=(rnd.nextInt())%maxspeed;
appletsize_x=this.getWidth();
appletsize_y=this.getHeight();
bounce=getAudioClip(getCodeBase(),"chimes.au");
hit=getAudioClip(getCodeBase(),"gun.au");
backImage=getImage(getCodeBase(),"ok.gif");
//ballA=new Ball(200,200,-3,5,10,Color.cyan);
//ballB=new Ball(x_pos,y_pos,x_speed,y_speed,radius,Color.yellow);
//ballC=new Ball(90,90,4,3,10,Color.red);
ball.add(new Ball(200,200,-3,5,10,Color.white));
ball.add(new Ball(90,90,4,3,10,Color.white));
}

public boolean ballHit(Ball a,Ball b)...{
double distance=0;
double x=0;
double y=0;
double radius=0;
int speed=0,space=0;
radius=a.radius+b.radius;
x=a.x_pos-b.x_pos;
y=a.y_pos-b.y_pos;

if(x<radius && y<radius)...{
distance=Math.sqrt((x*x)+(y*y));

if(distance>radius)...{
return false;
}
else

...{
speed=a.x_speed;
a.setVX(b.x_speed);
b.setVX(speed);

if(x<0)...{
space=a.x_pos +(int) radius;
b.setXPos(space);
}
else

...{
space=b.x_pos+(int)radius;
a.setXPos((space));
}

speed=a.y_speed;
a.setVY(b.y_speed);
b.setVY(speed);

if(y>0)...{
space=a.y_pos+(int)radius;
b.setYPos(space);
}
else

...{
space=b.y_pos+(int)radius;
a.setYPos(space);
}
return true;
}
}
else

...{
return false;
}

}

public boolean ballOut(Ball b)...{

if(b.x_pos>appletsize_x-b.radius)...{
x_speed=-(b.x_speed);
b.setVX(x_speed);
b.setXPos(appletsize_x-b.radius);
return true;
}
else if(b.x_pos<b.radius)

...{
x_speed=-(b.x_speed);
b.setXPos(b.radius);
b.setVX(x_speed);
return true;
}

if(b.y_pos>appletsize_y-b.radius)...{
b.setYPos(appletsize_y-b.radius);
b.setVY(-(b.y_speed));
return true;
}

else if(b.y_pos<b.radius)...{
b.setYPos(b.radius);
y_speed=-(y_speed);
b.setVY(-(b.y_speed));
return true;
}
return false;
}

public boolean mouseDown(Event e,int x,int y) ...{

return true;
}

public boolean keyDown(Event e,int key)...{

return true;
}

void newBall()...{
ball.add(new Ball());
}

void eatBall(Ball b)...{
ball.remove(b);
}

public void start()...{
Thread th=new Thread(this);
th.start();
}

public void stop()...{}

public void destory()...{}

public void run()...{
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

while(true)...{


/**//* if(ballHit(ballA,ballB)){
hit.play();
}
if(ballHit(ballA,ballC )){
hit.play();
}
if(ballHit(ballB,ballC)){
hit.play();
}
if(ballOut(ballA)){
bounce.play();
}
ballA.move();
if(ballOut(ballB)){
bounce.play();
}
ballB.move();
if(ballOut(ballC)){
bounce.play();
}
ballC.move(); */
int i=0,j=0;
int size=0;
Ball ballA,ballB,ballEat;
ballEat=null;
size=ball.size();
for(i=0;i<size;i++)

...{ ballA=(Ball)(ball.get(i));
for(j=i+1;j<size;j++)

...{ ballB=(Ball)(ball.get(j));

if(ballHit(ballA,ballB))...{
hit.play();
//add a new ball

if (ballA.radius == ballB.radius) ...{
newBall();
}

else if(ballA.radius > ballB.radius)...{
ballEat=ballB;
}

else ...{
ballEat=ballA;
}
}
}
}

if(ballEat!=null)...{
eatBall(ballEat);
}

for(i=0;i<ball.size();i++)...{
ballA=(Ball)ball.get(i);

if(ballOut(ballA))...{
bounce.play();
}
ballA.move();
}
repaint();

try ...{
Thread.sleep(20);
}

catch(InterruptedException ex)...{

}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}

public void paint(Graphics g)...{
g.drawImage(backImage,0,0,this);

/**//* ballA.drawball(g);
ballB.drawball(g);
ballC.drawball(g); */
Ball ballA;
for(int i=0;i<ball.size();i++)

...{
ballA=(Ball)ball.get(i);
ballA.drawball(g);
}

}

public void update(Graphics g)...{
if(dbImage==null)

...{
dbImage=createImage(this.getSize().width,this.getSize().height);
dbg=dbImage.getGraphics();
}
dbg.setColor(getBackground());
dbg.fillRect(0,0,this.getWidth(),this.getHeight());
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage,0,0,this);
}
}

这个问题其实很复杂,因为小球之间的球心不在一条直线上。我只是为了编游戏,就省事些。
根据动量守恒原理。如果一个运动的小球碰上一个静止的小球,则原来的静止的小球运动。
小球相碰的时候有两个力,一个是产成的弹力,另一个是对方小球给额外施加的力。
也就是说,在完全弹性碰撞的时候发生了速度的交换。
例如:用子弹打同样重量的迎面飞来的石头,在完全弹性碰撞的时候,子弹把石头打飞了,子弹的速度成了石头的速度,反弹回来了。如果子弹追着石头打会如何呢?则,子弹停止了,石头飞的更快了。
就根据这个道理,把小球的速度分解成x轴速度和y轴速度。分别计算,最后合成。看看是否符合常规印象。
=========================================================================
经过编程实验成功了。实现起来很简单,当两个小球相撞的时候 x轴速度交换,y轴速度交换,就实现了两个小球的弹性碰撞。也就是说当一个小球飞撞上另一个静止的小球后,原来静止的小球开始运动,原来运动的小球静止。
编程还解决了两个小问题:
当两个小球相碰的时候,由于运动不是连续的,而是根据步长来的,因此碰撞时要重置两个小球球心
编程的基本步骤:
1. 主要是开一个线程,在线程中不断的更改小球的位置,然后调用applet 的repaint() 方法,实现动画效果。
2.为了让画面不闪烁,准备两幅画,后台画好了以后,前台再展示。