⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 billiardball.java

📁 java桌球游戏java桌球游戏java桌球游戏java桌球游戏
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		pTarget = new Point(51, 51);  // 先设为一个初始值.
		setCanFire(true);  // 设置fire 为true, 表示能发射
		addMouseMotionListener(new MouseMotionMonitor());
		addMouseListener(new MouseMonitor());
	}

	public void paint(Graphics g) {
		Color c = g.getColor();
		g.setColor(Color.GREEN);
		g.fillRect(0, 0, getSize().width - 1, getSize().height - 1);
		g.drawImage(table, 0, 0, null);
	//	mBall.draw(g);
		for ( int i = 0; i < balls.size(); i++ ) {
			balls.get(i).draw(g);
		}
		if ( isCanFire() == true && isCanPlace() == false ) {
			g.setColor(Color.PINK);
			g.drawLine((int)(mBall.x + 0.5), (int)(mBall.y + 0.5), pTarget.x, pTarget.y);
			g.fillOval(pTarget.x - 5, pTarget.y - 5, 10, 10);
		//	g.drawLine((int)(mBall.x + 1.5), (int)(mBall.y + 1.5), pTarget.x + 1, pTarget.y + 1);
		}	
		synchronized(this) {
			for ( int i = 0; i < flashs.size(); i++ ) {
				flashs.get(i).draw(g);
			}
			Iterator<Tnode> iter = flashs.iterator();
			while ( iter.hasNext() ) {
				Tnode item = iter.next();
				if ( item.isLive() == false )
					iter.remove();
			}
		}		

		g.setColor(c);
	}
	
	public boolean isState() {
		return state;
	}

	public void setState(boolean state) {
		this.state = state;
	}

	public boolean isCanFire() {
		return canFire;	
	}

	public void setCanFire(boolean fire) {
		canFire = fire;
	}

	public boolean isCanPlace() {
		return canPlace;
	}

	public void setCanPlace(boolean canPlace) {
		this.canPlace = canPlace;
	}

	public void initial() {
		mBall = new Ball();
		balls.add(mBall);
		for ( int i = 0; i < 10; i++ )
			balls.add(new Ball());
	}

	public void gameStart() {
		
		double rad = Math.sqrt(3.0) * 10.0;
		double ix = 450, iy = 150;
		int    index = 0;
		balls.get(0).setProperty(150, 150, Color.WHITE);
		balls.get(0).setLive(true);
		for ( int i = 0; i < 4; i++ ) {
			for ( int j = 0; j <= i; j++ ) {
				balls.get(++index).setProperty(ix + i * rad, iy + (j - i / 2.0) * 20, Color.RED);
				balls.get(index).setLive(true);
			}
		}
		setCanFire(true);
		setCanPlace(true);
		parent.initScore();
		synchronized(this) {
			flashs.clear();
		}

	}

	public void addFlash(Tnode item) {
		synchronized(this) {
			flashs.add(item);
		}		
	}

	public void move() {  //  主要负责运动的处理.
		// 把一个单位, 划分为很小时间片, 然后进行模拟. 碰撞, 就是这样的.

		int ctype = 0;
		int step = 0, record = 0, mstep;
		int number = 0, slice, request; //balls.size();
		Ball sb1 = null, sb2 = null;
		while ( step < SLICE ) {  // time limited
			mstep = SLICE - step;
			ctype = CWNULL;
			sb1 = sb2 = null;
			for ( int i = 0; i < balls.size(); i++ ) {
				Ball b1 = balls.get(i); 
				if ( b1.isLive() == false ) continue;
				slice = b1.collidesHole(TABLE_WIDTH - 1, TABLE_HEIGHT - 1);
				if ( mstep > slice ) {
					mstep = slice;
					ctype = CWHOLE;
					sb1 = b1;
				}
				for ( int j = i + 1; j < balls.size(); j++ ) {	
					Ball b2 = balls.get(j);
					if ( b2.isLive() == false ) continue;
					slice = b1.collides(b2);
					if ( mstep > slice ) {
						mstep = slice;
						ctype = CWBALL;   // 1 表示两球碰撞.
						sb1 = b1; sb2 = b2;					
					}
				}	
				slice = b1.collidesWall(TABLE_WIDTH - 1, TABLE_HEIGHT - 1);	
				if ( mstep > slice ) {
					mstep = slice;
					ctype = CWWALL;  // 2 表示球与墙壁发生碰撞.
					sb1 = b1;
				}
			}
			for ( int i = 0; i < balls.size(); i++ ) {
				if ( balls.get(i).isLive() == true )
					balls.get(i).update(mstep);	
			}

			if ( ctype == CWBALL ) {  
				sb1.changes(sb2);
				new Thread(new MusicThread("Collide.wav")).start();
			} else if ( ctype == CWWALL ) {
				sb1.changesWall(TABLE_WIDTH - 1, TABLE_HEIGHT - 1);
				new Thread(new MusicThread("CollideEdge.wav")).start();
			} else if ( ctype == CWHOLE ) {
				Point tp = sb1.changesHole(TABLE_WIDTH - 1, TABLE_HEIGHT - 1);
				addFlash(new Tnode(tp.x, tp.y));
				if ( sb1 != mBall ) {
					parent.addScore();
				}
				new Thread(new Mp3Encode("sounds/Pocket.wav")).start();
			}	
			step += mstep;		
		}
		int counter = 0;		
		for ( int i = 0; i < balls.size(); i++ ) {
			if ( balls.get(i).isStayed() == true || balls.get(i).isLive() == false )
				counter++;
		}
		if ( counter == balls.size() ) {
			if ( isCanFire() == false )
			       	parent.initialPower();
			setCanFire(true);
			if ( balls.get(0).isLive() == false ) {
				balls.get(0).setData(150, 150, 0, 0); // bug still exsit. 可能存在重叠
				balls.get(0).setLive(true);
				setCanPlace(true);
			}
		}


	}

	public boolean judge() {
		Ball b1 = balls.get(0);
		for ( int i = 1; i < balls.size(); i++ ) {
			Ball b2 = balls.get(i);
			if ( b1.isTouched(b1.x, b1.y, b2.x, b2.y) == true )
				return false;
		}	
		if ( b1.y <= Ball.OFFSET + b1.radian || b1.y >= TABLE_HEIGHT - Ball.OFFSET - b1.radian )
			return false;
		return true;
	}

	private class MouseMotionMonitor extends MouseMotionAdapter {
		
		public void mouseDragged(MouseEvent e) {
			if ( isCanFire() == true ) {
				pTarget = e.getPoint();
			}
			if ( isCanPlace() == true ) {
				balls.get(0).x = 150;
				balls.get(0).y = e.getPoint().y;
			}
		}

		public void mouseMoved(MouseEvent e) {
			if ( isCanFire() == true ) {
				pTarget = e.getPoint();
			}
			if ( isCanPlace() == true ) {
				
				balls.get(0).x = 150;
				
				balls.get(0).y = e.getPoint().y;
			}
		}

	}

	private class MouseMonitor extends MouseAdapter {  // 这边涉及一个同步问题.
		public PowerChooser chooser = null;
		public void mousePressed(MouseEvent e) {	
			if ( e.getButton() == MouseEvent.BUTTON1 && isCanFire() == true && isCanPlace() == false ) {	
				chooser = new PowerChooser();
				chooser.start();
			}
		}
		
		public void mouseReleased(MouseEvent e) {
			if ( e.getButton() == MouseEvent.BUTTON1 && isCanFire() == true ) {
				if ( isCanPlace() == false ) {
					setCanFire(false);
					mBall.setData(parent.getPower(), e.getPoint());	
					chooser.setLive(false);
				} else if ( judge() == true ) {
					setCanPlace(false);
				}
			}
		}

	}
	
	private class Tnode {
		
		public int x, y;
		public int index = 0;
		public Tnode(int x, int y) {
			this.x = x; 
			this.y = y;
		}

		public void draw(Graphics g) { // 0 1 2 3 2 1 0
			BufferedImage image = null;
			if ( index <= 3 )
				image = ImageLoader.getHitedImage(index);			
			else 
				image = ImageLoader.getHitedImage(6 - index);
			g.drawImage(image, x - image.getWidth() / 2, y - image.getHeight() / 2, null);
			index++;
		}	
		
		public boolean isLive() {
			 return index <= 6;
		}


	}	

	private class PowerChooser extends Thread {
		public boolean live = true;
		public void setLive(boolean live) {
			this.live = live;
		}
		public void run() {
			parent.initialPower();
			while ( live == true ) {
				try {
					Thread.sleep(80);
					parent.updatePower();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}	
		}
	}


}

// 使用一个隐藏组件, 来回避JProcessBar 这个高级Swing组件的model问题;
class ProcessPanel extends JPanel {

	public static final int PROCESS_WIDTH  = 600;
	public static final int PROCESS_HEIGHT = 50;
	public JLabel lblScore = null;
	public JLabel lblPower = null;
	public JTextField tfScore = null;
	public JButton btnStart = null;

	private int prec = 0;
	private int changedUnit = 2;

	public ProcessPanel() {

		lblScore = new JLabel("得分");
		lblPower = new JLabel("力量条");
		tfScore = new JTextField("0", 5);
		tfScore.setEditable(false);
		btnStart = new JButton("开始");
		deploy();
	}

	public void deploy() {
		setSize(PROCESS_WIDTH, PROCESS_HEIGHT);		
		setLayout(null);
		lblScore.setBounds(50, 10, 60, 30);
		tfScore.setBounds(120, 10, 60, 30);
		btnStart.setBounds(200, 10, 60, 30);
		lblPower.setBounds(300, 10, 60, 30);		
		add(lblScore);
		add(lblPower);
		add(btnStart);
		add(tfScore);
	}

	public void paint(Graphics g) {
		super.paint(g);
		Color c = g.getColor();
		g.setColor(Color.PINK);
		g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);	
		g.drawRect(360, 10, 200, 30);
		g.setColor(Color.LIGHT_GRAY);
		g.fillRect(360, 10, 200 * (prec - 10) / 90, 30);
		g.setColor(c);
	}
	
	public int getPower() {
		return prec;
	}

	public synchronized void initialPower() {
		prec = 10;
		changedUnit = 2;
	}

	public synchronized void updatePower() {
		if ( prec >= 100 ) {
			changedUnit = -2;
		} else if ( prec <= 2 ) {
			changedUnit = 2;
		}
		prec += changedUnit;
	}

	public void addStartActionListener(ActionListener act) {
		btnStart.addActionListener(act);
	}

	public void addScore() {
		int value = Integer.parseInt(tfScore.getText());
		tfScore.setText(new Integer(value + 1).toString());
	}
 
	public void initScore() {
		tfScore.setText("0");
	}

}

// singleton pattern

class ImageLoader {
	
	public static final int NPICTURE = 18;
	public static final int NFLASH = 4;
	public static BufferedImage[] images = new BufferedImage[NPICTURE];
	public static BufferedImage   cursor = null;
	public static BufferedImage   background = null;
	public static BufferedImage[]   flashs = new BufferedImage[NFLASH];

	public synchronized static BufferedImage getIndexOf(int index) {  // check index, judge whether index skip the range;
		if ( images[index] == null ) {
			URLClassLoader loader = (URLClassLoader)ImageLoader.class.getClassLoader();
			URL url = loader.findResource("images/" + index + ".png");
			try {
				images[index] = ImageIO.read(url);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return images[index];
	}

	public synchronized static BufferedImage getCursor() {
		if ( cursor == null ) {
			URLClassLoader loader = (URLClassLoader)ImageLoader.class.getClassLoader();
			URL url = loader.findResource("images/cursor.gif");
			try {
				cursor = ImageIO.read(url);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return cursor;
	}

	public synchronized static BufferedImage getBackground() {
		if ( background == null ) {
			URLClassLoader loader = (URLClassLoader)ImageLoader.class.getClassLoader();
			URL url = loader.findResource("images/table.png");
			try {
				background = ImageIO.read(url);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return background;
	}	

	public synchronized static BufferedImage getHitedImage(int index) {
		if ( flashs[index] == null ) {
			URLClassLoader loader = (URLClassLoader)ImageLoader.class.getClassLoader();
			URL url = loader.findResource("images/" + index + ".gif");
			try {
				flashs[index] = ImageIO.read(url);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return flashs[index];
	}

}

// 显然, 用AudioClip 也可以来播放wav格式的文件
// Applet 中定义的AudioClip: getAudioClip();

class MusicThread implements Runnable {
	
	public AudioClip clip = null;
	public String filename = null;

	public MusicThread(String filename) {
		this.filename = filename;
	}
	public void run() {
		try {
			URLClassLoader loader = (URLClassLoader)getClass().getClassLoader();
			URL url = loader.findResource("sounds/" + filename);
			clip = Applet.newAudioClip(url);  // newAudioClip(url) 与 getAudioClip() 的区别是,一个是静态另一个是成员函数.
			clip.play();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

//  知识点: (1) 函数mouseMoved(MouseEvent e) 和mouseDragged(MouseEvent e) 两者都监控鼠标的移动, 但是, 前者为无按键按下时,
//  而后者则是按下某个组件时进行跟踪.
//  在监视mouseDragged(MouseEvent e) {} 这个函数时, 要用到MouseMotionAdapter类, 
//  因为mouseAdapter() 中可能不发送mouseDragged事件, 这与具体的实现有关.


// Thread ---> java.lang.Thread;

// (1)先搭框架.
// (2)先完成, 球碰台球桌面, 的碰撞检测, 以及碰撞反应.
// (3)简单的两个球的碰撞, 以及多个球的碰撞.
//
// (4) 安置力量条: 
// (5) 对碰撞的时候, 添加背景音乐.

// 今天的任务: 完成
// 给球贴上图.(option: 制作球滚动的效果).

// 书写 碰撞的原理 + 实现碰撞的过程.
//
//
// 对Timer类的认识, Timer在java中, 很有多种定义. 在不同的包中
// 我们一般用java.util.timer;
// timer.schedule(task, delay, interval);
//
// 撑到800行吧
//
//
//
// today task:
// (1) 球进洞, + 显示进球的洞, 制作动画效果  \/
// (2) 对力量条的选择, 应该更加主动.  \/
// (3) 白球进洞后, 位置的重新选择.    \/
// (4) 开始, 即重新开始              \/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -