📄 billiardball.java
字号:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import java.applet.*;
import java.util.Timer;
public class BilliardBall extends JFrame {
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
public Image offScreenImage = null;
public Graphics bg = null;
public TablePanel pTable = null;
public ProcessPanel pInfo = null;
public BilliardBall() {
pInfo = new ProcessPanel();
pTable = new TablePanel(this); // 暂时, 就这么设为.
}
public void launchFrame() {
setTitle("台球游戏");
setSize(GAME_WIDTH, GAME_HEIGHT);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setLayout(null);
pTable.setBounds(100, 50, pTable.TABLE_WIDTH, pTable.TABLE_HEIGHT);
add(pTable);
pInfo.setBounds(100, 400, pInfo.PROCESS_WIDTH, pInfo.PROCESS_HEIGHT);
add(pInfo);
pInfo.addStartActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pTable.gameStart();
}
});
setResizable(false);
setVisible(true);
new PaintThread().start();
}
public void update(Graphics g) {
if ( offScreenImage == null ) {
offScreenImage = createImage(GAME_WIDTH, GAME_HEIGHT);
}
bg = offScreenImage.getGraphics();
Color c = bg.getColor();
bg.setColor(Color.WHITE);
bg.fillRect(0, 0, GAME_WIDTH - 1, GAME_HEIGHT - 1);
paint(bg);
bg.setColor(c);
g.drawImage(offScreenImage, 0, 0, null);
}
public void paint(Graphics g) {
super.paint(g);
Color c = g.getColor();
// add code here: to draw many ball with movement;
g.setColor(c);
}
public int getPower() {
return pInfo.getPower();
}
//change
public void initialPower() {
pInfo.initialPower();
}
public void updatePower() {
pInfo.updatePower();
}
public void addScore() {
pInfo.addScore();
}
public void initScore() {
pInfo.initScore();
}
public static void main(String[] args) {
new BilliardBall().launchFrame();
}
private class PaintThread extends Thread {
public static final int INTERVAL = 80;
public void run() {
while ( true ) {
try {
Thread.sleep(INTERVAL); //
pTable.move();
update(getGraphics()); // 当然 repaint() 这个函数也是行的.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
// 就一个球而言, 其应该储存什么信息?
class Ball { // 封装信息: ball之间.
public static final double EPS = 0.01;
public static final int SLICE = 45;
public static final int OFFSET = 16;
public static final double PROBABILITY = 2.0;
public Color color = null;
public double x, y, radian;
public double vx, vy; // 这里的vx, vy 表示运动矢量.
public BufferedImage picture = null;
public boolean live = false;
public Ball() {
// x = y = 50;
// vx = vy = 0;
live = true;
setData(150, 150, 0, 0);
radian = 10;
color = Color.WHITE;
picture = ImageLoader.getIndexOf(0);
}
public Ball(double x, double y, Color color) {
live = true;
setData(x, y, 0, 0);
radian = 10;
this.color = color;
if ( color != Color.WHITE ) {
picture = ImageLoader.getIndexOf(1);
}
}
public void draw(Graphics g) {
if ( isLive() == true ) {
Color c = g.getColor();
g.setColor(color);
//g.fillOval((int)(x - radian + 0.5), (int)(y - radian + 0.5), (int)(radian * 2 + 0.5), (int)(radian * 2 + 0.5));
g.drawImage(picture, (int)(x - radian + 0.5), (int)(y - radian + 0.5), null);
g.setColor(c);
}
}
public boolean isHited(Point p) { // 这个是正方形包含,
// if ( p.x == x && p.y == y ) return false;
return (p.x >= x - radian && p.x <= x + radian && p.y >= y - radian && p.y <= y + radian);
}
public void setData(double x, double y, double vx, double vy) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
}
public void setData(int value, Point p) {
double spring = Math.sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y));
// System.out.println("Spring:" + spring);
vx = (p.x - x) / spring * value * 25;
vy = (p.y - y) / spring * value * 25;
// System.out.println("vx:" + vx + " vy: " + vy);
}
public void setProperty(double x, double y, Color c) {
this.x = x;
this.y = y;
this.color = c;
vx = vy = 0;
if ( color != Color.WHITE )
picture = ImageLoader.getIndexOf(1);
else
picture = ImageLoader.getIndexOf(0);
}
// 恐怕 这里的速度需要测试出来.
public void forward() {
}
public boolean isStayed() {
if ( Math.abs(vx) <= EPS && Math.abs(vy) <= EPS ) {
vx = vy = 0;
return true;
}
return false;
}
public boolean isTouched(double x1, double y1, double x2, double y2) {
double dist = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
return dist < 2 * radian;
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
public int collides(Ball s) {
int step = 1;
double px, py, nx, ny;
double tx1, ty1, cx1, cy1;
double tx2, ty2, cx2, cy2;
if ( isStayed() == true && s.isStayed() == true )
return SLICE;
if ( isStayed() == true ) {
px = py = 0;
} else {
px = vx / Math.sqrt(vx * vx + vy * vy);
py = vy / Math.sqrt(vx * vx + vy * vy);
}
if ( s.isStayed() == true ) {
nx = 0; ny = 0;
} else {
nx = s.vx / Math.sqrt(s.vx * s.vx + s.vy * s.vy);
ny = s.vy / Math.sqrt(s.vx * s.vx + s.vy * s.vy);
}
//tx = mBall.vx - (mBall.vx * (mstep - step) / spring);
while ( step < SLICE ) {
tx1 = vx - step * px;
ty1 = vy - step * py;
if ( (tx1 > 0 && vx < 0) || (tx1 < 0 && vx > 0) ) tx1 = 0.0;
if ( (ty1 > 0 && vy < 0) || (ty1 < 0 && vy > 0) ) ty1 = 0.0;
cx1 = x + step * (vx + tx1) / 2000.0;
cy1 = y + step * (vy + ty1) / 2000.0;
tx2 = s.vx - step * nx;
ty2 = s.vy - step * ny;
if ( (tx2 > 0 && vx < 0) || (tx2 < 0 && vx > 0) ) tx2 = 0.0;
if ( (ty2 > 0 && vy < 0) || (ty2 < 0 && vy > 0) ) ty2 = 0.0;
cx2 = s.x + step * (s.vx + tx2) / 2000.0;
cy2 = s.y + step * (s.vy + ty2) / 2000.0;
if ( isTouched(cx1, cy1, cx2, cy2) == true ) break; // 表接触
step++;
}
return step;
}
public int collidesWall(int width, int height) {
int step = 1;
double px = 0, py = 0, tx = 0, ty = 0, cx = 0, cy = 0;
if ( isStayed() == true ) return SLICE;
px = vx / Math.sqrt(vx * vx + vy * vy);
py = vy / Math.sqrt(vx * vx + vy * vy);
while ( step < SLICE ) {
tx = vx - step * px;
ty = vy - step * py;
if ( (tx > 0 && vx < 0) || (tx < 0 && vx > 0) ) tx = 0.0;
if ( (ty > 0 && vy < 0) || (ty < 0 && vy > 0) ) ty = 0.0;
cx = x + step * (vx + tx) / 2000.0;
cy = y + step * (vy + ty) / 2000.0;
if ( cx - radian <= 0 + OFFSET || cx + radian >= width - OFFSET
|| cy - radian <= 0 + OFFSET || cy + radian >= height - OFFSET ) {
if ( isSpecial(cx, cy, width, height) == false ) break;
}
step++;
}
return step;
}
public boolean isSpecial(double cx, double cy, int width, int height) { // 增强真实感,(1) 进洞.
double r1 = OFFSET, r2 = (width - 2 * OFFSET) / 2;
for ( int i = 0; i < 3; i++ ) {
if ( Math.sqrt((cx - r2 * i - OFFSET) * (cx - r2 * i - OFFSET) + (cy - r1) * (cy - r1)) < radian * PROBABILITY )
return true;
}
r1 = height - OFFSET;
for ( int i = 0; i < 3; i++ ) {
if ( Math.sqrt((cx - r2 * i - OFFSET) * (cx - r2 * i - OFFSET) + (cy - r1) * (cy - r1)) < radian * PROBABILITY )
return true;
}
return false;
}
public int collidesHole(int width, int height) {
int step = 1;
double px = 0, py = 0;
double tx = 0, ty = 0;
double cx = 0, cy = 0;
double r1 = 0, r2 = 0;
if ( isStayed() == true ) return SLICE;
px = vx / Math.sqrt(vx * vx + vy * vy);
py = vy / Math.sqrt(vx * vx + vy * vy);
while ( step < SLICE ) {
tx = vx - step * px;
ty = vy - step * py;
if ( (tx > 0 && vx < 0) || (tx < 0 && vx > 0) ) tx = 0.0;
if ( (ty > 0 && vy < 0) || (ty < 0 && vy > 0) ) ty = 0.0;
cx = x + step * (vx + tx) / 2000.0;
cy = y + step * (vy + ty) / 2000.0;
r1 = OFFSET; r2 = (width - 2 * OFFSET) / 2;
for ( int i = 0; i < 3; i++ ) {
// double tvalue = Math.sqrt((cx - r2 * i) * (cx - r2 * i) + (cy - r1) * (cy - r1));
// System.out.println("tvalue :" + tvalue + ":radian2" + (radian * 2));
if ( Math.sqrt((cx - r2 * i - OFFSET) * (cx - r2 * i - OFFSET) + (cy - r1) * (cy - r1)) < radian * PROBABILITY )
return step;
}
r1 = height - OFFSET;
for ( int i = 0; i < 3; i++ ) {
// double tvalue = Math.sqrt((cx - r2 * i) * (cx - r2 * i) + (cy - r1) * (cy - r1));
// System.out.println("tvalue :" + tvalue + ":radian2" + (radian * 2));
if ( Math.sqrt((cx - r2 * i - OFFSET) * (cx - r2 * i - OFFSET) + (cy - r1) * (cy - r1)) < radian * PROBABILITY )
return step;
}
step++;
}
return step;
}
public void update(int step) {
double px = 0, py = 0;
double tx, ty, cx, cy;
if ( isStayed() == true ) {
px = py = 0;
} else {
px = vx / Math.sqrt(vx * vx + vy * vy);
py = vy / Math.sqrt(vx * vx + vy * vy);
}
tx = vx - step * px;
ty = vy - step * py;
if ( (tx > 0 && vx < 0) || (tx < 0 && vx > 0) ) tx = 0.0;
if ( (ty > 0 && vy < 0) || (ty < 0 && vy > 0) ) ty = 0.0;
cx = x + step * (vx + tx) / 2000.0;
cy = y + step * (vy + ty) / 2000.0;
setData(cx, cy, tx, ty);
}
public void changes(Ball s) { // 这个函数, 则是碰撞反应的核心, 最重要的要防止粘滞住...
double px, py;
double ux1, uy1, ux2, uy2;
double ux3, uy3, ux4, uy4;
px = (s.x - x) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y)); // 这边是单位化
py = (s.y - y) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y));
ux1 = (px * vx + py * vy) * px;
uy1 = (px * vx + py * vy) * py;
ux2 = vx - ux1;
uy2 = vy - uy1;
ux3 = px * (px * s.vx + py * s.vy);
uy3 = py * (py * s.vx + py * s.vy);
ux4 = s.vx - ux3;
uy4 = s.vy - uy3;
vx = ux2 + ux3;
vy = uy2 + uy3;
s.vx = ux1 + ux4;
s.vy = uy1 + uy4;
// 还要恰当改变两球之间的距离.
int step = 1;
while ( true ) {
x = x + step * vx / 1000.0;
y = y + step * vy / 1000.0;
s.x = s.x + step * s.vx / 1000.0;
s.y = s.y + step * s.vy / 1000.0;
if ( isTouched(x, y, s.x, s.y) == false ) break;
if ( isStayed() == true && s.isStayed() == true && isTouched(x, y, s.x, s.y) == true ) { // 潜在的一个死循环.
double p1 = (x - s.x) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y));
double p2 = (y - s.y) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y));
double p3 = (s.x - x) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y));
double p4 = (s.y - y) / Math.sqrt((s.x - x) * (s.x - x) + (s.y - y) * (s.y - y));
step = 1;
// System.out.println("I frame myself");
while ( true ) {
x = x + step * p1 / 200;
y = y + step * p2 / 200;
s.x = s.x + step * p3 / 200;
s.y = s.y + step * p4 / 200;
if ( isTouched(x, y, s.x, s.y) == false ) return;
step++;
}
}
step++;
}
}
public void changesWall(int width, int height) {
if ( x - radian <= 0 + OFFSET ) {
x = radian + OFFSET;
vx = -vx;
} else if ( x + radian >= width - OFFSET ) {
x = width - radian - OFFSET;
vx = -vx;
}
if ( y - radian <= 0 + OFFSET ) {
y = radian + OFFSET;
vy = -vy;
} else if ( y + radian >= height - radian - OFFSET ) {
y = height - radian - OFFSET;
vy = -vy;
}
}
public Point changesHole(int width, int height) { // 制作消失效果.
double r1, r2;
setLive(false);
r1 = OFFSET; r2 = (width - 2 * OFFSET) / 2;
for ( int i = 0; i < 3; i++ ) {
if ( Math.sqrt((x - r2 * i - OFFSET) * (x - r2 * i - OFFSET) + (y - r1) * (y - r1)) < radian * PROBABILITY )
return new Point((int)(r2 * i + OFFSET), (int)(r1));
}
r1 = height - OFFSET;
for ( int i = 0; i < 3; i++ ) {
if ( Math.sqrt((x - r2 * i - OFFSET) * (x - r2 * i - OFFSET) + (y - r1) * (y - r1)) < radian * PROBABILITY )
return new Point((int)(r2 * i + OFFSET), (int)(r1));
}
return new Point(-100, -100); // 若程序执行到这里,表明程序执行错误.
}
public String toString() { // 这个toString() 用于调试用的.
return "x: " + x + " y: " + y + " vx " + vx + " vy " + vy;
}
// public boolean is
//public synchronized ()
// 当然也可以重载.
// return . Math.sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y)) <= radian ;
// return (p.x - x) * (p.x - x) + (p.y - y) * (p.y - y) <= radian *radian;
}
class TablePanel extends JPanel {
public static final int TABLE_WIDTH = 600;
public static final int TABLE_HEIGHT = 300;
public static final int SLICE = 45;
public static final int CWNULL = 0; // 表没有碰撞的情况
public static final int CWBALL = 1; // 与球相碰
public static final int CWWALL = 2; // 与wall相碰
public static final int CWHOLE = 3; // 落入hole中
// public MouseMonitor mouseManager = null;
public Point pTarget;
public Ball mBall;
public boolean state = false;
public boolean canFire = false;
public boolean canPlace = true;
public ArrayList<Ball> balls = null;
public ArrayList<Tnode> flashs = null;
public BufferedImage table = null;
public BilliardBall parent = null;
public TablePanel(BilliardBall parent) {
this.parent = parent;
table = ImageLoader.getBackground();
balls = new ArrayList<Ball>();
flashs = new ArrayList<Tnode>();
initial();
gameStart();
// balls.add(new Ball()); // 对Ball的构造函数进行修改.
setSize(TABLE_WIDTH, TABLE_HEIGHT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -