效果图:



由于Java可以很轻易的完成比较复杂的数学运算,所以我们经常能看到物理领域的问题借助Java实现效果演示,下面我给出一个桌球碰撞的处理及绘制实例。

package org.test.mail;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:Java桌球演示
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * 
@author chenpeng
 * @email:ceponline@yahoo.com.cn
 * 
@version 0.1
 
*/


public class JavaBilliards extends Panel implements Runnable, MouseListener,
        MouseMotionListener 
{

    
/**
     * 
     
*/

    
private static final long serialVersionUID = -5019885590391523441L;

    
// 球
    private double _ball;

    
// 缓存用背景
    private Image _screen;

    
// 画布
    private Graphics _graphics;

    
// 台桌
    private Image _table;

    
private double c[];

    
private double d[];

    
private double e[];

    
private double f[];

    
private int countBall;

    
private int h;

    
private double i[];

    
private double j[];

    
private double k[];

    
private double l[];

    
private double m[];

    
private double n[];

    
private double o[];

    
private double p[];

    
private boolean q[];

    
private double r;

    
private int a;

    
private int u;

    
private int v;

    
private int w;

    
private int x;

    
private boolean y;

    
private int z;

    
private int A;

    
/**
     * 初始化
     * 
     
*/

    
public JavaBilliards() {
        a 
= 0;
        r 
= 10D;
        z 
= 300;
        A 
= 0;
        setBounds(
5050700350);
        Frame frame 
= new Frame("Java桌球演示");
        frame.add(
this);
        frame.setBounds(
00700380);
        frame.setResizable(
false);
        frame.setVisible(
true);
        frame.addWindowListener(
new WindowAdapter() {
            
public void windowClosing(WindowEvent e) {
                System.exit(
0);
            }

        }
);
        requestFocus();
        initialize();
    }


    
public void initialize() {
        
// 基础数据
        base();
        
// 注入实例
        immit();
        
// 缓存背景
        _screen = new BufferedImage(this.getWidth(), this.getHeight(), 1);
        
// 背景图形
        _graphics = _screen.getGraphics();
        
// 绘制台桌
        makeTable();
        
// 设置监听
        addMouseListener(this);
        addMouseMotionListener(
this);
        
// 启动
        new Thread(this).start();
    }


    
/**
     * 初始化数据
     * 
     
*/

    
public void base() {

        
// 球体
        _ball = 16D;
        c 
= (new double[] { 40D, (double) (getWidth() - 40) });
        d 
= (new double[] { c[0], (double) getHeight() - c[0] });
        e 
= (new double[] { c[0+ 20D, (double) (getWidth() / 2), c[1- 20D });
        f 
= (new double[] { d[0+ 20D, d[1- 20D });
    }


    
/**
     * 注入实例
     * 
     
*/

    
public void immit() {
        countBall 
= 16;
        i 
= new double[countBall];
        j 
= new double[countBall];
        k 
= new double[countBall];
        l 
= new double[countBall];
        m 
= new double[countBall];
        n 
= new double[countBall];
        o 
= new double[countBall];
        p 
= new double[countBall];
        q 
= new boolean[countBall];
        
// 打击对象
        hitObject();
        
// 打击用球
        hitBall();
    }


    
/**
     * 打击用球数值
     * 
     
*/

    
public void hitBall() {
        i[
0= (1.0D * (e[2- e[0])) / 3D;
        j[
0= this.getHeight() / 2;
        k[
0= 0.0D;
        l[
0= 0.0D;
        q[
0= true;
    }


    
/**
     * 打击对象
     * 
     
*/

    
public void hitObject() {
        
int il = 1;
        h 
= countBall - 1;
        
// 求平方根
        double dl = Math.sqrt(3.5D);
        
for (int j1 = 0; j1 < 5; j1++{
            
double d2 = ((double) getWidth() * 2D) / 3D + (double) j1 * dl * r;
            
double d3 = (double) (getHeight() / 2- (double) j1 * r;
            
for (int k1 = 0; k1 <= j1; k1++{
                i[il] 
= d2;
                j[il] 
= d3;
                k[il] 
= 0.0D;
                l[il] 
= 0.0D;
                q[il] 
= true;
                d3 
+= 2D * r;
                il
++;
            }


        }


    }


    
 
这么点代码居然不能一次都发了……

/**
     * 绘制台球桌
     * 
     
*/

    
public void makeTable() {
        _table 
= new BufferedImage(this.getWidth(), this.getHeight(), 1);
        Graphics g 
= _table.getGraphics();
        g.setColor(Color.GRAY);
        g.fillRect(
00, getWidth(), getHeight());
        g.setColor((
new Color(20010050)).darker());
        g.fill3DRect((
int) c[0], (int) d[0], (int) (c[1- c[0]),
                (
int) (d[1- d[0]), true);
        g.setColor(Color.BLACK);
        g.fill3DRect((
int) e[0], (int) f[0], (int) (e[2- e[0]),
                (
int) (f[1- f[0]), false);
        g.setColor(Color.GREEN.darker());
        g.drawLine((
int) ((1.0D * (e[2- e[0])) / 3D), (int) f[0],
                (
int) ((1.0D * (e[2- e[0])) / 3D), (int) f[1]);
        g.fillOval((
int) ((1.0D * (e[2- e[0])) / 3D) - 2,
                (
int) ((f[1+ f[0]) / 2D) - 244);
        g.drawArc((
int) ((1.0D * (e[2- e[0])) / 3D) - 20,
                (
int) ((f[1+ f[0]) / 2D) - 20404090180);
        g.setColor(Color.BLACK);
        
double d1 = _ball - 2D;
        
for (int i1 = 0; i1 < 3; i1++{
            
for (int j1 = 0; j1 < 2; j1++{
                g.fillOval((
int) (e[i1] - d1), (int) (f[j1] - d1),
                        (
int) (2D * d1), (int) (2D * d1));
            }

        }

    }


    
/**
     * 线程处理
     
*/

    
public void run() {
        
long timeStart;
        timeStart 
= System.currentTimeMillis();
        
// 死循环反复处理
        for (;;) {
            
long timeEnd = System.currentTimeMillis();
            
switch (a) {
            
default:
                
break;

            
case 1:
                
// 根据时间换算运动轨迹
                conversion(timeEnd - timeStart);
                
// 过程处理
                course();
                
break;

            
case 2:
                conversion(timeEnd 
- timeStart);
                
// 过程处理
                course();
                
boolean flag = true;
                
for (int i1 = 0; flag && i1 < countBall; i1++)
                    flag 
= k[i1] == 0.0D && l[i1] == 0.0D;

                
if (flag) {
                    a 
= 1;
                    
// 击球
                    if (!q[0]) {
                        hitBall();
                    }

                }

                
if (h == 0)
                    a 
= 3;
                
break;

            
case 3:
                hitObject();
                hitBall();
                a 
= 0;
                
break;
            }


            repaint();
            timeStart 
= timeEnd;
            
try {
                Thread.sleep(
10L);
            }
 catch (InterruptedException e1) {
                e1.printStackTrace();
            }

        }


    }


    
public void course() {
        
// 限制区域
        limit();
        
// 入袋处理
        pocket();
        
// 运动演算
        play();
        
for (int i1 = 0; i1 < countBall; i1++)
            
if (q[i1]) {
                i[i1] 
= m[i1];
                j[i1] 
= n[i1];
            }

    }


    
/**
     * 变换时间为动作数据
     * 
     * 
@param value
     
*/

    
public void conversion(long value) {
        
double d1 = (double) value / 1000D;
        
for (int i1 = 0; i1 < countBall; i1++)
            
if (q[i1]) {
                m[i1] 
= i[i1] + k[i1] * d1;
                n[i1] 
= j[i1] + l[i1] * d1;
                k[i1] 
*= 0.98999999999999999D;
                l[i1] 
*= 0.98999999999999999D;
                
if (Math.abs(Math.hypot(k[i1], l[i1])) < 2D) {
                    k[i1] 
= 0.0D;
                    l[i1] 
= 0.0D;
                }

            }


    }


    
public void pocket() {
        
for (int i1 = 0; i1 < countBall; i1++)
            
if (q[i1]) {
                
for (int j1 = 0; j1 < 3; j1++{
                    
for (int k1 = 0; k1 < 2; k1++)
                        
if (Math.hypot(e[j1] - i[i1], f[k1] - j[i1]) < _ball) {
                            q[i1] 
= false;
                            
if (i1 != 0{
                                h
--;
                            }

                            k[i1] 
= 0.0D;
                            l[i1] 
= 0.0D;
                        }


                }


            }


    }


    
public void play() {
        
for (int i1 = 0; i1 < countBall; i1++)
            
if (q[i1]) {
                
for (int j1 = i1 + 1; j1 < countBall; j1++{
                    
boolean flag;
                    
if (q[j1] && (flag = randball(i1, j1))) {
                        
for (int k1 = 0; k1 < 10 && flag; k1++{
                            m[i1] 
= (m[i1] + i[i1]) / 2D;
                            n[i1] 
= (n[i1] + j[i1]) / 2D;
                            m[j1] 
= (m[j1] + i[j1]) / 2D;
                            n[j1] 
= (n[j1] + j[j1]) / 2D;
                            flag 
= randball(i1, j1);
                        }


                        
if (flag) {
                            m[i1] 
= i[i1];
                            n[i1] 
= j[i1];
                            m[j1] 
= i[j1];
                            n[j1] 
= j[j1];
                        }

                        
double d1 = m[j1] - m[i1];
                        
double d2 = n[j1] - n[i1];
                        
double d3 = Math.hypot(m[i1] - m[j1], n[i1] - n[j1]);
                        
double d4 = d1 / d3;
                        
double d5 = d2 / d3;
                        o[j1] 
= k[j1] - k[j1] * d4 * d4;
                        o[j1] 
-= l[j1] * d4 * d5;
                        o[j1] 
+= k[i1] * d4 * d4;
                        o[j1] 
+= l[i1] * d4 * d5;
                        p[j1] 
= l[j1] - l[j1] * d5 * d5;
                        p[j1] 
-= k[j1] * d4 * d5;
                        p[j1] 
+= k[i1] * d4 * d5;
                        p[j1] 
+= l[i1] * d5 * d5;
                        o[i1] 
= k[i1] - k[i1] * d4 * d4;
                        o[i1] 
-= l[i1] * d4 * d5;
                        o[i1] 
+= k[j1] * d4 * d4;
                        o[i1] 
+= l[j1] * d4 * d5;
                        p[i1] 
= l[i1] - l[i1] * d5 * d5;
                        p[i1] 
-= k[i1] * d4 * d5;
                        p[i1] 
+= k[j1] * d4 * d5;
                        p[i1] 
+= l[j1] * d5 * d5;
                        k[i1] 
= o[i1];
                        l[i1] 
= p[i1];
                        k[j1] 
= o[j1];
                        l[j1] 
= p[j1];
                    }

                }


            }


    }


    
public boolean randball(int i1, int j1) {
        
// hypot随机决定两值之一
        return Math.hypot(m[i1] - m[j1], n[i1] - n[j1]) < 2D * r;
    }


    
/**
     * 限制区域
     * 
     
*/

    
public void limit() {
        
for (int i = 0; i < countBall; i++)
            
if (q[i]) {
                
if (m[i] - r < e[0]) {
                    m[i] 
= e[0+ r;
                    k[i] 
*= -1D;
                }
 else if (m[i] + r > e[2]) {
                    m[i] 
= e[2- r;
                    k[i] 
*= -1D;
                }

                
if (n[i] - r < f[0]) {
                    n[i] 
= f[0+ r;
                    l[i] 
*= -1D;
                }
 else if (n[i] + r > f[1]) {
                    n[i] 
= f[1- r;
                    l[i] 
*= -1D;
                }

            }


    }


    
public void makeScreen(Graphics screenGraphics) {

        screenGraphics.drawImage(_table, 
00null);
        
if (q[0]) {
            _graphics.setColor(Color.WHITE);
            _graphics.fillOval((
int) (i[0- r), (int) (j[0- r),
                    (
int) (r * 2D), (int) (r * 2D));
        }

        screenGraphics.setColor(Color.RED);
        
for (int i1 = 1; i1 < countBall; i1++)
            
if (q[i1])
                screenGraphics.fillOval((
int) (i[i1] - r), (int) (j[i1] - r),
                        (
int) (r * 2D), (int) (r * 2D));

        screenGraphics.setColor(Color.BLACK);
        
for (int j1 = 0; j1 < countBall; j1++)
            
if (q[j1]) {
                screenGraphics.drawOval((
int) (i[j1] - r), (int) (j[j1] - r),
                        (
int) (r * 2D), (int) (r * 2D));
            }


        
if (a == 1){
            makeHelper(screenGraphics);
        }

        
if (a == 0{
            
int k1 = getWidth() / 2 - 85;
            
int l1 = getHeight() / 2;
            screenGraphics.setColor(Color.BLACK);
            screenGraphics.drawString(
"点击画面开始", k1 + 2, l1 + 2);
            
if ((System.currentTimeMillis() / 1000L & 1L== 0L){
                screenGraphics.setColor(Color.YELLOW);
            }

            
else{
                screenGraphics.setColor(Color.CYAN);
            }

            screenGraphics.drawString(
"点击画面开始", k1, l1);
        }

    }


    
/**
     * 绘制球杆及辅助线
     * 
     * 
@param screenGraphics
     
*/

    
public void makeHelper(Graphics screenGraphics) {
        
double d1 = Math.hypot(i[0- (double) u, j[0- (double) v);
        
double d2 = ((double) u - i[0]) / d1;
        
double d3 = ((double) v - j[0]) / d1;
        
double d4 = y ? n() / 10D : 1.0D;
        
double d5 = i[0+ d2 * (r + d4);
        
double d6 = i[0+ d2 * (r + (double) z + d4);
        
double d7 = j[0+ d3 * (r + d4);
        
double d8 = j[0+ d3 * (r + (double) z + d4);
        screenGraphics.setColor(Color.ORANGE);
        screenGraphics.drawLine((
int) d5, (int) d7, (int) d6, (int) d8);
        
int i1 = 0;
        
int j1 = y ? (int) (150D * (d4 / 1000D)) : 15;
        
double d9;
        
double d10 = (d9 = 30D) * d2;
        
double d11 = d9 * d3;
        
double d12 = i[0+ (double) A * d2;
        
double d13 = j[0+ (double) A * d3;
        A
--;
        A 
%= d9;
        screenGraphics.setColor(Color.WHITE);
        
for (; i1 < j1; i1++{
            
if (d12 < e[0]) {
                d12 
= e[0- d12;
                d12 
= e[0+ d12;
                d10 
*= -1D;
            }
 else if (d12 > e[2]) {
                d12 
-= e[2];
                d12 
= e[2- d12;
                d10 
*= -1D;
            }

            
if (d13 < f[0]) {
                d13 
= f[0- d13;
                d13 
= f[0+ d13;
                d11 
*= -1D;
            }
 else if (d13 > f[1]) {
                d13 
-= f[1];
                d13 
= f[1- d13;
                d11 
*= -1D;
            }

            screenGraphics.fillOval((
int) d12 - 2, (int) d13 - 244);
            d12 
-= d10;
            d13 
-= d11;
        }


    }


    
public double n() {
        
if (y) {
            
return Math.min(1000D, 10D * Math.hypot(i[0- (double) w, j[0]
                    
- (double) x));
        }
 else {
            
return Math.min(1000D, 10D * Math.hypot(u - w, v - x));
        }

    }


    
public void update(Graphics g) {
        paint(g);
    }


    
public void paint(Graphics g) {
        makeScreen(_graphics);
        g.drawImage(_screen, 
00null);
    }


    
public void mousePressed(MouseEvent mouseevent) {
        y 
= true;
    }


    
public void mouseReleased(MouseEvent mouseevent) {
        
if (a == 1{
            
double d1 = Math.hypot(i[0- (double) u, j[0- (double) v);
            
double d2 = (i[0- (double) u) / d1;
            
double d3 = (j[0- (double) v) / d1;
            
double d4;
            
if ((d4 = n()) > 0.0D{
                a 
= 2;
                k[
0= d4 * d2;
                l[
0= d4 * d3;
            }

        }

        y 
= false;
    }


    
public void mouseClicked(MouseEvent mouseevent) {
        
if (a == 0)
            a 
= 1;
    }


    
public void mouseEntered(MouseEvent mouseevent) {
    }


    
public void mouseExited(MouseEvent mouseevent) {
    }


    
public void mouseMoved(MouseEvent mouseevent) {
        w 
= mouseevent.getX();
        x 
= mouseevent.getY();
        u 
= w;
        v 
= x;
    }


    
public void mouseDragged(MouseEvent mouseevent) {
        w 
= mouseevent.getX();
        x 
= mouseevent.getY();
    }


    
public static void main(String args[]) {
        
new JavaBilliards();
    }


}

链接地址:http://blog.csdn.net/cping1982/archive/2008/01/08/2030534.aspx