代码详解,已经将java包导出,请在下面下载,如果你的机器上装有javaJDK直接点击运行即可
该游戏实现一下功能:
1、时间进度条,控制每局游戏在100s之内
2、显示剩余时间
3、实现鼠标监听器,使得控制小球能够跟随鼠标的移动而移动
4、设置有“开始”、“再来一次”、“暂停”、“继续”命令按钮
5、拥有一个得分文本框,和一个关数文本框
游戏特色:
1、当鼠标移动小球碰到黄色小球时,游戏窗口会出现炫目的闪屏效果
2、小球会越来越大
3、鼠标左右键可控制游戏的暂停与继续,不过让游戏者可以投机了
游戏规则:
留着自己探索吧,呵呵,规则比较简单
以下就是程序的代码详解:(也可从下面下载)
第1个类:
package MakeHerBigger;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestMain extends JFrame implements java.awt.event.MouseListener {
// 定义声明定义命令面板
private JPanel jp_command = new JPanel();
// 声明定义一个记录剩余时间,游戏进度的面板
private JPanel jp_progress = new JPanel();
// 声明定义tbk对象
private tanBallKinds tbk;
// private int x, y;
private paintBoard paintboard = new paintBoard();
// 初始化时的得分
public int score = 0;
// 初始化时的关数值
public int guan = 1;
// 初始化时的剩余时间数
public int time = 100;
// 静态变量,用来控制游戏的开始或重新来一次,和暂停与继续
public static boolean startOrstop = false;
public static boolean isContinue = true;
// 开始按钮
public javax.swing.JButton jb_start = new javax.swing.JButton("开始");
// 暂停按钮
public javax.swing.JButton jb_pause = new javax.swing.JButton("暂停");
// 得分标签
private javax.swing.JLabel jl_score = new javax.swing.JLabel("得分:");
// 得分显示文本框
public javax.swing.JTextField jt_score = new javax.swing.JTextField(5);
// 关数标签
private javax.swing.JLabel jl_guan = new javax.swing.JLabel("关数:");
// 显示关数文本框
public javax.swing.JTextField jt_guan = new javax.swing.JTextField(5);
// 剩余时间标签
public javax.swing.JLabel jl_time = new javax.swing.JLabel("剩余时间:");
// 显示剩余时间文本框
public javax.swing.JTextField jt_time = new javax.swing.JTextField(5);
// 剩余时间进度条
public javax.swing.JProgressBar jprogress = new javax.swing.JProgressBar();
public void init() {
// 窗口标题
this.setTitle("是男人就把它搞大");
// 初始化窗口大小
this.setSize(700, 700);
// 初始化窗口显示位置
this.setLocation(200, 25);
// 添加管理器——边界管理器
this.getContentPane().setLayout(new BorderLayout());
// 将组件添加到命令面板,显示在窗口下方的组件
jp_command.add(jb_start);
jp_command.add(jl_score);
jp_command.add(jt_score);
jp_command.add(jl_guan);
jp_command.add(jt_guan);
jp_command.add(jb_pause);
jp_command.setBackground(Color.pink);
// 将组件添加到进度面板,显示在窗口上方的组件
jp_progress.add(jl_time);
jp_progress.add(jprogress);
jp_progress.add(jt_time);
// 初始化文本框中显示的文字
jt_score.setText(score + "分");
jt_guan.setText("第" + guan + "关");
jt_time.setText(time + "S");
// 进度面板的背景色
jp_progress.setBackground(Color.pink);
// 进度条的前景色
jprogress.setForeground(Color.yellow);
// 进度条的背景色
jprogress.setBackground(Color.black);
jprogress.setValue(time);
// 启动剩余时间计时线程
timeCount timecount = new timeCount(this, paintboard);
timecount.start();
// 启动当鼠标移动小球碰到黄色小球时用来改变背景颜色实现闪屏的线程
backGroundColorChange colorChange = new backGroundColorChange(this,
paintboard);
colorChange.start();
// //
// 为开始按钮添加监听器
jb_start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if (str.equals("开始")) {
tbk.startPlay();
jb_start.setText("重来一次");
}
if (str.equals("重来一次")) {
tbk.stopPlay();
}
}
});
// 为暂停或继续按钮添加监听器
jb_pause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if (jb_start.getText().equals("重来一次")) {
if (str.equals("暂停")) {
tbk.pause();
jb_pause.setText("继续");
}
}
if (str.equals("继续")) {
tbk.continueAgain();
jb_pause.setText("暂停");
}
}
});
// //
// 将剩余时间记录面板放置到窗体的上方
this.getContentPane().add(jp_progress, BorderLayout.NORTH);
// 将花对象放到窗体的中间位置
this.getContentPane().add(paintboard, BorderLayout.CENTER);
// 将命令面板放到窗口的上方
this.getContentPane().add(jp_command, BorderLayout.SOUTH);
// 设置窗体可见性
this.setVisible(true);
// 设置程序默认关闭状态
this.setDefaultCloseOperation(3);
paintboard.addMouseListener(this);
// 启动小球线程
tbk = new tanBallKinds(paintboard, this);
tbk.start();
}
// 程序的入口函数
public static void main(String args[]) {
TestMain testmain = new TestMain();
testmain.init();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
// 当单击鼠标右键时,实现游戏暂停,前提是游戏还没有开始
if (e.getButton() == 3) {
if (jb_start.getText().equals("重来一次")) {
if (jb_pause.getText().equals("暂停")) {
// 调用暂停功能方法
tbk.pause();
// 将按钮的文字设为继续
jb_pause.setText("继续");
}
}
}
// 当单击鼠标左键时,实现游戏的继续
if (e.getButton() == 1) {
if (jb_pause.getText().equals("继续")) {
// 调用继续功能方法
tbk.continueAgain();
// 将按钮的文字设为暂停
jb_pause.setText("暂停");
}
}
}
public void mouseReleased(MouseEvent e) {
}
}
第2个类:
package MakeHerBigger;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class paintBoard extends Canvas implements MouseMotionListener {
//
private int NUMBER_OF_BALL = 30;
// 初始化鼠标移动小球的位置,即游戏窗体刚打开时小球的位置
public int x = 250, y = 680;
private int rectWidth = 50, rectHeight = 20;
public ballProperties[] ballproperties = new ballProperties[NUMBER_OF_BALL];
public static Color backGroundColor = Color.black;
// 初始化跟随鼠标移动的小球的大小
public static int mouseBallSize = 20;
// public void setBallProperties(ballProperties[] ballproperties){
// this.ballproperties=ballproperties;
// }
public paintBoard() {
// 添加鼠标监听器,用来控制鼠标移动小球能跟随鼠标移动
this.addMouseMotionListener(this);
// 初始化每个小球的属性,防止小球属性数组出现空指针
for (int i = 0; i < NUMBER_OF_BALL; i++) {
ballProperties b = new ballProperties();
ballproperties[i] = b;
ballproperties[i].setProperties();
java.util.Random rd = new java.util.Random();
ballproperties[i].positionX = i * 700 / NUMBER_OF_BALL;
ballproperties[i].positionY = rd.nextInt(5);
}
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// Dimension size = getSize();
// int width = size.width;
// int height = size.height;
// 重新填充画布
g.setColor(backGroundColor);
g.fillRect(0, 0, 700, 700);
// 画出鼠标拖动的小球
g.setColor(Color.green);
g.fillOval(x - mouseBallSize / 2, y - mouseBallSize / 2, mouseBallSize,
mouseBallSize);
// 遍历小球数组,将每一个小球画出
for (int i = 0; i < NUMBER_OF_BALL; i++) {
// 设置红色画图色
if (ballproperties[i].color == tanBallKinds.RED) {
g.setColor(Color.red);
}
// 设置绿色画图色
if (ballproperties[i].color == tanBallKinds.GREEN) {
g.setColor(Color.green);
}
// 设置黄色画图色
if (ballproperties[i].color == tanBallKinds.YELLOW) {
g.setColor(Color.yellow);
}
// 根据此时的小球属性画出小球
g.fillOval(ballproperties[i].positionX,
ballproperties[i].positionY, ballproperties[i].width,
ballproperties[i].width);
}
}
public void mouseDragged(MouseEvent e) {
}
// 获得鼠标移动的坐标值作为鼠标移动小球的绘制位置坐标
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
}
第3个类:
package MakeHerBigger;
public class tanBallKinds extends Thread {
// 定义球的个数
private int NUMBER_OF_BALL = 30;
// 定义静态颜色常量,
public static final int RED = 1, GREEN = 2, YELLOW = 3, GRAY = 4;
// 声明定义画板类对象
private paintBoard paintboard = new paintBoard();
public ballProperties[] ballproperties;
// 用来改变鼠标的大小增量,
public int changeSize = 1;
// 声明定义一个主类对象
private TestMain testmain = new TestMain();
// 用来记录当鼠标移动小球碰到黄色小球时的时间,随后剩余时间继续减少,用这个值减去剩余时间,用来得到屏幕闪动的时间(5s)
public static int backGroundFlash = 500;
// 构造函数,接收画板类对象,和主类对象
public tanBallKinds(paintBoard paintboard, TestMain testmain) {
this.paintboard = paintboard;
this.testmain = testmain;
this.ballproperties = paintboard.ballproperties;
}
public void run() {
while (true) {
// 给系统休息时间,防止CPU占用过多
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
// 如果TestMain.startOrstop为true那么就开始,否则就重新来一次
while (TestMain.startOrstop) {
// 给系统休息时间,防止CPU占用过多
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
// 如果TestMain.isContinue为true,就表示处于继续状态,而按钮上显示的是“暂停”,否则表示游戏处于暂停状态,按钮上显示“继续”
while (TestMain.isContinue) {
// 取得随机数对象
java.util.Random rd = new java.util.Random();
// 一个一个球地遍历
for (int i = 0; i < NUMBER_OF_BALL; i++) {
// 如果剩余时间小于0,那么提示玩家时间已到,重来一次
if (testmain.time < 0) {
stopPlay();
javax.swing.JOptionPane.showMessageDialog(null,
"对不起,时间已到");
}
// 如果有一个小球到达游戏窗口底部,就将这个小球属性重置(调用小球的属性随机重置函数)让小球从窗体上方随机位置,随机颜色,随机速度出现
if (ballproperties[i].positionY > 600) {
ballproperties[i].setProperties();
}
// 当遇到红色小球时
if (ballproperties[i].color == 1) {
if ((ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
* (ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
+ ((ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y) * (ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y)) <= ((ballproperties[i].width + 20)
* (ballproperties[i].width + 20) / 4)) {
// 令TestMain.startOrstop = false,表示该局结束停止当次循环,
TestMain.startOrstop = false;
// 同时让最里层循环处于暂停状态
pause();
// 弹出提示框
javax.swing.JOptionPane.showMessageDialog(null,
"Come on,Play once again!!!");
// 调用停止本次游戏的函数,使游戏状态重置成起始状态
stopPlay();
}
}
// 当遇到绿色小球时
if (ballproperties[i].color == 2) {
if ((ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
* (ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
+ ((ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y) * (ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y)) <= ((ballproperties[i].width + paintboard.mouseBallSize)
* (ballproperties[i].width + paintboard.mouseBallSize) / 4)) {
// 把遇到的小绿球的属性重置,就将这个小球属性重置(调用小球的属性随机重置函数)让小球从窗体上方随机位置,随机颜色,随机速度出现
ballproperties[i].setProperties();
// 将小球的大小增大
paintboard.mouseBallSize += changeSize;
// 碰到绿色小球时让分数增加,因为每个绿色小球都有一个记录大小的整形数,就用这个数实现分数增加,当碰到的绿色小球越大,得到的分数就越多
testmain.score += (ballproperties[i].width + 1) / 4;
// 将新的总分数显示到窗口的文本框中
testmain.jt_score.setText(testmain.score + "分");
// 进行关数设置,当分数小于100时为第一关,大于100小于200时是第二关,以此类推
testmain.guan = (testmain.score - testmain.score % 100) / 100 + 1;
testmain.jt_guan.setText("第" + testmain.guan
+ "关");
}
}
// 如果遇到的是黄色小球
if (ballproperties[i].color == 3) {
if ((ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
* (ballproperties[i].positionX
+ ballproperties[i].width / 2 - paintboard.x)
+ ((ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y) * (ballproperties[i].positionY
+ ballproperties[i].width / 2 - paintboard.y)) <= ((ballproperties[i].width + 20)
* (ballproperties[i].width + 20) / 4)) {
// 让这个backGroundFlash记录鼠标移动小球与黄色小球碰撞时的游戏剩余时间,再在另一个线程backGroundFlash减去testmain.time差值小于5表示在5秒内要进行闪屏处理
backGroundFlash = testmain.time;
// 既然碰到黄色小球会闪屏,当然也得有点奖励,那就是8分,有点诱惑,但也有点危险
testmain.score += 8;
testmain.jt_score.setText(testmain.score + "分");
testmain.guan = (testmain.score - testmain.score % 100) / 100 + 1;
testmain.jt_guan.setText("第" + testmain.guan
+ "关");
ballproperties[i].setProperties();
}
}
// 在进行遍历过程中让每个小球的当前的Y坐标加上一个位置改变值,之后进行画布重绘,这样就体现小球的动画效果,
ballproperties[i].positionY += ballproperties[i].speedChange;
}
// 休息一段时间
try {
Thread.sleep(8);
} catch (Exception ef) {
ef.printStackTrace();
}
// 遍历每个小球后实现画布重绘
paintboard.repaint();
// paintboard.setBallProperties(ballproperties);
}
}
}
}
// 当点击开始按钮时调用该函数,启动开始while循环
public void startPlay() {
TestMain.startOrstop = true;
continueAgain();
}
// 当单击重来一次按钮时调用该函数,结束while循环,并进行小球属性,按钮文字,文本框文字剩余时间进度条的重置
public void stopPlay() {
TestMain.startOrstop = false;
pause();
// 遍历每一个小球进行属性虫子
for (int j = 0; j < NUMBER_OF_BALL; j++) {
ballproperties[j].setProperties();
}
// 文本框,按钮文字,剩余时间重置
paintBoard.mouseBallSize = 20;
testmain.jb_start.setText("开始");
testmain.jb_pause.setText("暂停");
testmain.score = 0;
testmain.jt_score.setText(testmain.score + "分");
testmain.time = 100;
testmain.jprogress.setValue(testmain.time);
testmain.jt_time.setText(testmain.time + "S");
testmain.guan = 1;
testmain.jt_guan.setText("第" + testmain.guan + "关");
backGroundFlash = 500;
}
// 暂停功能方法,当点击暂停按钮时调用
public void pause() {
TestMain.isContinue = false;
}
// 继续功能方法,当点击继续按钮时调用
public void continueAgain() {
TestMain.isContinue = true;
}
}
第4个类:
package MakeHerBigger;
public class ballProperties {
public int positionX, positionY;
public int color;
public int width;
public int speedChange;
public void setProperties() {
java.util.Random rd = new java.util.Random();
//实现速度随随机
speedChange=rd.nextInt(5)+2;
//实现初始小球X坐标随机
positionX = rd.nextInt(600);
//让刚开始时小球Y坐标值都为-10(实际上系统会将这个值定位0)
positionY = -10;
//实现初始小球颜色随机
color = rd.nextInt(3) + 1;
//color==1代表是红色
//color==2代表是绿色
//color==3代表是黄色
if(color==1){
width=25;
}else if(color==2){
//实现绿色小球的大小随机
java.util.Random rd_size = new java.util.Random();
int size=rd_size.nextInt(5)+1;
switch(size){
case 1:width=5;break;
case 2:width=7;break;
case 3:width=9;break;
case 4:width=11;break;
case 5:width=13;break;
}
}else if(color==3){
width=20;
}
}
}
第5个类:
package MakeHerBigger;
import java.awt.Color;
public class backGroundColorChange extends Thread {
private TestMain testmain;
private paintBoard paintboard;
public backGroundColorChange(TestMain testmain, paintBoard paintboard) {
this.testmain = testmain;
this.paintboard = paintboard;
}
public void run() {
while (true) {
//休息100
try {
Thread.sleep(100);
} catch (Exception ef) {
ef.printStackTrace();
}
//如果还是在和黄色小球碰撞后5秒内,就改变背景颜色
if (tanBallKinds.backGroundFlash - testmain.time < 6) {
paintBoard.backGroundColor = Color.pink;
}
//休息100
try {
Thread.sleep(100);
} catch (Exception ef) {
ef.printStackTrace();
}
//如果还是在和黄色小球碰撞后5秒内,就改变背景颜色
if (tanBallKinds.backGroundFlash - testmain.time < 6) {
paintBoard.backGroundColor = Color.black;
}
//休息100
try {
Thread.sleep(100);
} catch (Exception ef) {
ef.printStackTrace();
}
//如果还是在和黄色小球碰撞后5秒内,就改变背景颜色
if (tanBallKinds.backGroundFlash - testmain.time < 6) {
paintBoard.backGroundColor = Color.red;
}
//休息100
try {
Thread.sleep(100);
} catch (Exception ef) {
ef.printStackTrace();
}
//如果还是在和黄色小球碰撞后5秒内,就改变背景颜色
if (tanBallKinds.backGroundFlash - testmain.time < 6) {
paintBoard.backGroundColor = Color.green ;
}
//如果还是在和黄色小球碰撞后超出5秒内,就恢复原黑色背景
if(tanBallKinds.backGroundFlash - testmain.time>=6){
paintBoard.backGroundColor = Color.black;
}
}
}
}
第6个类:
package MakeHerBigger;
import java.awt.Color;
public class timeCount extends Thread {
private TestMain testmain;
private paintBoard paintboard;
public timeCount(TestMain testmain,paintBoard paintboard) {
this.testmain = testmain;
this.paintboard= paintboard;
}
//记录剩余时间的函数
public void run() {
//此方法的while循环结构和tanBallKinds中的while循环结构一样,实现开始,重新来一次,暂停继续的剩余时间的相关内容
while (true) {
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
while (TestMain.startOrstop) {
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
while (TestMain.isContinue) {
try {
Thread.sleep(1000);
} catch (Exception ef) {
ef.printStackTrace();
}
testmain.time--;
testmain.jprogress.setValue(testmain.time);
testmain.jt_time.setText(testmain.time + "s");
}
}
}
}
}