Java趣味编程实例:模拟桌球打击处理与绘制

精贴 置顶
1419 0

  由于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;
  /** *//**
  * Title: LoonFramework
  *
  * * Description:Java桌球演示
  *
  *
  * Copyright: Copyright (c) 2007
  *
  *
  * Company: LoonFramework
  *
  *
  * @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(50, 50, 700, 350);
  Frame frame = new Frame("Java桌球演示");
  frame.add(this);
  frame.setBounds(0, 0, 700, 380);
  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(0, 0, getWidth(), getHeight());
  g.setColor((new Color(200, 100, 50)).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) - 2, 4, 4);
  g.drawArc((int) ((1.0D * (e[2] - e[0])) / 3D) - 20,
  (int) ((f[1] + f[0]) / 2D) - 20, 40, 40, 90, 180);
  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, 0, 0, null);
  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 - 2, 4, 4);
  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, 0, 0, null);
  }
  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();
  }
  }

  • 没有任何评论
今日天气 ···

···

···

···

热门排行
CSS cursor鼠标样式一览表 2012-06-25
.NET后台写JS代码 2011-11-03
网站地址多出jdfwkey的问题解析及... 2010-08-25
数据库xxx的日志已满,请备份该数... 2013-07-19
百度、google、Yahoo网站地图制作... 2011-01-30
<a>标签的伪类书写顺序问题... 2010-09-04
什么是长尾关键词? 2010-09-24
CEO名言 2010-08-31
Mysql 主从数据库同步 2010-09-12
用ASP实现网页BBS 2010-11-01
博主推荐
本个人博客微信公众平台上线啦~~... 2013-10-13
饼哥网络互联上线啦~~要买域名空... 2013-09-20
网站title标题如何正确修改不会被... 2013-08-26
饼哥通讯录系统上线啦,欢迎大家... 2013-08-24
ASP .NET MYSQL 的简单分页 并不... 2013-08-19
网站有弹窗广告这样的站点,百度... 2013-08-17
做淘宝SEO优化需要注意的8大问题 2013-08-17
淘宝网怎么做SEO优化 2013-08-17
站长们要学习的“苍井空精神” 2013-08-17
苹果公司今日发布了iOS 7第五个开... 2013-08-07
随便看看
趣味编程:请MM吃饭之工厂模式实... 2013-06-26
Access注入语句大全 2010-12-07
DBNull与Null的区别 2010-12-06
软件革命第二步:转向云计算 2013-09-29
在ASP中限制同一表单被多次提交 2010-10-26
关键词怎么确定? 2010-09-19
跳出率、退出率 2010-10-02
我们为什么要学习Java:Java的八... 2013-06-26
win7系统局域网共享设置解决方案 2013-07-29
Eclipse快捷键大全 2010-08-31
RSS新闻
传媒新闻
CSDN
八卦新闻
女性新闻
台湾新闻
互联网
军事-新浪博客
IT-新浪博客
汽车新闻
游戏新闻
国际新闻
国内新闻
体育新闻
我的微博
北京 上海 杭州 深圳 广州 成都