Java趣味小程序:打弹珠

    分享一个最近作的一个用swing作的小程序,相似于打砖块。单击开始,单击暂停,再次单击继续游戏,鼠标离开窗口暂停。鼠标移动控制挡板,小球落到挡板上反弹,落到底部生命值扣一,每击中一个成绩加一。初学者能够写一写,就当作一个小练习。java

    第一个类:窗口类,用JFrame画的窗口。小程序

import javax.swing.JFrame;

public class BallJframe {
	// 建立一个窗体对象
	JFrame frame = new JFrame();

	// 自定义方法为窗体设置属性
	public void init() {
		// 设置标题
		frame.setTitle("打弹珠");
		// 设置窗体大小、位置
		frame.setBounds(200, 100, 800, 600);
		// 设置默认关闭方式
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// 建立画布对象
		BallJpanel jp = new BallJpanel();
		// 将画布类对象添加到窗体中
		frame.add(jp);
		// 设置窗口可见
		frame.setVisible(true);

	}

	public static void main(String[] args) {
		BallJframe bf = new BallJframe();
		bf.init();
	}
}
    第二个类:面板类,用线程与鼠标监听器来实现功能。

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;


import javax.swing.JPanel;


public class BallJpanel extends JPanel implements MouseMotionListener,
		MouseListener {


	// 定义挡板的坐标
	static int dx = 200, dy = 550;
	//成绩
	static int score = 0;
	 //球速
	static int n=10;
	//生命值
	static int hp=n; 
	//游戏速度
	int speed = 5;
	//开始状态
	static final int START = 0;
	//运行状态
	static final int RUNNING = 1;
	//暂停状态
	static final int PASS = 2;
	//结束状态
	static final int OVER=3;
	//当前的运动状态
	int state = START;
	//建立List集合存储Ball类
	List<Ball> list = new ArrayList<Ball>();
	public BallJpanel() {
		// 添加小球类
		for(int i=0;i<hp;i++){
			Ball ball = new Ball();
			list.add(ball);
		}
		move();
		addMouseMotionListener(this);
		addMouseListener(this);
	}


	public void paint(Graphics g) {
		super.paint(g);
		//设置背景颜色
		setBackground(Color.black);
		//画出挡板
		g.setColor(Color.orange);
		g.fillRect(dx, dy, 100, 20);
		// 画出小球
		for(int i=0;i<list.size();i++){
			Ball ball = list.get(i);
			g.setColor(Color.white);
			g.fillOval(ball.getX(), ball.getY(), 2 * ball.getR(), 2 * ball.getR());
			
		}
		//在屏幕上显示成绩与生命值
		g.drawString("成绩:" + score, 20, 20);
		g.drawString("生命值:"+hp, 20, 40);
		//开始时重置成绩、生命值与速度,屏幕上显示游戏开始
		if(state==START){
			score=0;
			hp=n;
			speed=5;
			g.setColor(Color.red);
			g.setFont(new Font("微软雅黑",Font.PLAIN,40));
			g.drawString("游戏开始",300,250);
		}
		//暂停时屏幕上显示游戏暂停
		if(state==PASS){
			g.setColor(Color.red);
			g.setFont(new Font("微软雅黑",Font.PLAIN,40));
			g.drawString("游戏暂停",300,250);
		}
		//生命值为0时游戏结束,屏幕上显示游戏结束
		if(hp==0){
			state=OVER;
			g.setColor(Color.red);
			g.setFont(new Font("微软雅黑",Font.PLAIN,40));
			g.drawString("游戏结束",300,250);
		}
		//根据成绩调整速度
		if (score >= 40) {
			speed = 4;
		}
		if (score >= 60) {
			speed = 3;
		}
		if (score >= 80) {
			speed = 2;
		}
		if (score >= 100) {
			speed = 1;
		}
	}


	public void move() {
		new Thread() {
			public void run() {
				while (true) {
					//当运行时
					if (state == RUNNING) {
						for(int i=0;i<list.size();i++){
							Ball ball = list.get(i);
							// 调用ballMove方法让小球动起来
							ball.ballMove();
							ball.ballBorder();
							// 小球碰撞
							for(int j=i+1;j<list.size();j++){
								Ball ball2 = list.get(j);
								ball.ballCrash(ball2);
							}
						}
					} else if (state == START) {
						//开始时将挡板移到屏幕中间
						dx = 350;
					} else {
						//暂停
					}
					// 重绘
					repaint();
					try {
						Thread.sleep(speed);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}


	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub


	}


	@Override
	public void mouseMoved(MouseEvent e) {
		// TODO Auto-generated method stub
		//当运行时挡板跟着鼠标移动
		if (state == RUNNING) {
			dx = e.getX() - 100 / 2;
			if (dx <= 0) {
				dx = 0;
			}
			if (dx >= 800 - 116) {
				dx = 684;
			}
			repaint();
		}
	}


	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		//开始时单击鼠标运行 运行时单击鼠标暂停 暂停时单击鼠标运行
		if (state == START) {
			state = RUNNING;
		} else if (state == RUNNING) {
			state = PASS;
		} else if(state==PASS){
			state = RUNNING;
		}else if(state==OVER){
			state=START;
			//重置小球的坐标
			for(int i=0;i<list.size();i++){
				Ball ball = list.get(i);
				ball.reset();
			}
		}
	}


	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub


	}


	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub


	}


	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		//鼠标进入窗口暂停变运行
		if (state == PASS) {
			state = RUNNING;
		}
	}


	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		//鼠标离开窗口运行变暂停
		if (state == RUNNING) {
			state = PASS;
		}
	}
}


    第三个类:小球类,小球的坐标、半径、运动方向、移动、越界处理、碰撞检测及碰撞后的反弹。

public class Ball {
	// 定义小球的运动方向
	public static final int LEFT_UP = 0;
	public static final int LEFT_DOWN = 1;
	public static final int RIGHT_UP = 2;
	public static final int RIGHT_DOWN = 3;
	// 定义小球当前的运动方向
	private int f = LEFT_UP;
	// 定义小球的坐标
	private int x, y;
	// 定义小球的半径
	private int r;

	public Ball() {
		x = (int) (Math.random() * 800);
		y = (int) (Math.random() * 400);
		r = 10;
		int ran = (int) (Math.random() * 2);
		if (ran == 0) {
			f = LEFT_UP;
		} else if (ran == 1) {
			f = RIGHT_UP;
		}
	}

	public Ball(int x, int y, int r, int f) {
		super();
		this.x = x;
		this.y = y;
		this.r = r;
		this.f = f;
	}

	public int getF() {
		return f;
	}

	public void setF(int f) {
		this.f = f;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getR() {
		return r;
	}

	public void setR(int r) {
		this.r = r;
	}
	//小球移动
	public void ballMove() {
		if (f == LEFT_UP) {
			x--;
			y--;
		}
		if (f == LEFT_DOWN) {
			x--;
			y++;
		}
		if (f == RIGHT_UP) {
			x++;
			y--;
		}
		if (f == RIGHT_DOWN) {
			x++;
			y++;
		}
	}

	// 小球越界处理
	public void ballBorder() {
		if (y <= 0) {
			if (f == LEFT_UP) {
				f = LEFT_DOWN;
			}
			if (f == RIGHT_UP) {
				f = RIGHT_DOWN;
			}
		}
		if (x <= 0) {
			if (f == LEFT_UP) {
				f = RIGHT_UP;
			}
			if (f == LEFT_DOWN) {
				f = RIGHT_DOWN;
			}
		}
		// 小球碰到挡板
		if (y >= BallJpanel.dy - 2 * r) {
			if (x >= BallJpanel.dx && x <= BallJpanel.dx + 100) {
				if (f == LEFT_DOWN) {
					f = LEFT_UP;
				}
				if (f == RIGHT_DOWN) {
					f = RIGHT_UP;
				}
				y-=3;
				BallJpanel.score++;
			} else if (y == 600 - 2 * r - 40) {
				BallJpanel.hp--;
			} else if (y > 600 - 2 * r - 40) {
				x = 900;
				y = 900;
			}
		}
		if (x >= 800 - 2 * r - 15) {
			if (f == RIGHT_UP) {
				f = LEFT_UP;
			}
			if (f == RIGHT_DOWN) {
				f = LEFT_DOWN;
			}
		}
	}
	
	//小球碰撞检测
	public boolean isCrash(Ball ball){
		int lx = Math.abs(x+r-(ball.x+ball.r));
		int ly = Math.abs(y+r-(ball.y+ball.r));
		boolean h = lx<=(r+ball.r)&&ly<=(r+ball.r);
		return h;
	}
	
	//小球碰撞反弹
	public void ballCrash(Ball another) {
		if(isCrash(another)){
			x++;
y++;
int temp = this.f;
this.f = another.f;
another.f = temp;
		}
	}

	// 重置小球的位置
	public void reset() {
		x = (int) (Math.random() * 800);
		y = (int) (Math.random() * 500);
		int ran = (int) (Math.random() * 2);
		if (ran == 0) {
			f = LEFT_UP;
		} else if (ran == 1) {
			f = RIGHT_UP;
		}
	}
}