一、游戏概述
弹珠传说是一个基于java swing的弹球小游戏,运行程序后允许用户选择执行选项菜单。双缓冲就是在内存中开辟一片区域,作为后台图像,程序对他进行更新、修改绘制完成后再显示到屏幕上。可以简单地这样理解,将开辟区域可以理解为新建一个图层,然后将之前所建立的图片图层都放在这个图层上面,然后最他们进行合并图层合并成一个图层,然后不管再怎样刷新渲染,几个图像组件都是保持一致的,出现频率不一样的情况也就不会出现了。本设计的主要实现功能是通过双缓冲技术绘制弹珠小球,键盘控制滑块让弹珠能够弹射到墙面得分,并不断升级游戏难度,记录最终得分上传至数据库中进行排序,实现了单人模式和双人合作模式。
二、需求分析
当前各种游戏层出不穷,因为游戏的开发成本非常大,所以游戏开发具有一定的风险性,但是一些小游戏的开发成本具有成本小、编写简单、易上手的优势,所以这些小游戏的开发也在市场占有一席之地。在这类小游戏中包括换装类,益智类,动作类等等,它以画面精美、操作简单得到大家认可,使人们在休息时间可以得到适当的放松。针对这个情况,我们选择了弹珠传说作为我们的小组课程设计。通过拖动滑块使弹球反弹到墙壁,并提前预判其下落的位置等玩法,从而提高人们的观察能力、反应能力与计算能力。
三、运行环境
本项目的开发环境如下:
操作系统:Windows 10。
开发工具:IntelliJ IDEA JDK17、MySQL 。
开发语言:JAVA语言。
四、详细设计
1.游戏初始化界面
代码展示
package JAVA_Lesson_Myprocess;
import javax.sound.sampled.*;
import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
public class 主页面{
public static JFrame frame=new JFrame("弹珠传说");
public void run() throws Exception{
frame.setResizable(false);
//插入背景图片
ImageIcon icon1 = new ImageIcon("C:\\Users\\Lenovo\\Desktop\\Music\\background.jpg");
JLabel label1 = new JLabel(icon1);
label1.setBounds(0, 0, icon1.getIconWidth(), icon1.getIconHeight());
frame.setDefaultCloseOperation(3);
frame.getLayeredPane().add(label1, new Integer(Integer.MIN_VALUE));
JPanel panel = new JPanel();
JPanel panelTop = new JPanel();
panelTop = (JPanel) frame.getContentPane();
//panel和panelTop设置透明
panelTop.setOpaque(false);
panel.setOpaque(false);
//----------------------------------------------------------------------------------------
JPanel jPanel = new JPanel();
jPanel.setLayout(null);
//三个按钮对应三种模式
JButton jButton_Person = new JButton("单人闯关");
JButton jButton_Double = new JButton("双人合作");
JButton jButton_Check = new JButton("排行榜");
jButton_Person.setSize(90, 50);
jButton_Double.setSize(90, 50);
jButton_Check.setSize(90, 50);
jButton_Person.setLocation(100, 200);
jButton_Double.setLocation(100, 300);
jButton_Check.setLocation(100, 400);
jPanel.setOpaque(false);
//按钮获取焦点的事件触发音效
jButton_Person.addMouseListener(
new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
new MUSIC().focus();
}
@Override
public void mouseExited(MouseEvent e) {
}
}
);
jButton_Check.addMouseListener(
new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
new MUSIC().focus();
}
@Override
public void mouseExited(MouseEvent e) {
}
}
);
jButton_Double.addMouseListener(
new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
new MUSIC().focus();
}
@Override
public void mouseExited(MouseEvent e) {
}
}
);
//三个按钮跳转到分别不同的界面 先跳转再关闭当前窗口
jButton_Person.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
new Login().init();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
frame.dispose();
}
});
jButton_Double.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
new Double_Login().init();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
frame.dispose();
}
});
jButton_Check.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
new Mark_user().run();
frame.dispose();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
//设置界面布局
frame.setLocation(500,300);
jPanel.add(jButton_Person);
jPanel.add(jButton_Double);
jPanel.add(jButton_Check);
frame.add(jPanel);
frame.setSize(900, 565);
jPanel.requestFocus();//获取界面焦点
frame.setVisible(true);
}
public static void main(String[] args) {
//主界面执行
try {
new 主页面().run();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
初始化界面调用的音乐类
package JAVA_Lesson_Myprocess;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import java.io.File;
import java.net.URI;
public class MUSIC {
public void focus(){
try{
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Jump1.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn= AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception e){
e.printStackTrace();
}
}
public void defeat(){
try{
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Defeat1.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn= AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception e){
e.printStackTrace();
}
}
}
2.单人闯关模式的设计
开始单人闯关前需先注册用户名方便上传到数据库保存成绩,通过键盘事件监听使木板在画板上的坐标移动,小球使通过一帧一帧改变横坐标和纵坐标重绘出来的,使用双缓冲技术实现小球在页面中移动得更丝滑,调用定时器Timer实现关卡自动升级,3000ms为一个关卡,在第三关时会有另一个小球出现。超级模式即是在木板的右边无限延长需要用户来判断哪个时机适合接小球,空格键触发,一共只能用3次。在初始界面点击单人闯关即可进入游戏,当未接到小球时则会结束游戏显示排行榜上的名次,点击右上角即可返回主菜单。
界面展示
代码展示
我们先是跳转到一个输入用户界面的源代码
package JAVA_Lesson_Myprocess;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Login {
public String username;
public void init(){
//初始化组件
JFrame frame1=new JFrame("弹珠传说");
JLabel label_uername=new JLabel("用户名称:");
JButton jButton=new JButton("确定");
JPanel panel=new JPanel();
JTextField jTextField=new JTextField(8);
frame1.setResizable(false);//设置不可改变
jTextField.setMaximumSize(new Dimension(100,50));
frame1.setLayout(new BorderLayout());//设置布局
panel.add(label_uername,BorderLayout.WEST);
panel.add(jTextField,BorderLayout.CENTER);
panel.add(jButton,BorderLayout.SOUTH);
frame1.add(panel);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
username=jTextField.getText();
System.out.println(username);
try {
prinBall p=new prinBall();
p.setUsername(username);
//这里调用setter方法传参到prinBall界面去
p.init();
frame1.dispose();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
frame1.setBounds(500,300,300,100);
frame1.setVisible(true);
}
}
这边我们先说一下双缓冲技术,所谓的双缓冲就是先画一个等比例大小的画布再盖上去这里话不多说直接上代码
private static Image offScreenImage = null;//用于实现双缓冲
//以下在画布中重写
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(TABLE_WIDTH, TABLE_HEIGHT);//创建一张大小和窗口大小一样的虚拟图片
}
Graphics gOffScreen = offScreenImage.getGraphics();//获得画笔
//刷新背景,否则物体运动痕迹会保留
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0,TABLE_WIDTH, TABLE_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);//画到虚拟图片上
g.drawImage(offScreenImage, 0, 0, null);//把图片画到屏幕上
这里的update一定要重写,具体的你们可以去看下其他博主写的update与paint的关系,update与paint重写与画布中,每当重绘的时候都要取前景色设置前景色
Color c = g.getColor();//取出原前景色
g.setColor(Color.RED);//设置前景色
然后在你每次绘制完一个图形之后要恢复它
g.setColor(c);//恢复原前景色
具体可以看下单人闯关整个界面的源代码展示
package JAVA_Lesson_Myprocess;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.sql.*;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class prinBall {
private int line;
//初始化数据 为连接数据库做准备
private static String url="jdbc:mysql://localhost:3306/ceshi";
private int mingci;
private static String username_mysql="root";
private static String password_mysql="123456";
private String username;
private int user_mark;
private JFrame frame=new JFrame("弹珠传说-单人闯关");
private int count=3;
//是否为两个小球,两个小球的横纵坐标是不一样的,因此我们可以可以看到是不同轨迹运动
private boolean isTwo=false;
public void setUsername(String username) {
this.username= username;
}
private boolean isbegin=false;
public int mark=0;
public int guan=0;//这里代表关卡每过3s为一关 底下会设置
//桌面高度宽度
private final int TABLE_WIDTH=500;
private final int TABLE_HEIGHT=700;
//球拍高度宽度
private int RACKET_WIDTH=100;
private final int RACKET_HEIGHT=20;
//小球大小
private final int BALL_SIZE=30;
//小球坐标
//随机数出现坐标
Random a=new Random();
private int ballX=a.nextInt(200);
private int ballY=a.nextInt(500);
//第二个小球
private int ballX2=a.nextInt(300);
private int ballY2=a.nextInt(200);
public int speedX2=5;
public int speedY2=4;
//小球速度
public int speedX=5;
public int speedY=6;
//球拍的坐标
private int recketX=120;
private final int recketY=540;
private boolean isOver=false;
private static Image offScreenImage = null;//用于实现双缓冲
private Timer timer;
//开始画小球
private class MyCanvas extends Canvas{
@Override
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(TABLE_WIDTH, TABLE_HEIGHT);//创建一张大小和窗口大小一样的虚拟图片
}
Graphics gOffScreen = offScreenImage.getGraphics();//获得画笔
//刷新背景,否则物体运动痕迹会保留
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0,TABLE_WIDTH, TABLE_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);//画到虚拟图片上
g.drawImage(offScreenImage, 0, 0, null);//把图片画到屏幕上
}
//这里代表着每一帧一帧地重绘
@Override
public void paint(Graphics g) {
Color c = g.getColor();//取出原前景色
g.setColor(Color.RED);//设置前景色
if (isOver){
//判断是否结束如果结束就上传用户名以及成绩到数据库中
//over
user_mark=mark;
g.setColor(Color.RED);
g.setFont(new Font("Times",Font.BOLD,30));
//播放音效
new MUSIC().defeat();
try{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn= DriverManager.getConnection(url,username_mysql,password_mysql);
String sql="INSERT INTO mark_table(username,mark) VALUES(?,?)";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,username);
ps.setInt(2,user_mark);
ps.executeUpdate();
ps.close();
conn.close();
//关闭数据库
}catch (Exception e1){
e1.printStackTrace();
}
try{
mingci= new Check_mark().run_person(username);
}catch (Exception a1){
a1.printStackTrace();
}
g.drawString("游戏结束!您当前分数为"+user_mark,80,200);
g.drawString("排行为"+mingci+"名",200,250);
g.setColor(c);//恢复原前景色
}else{
g.setColor(Color.BLACK);
g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);
g.setColor(c);//恢复原前景色
if (isTwo) {
g.setColor(Color.PINK);//设置颜色
g.fillOval(ballX2, ballY2, BALL_SIZE, BALL_SIZE);//画一个实心圆
g.setColor(c);//恢复原前景色
}
//球拍
g.setColor(Color.BLACK);
g.fillRect(recketX,recketY,RACKET_WIDTH,RACKET_HEIGHT);//画一个实心长方体
g.setColor(c);//恢复原前景色
}
}
}
MyCanvas drawArea=new MyCanvas();//新建画布对象
public void init() throws Exception {
// System.out.println(username);
//触发音效
System.out.println(username);
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Dungeon2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn= AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
//最关键的就是这一步操作我们设置监听然后每过100ms木板就会根据我们的按键改变横纵坐标
//球拍坐标的变化
KeyListener listener=new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode==KeyEvent.VK_LEFT){
if(recketX>0)
recketX-=20;
}
if(keyCode==KeyEvent.VK_RIGHT){
if(recketX<(TABLE_WIDTH-RACKET_WIDTH))
recketX+=20;
}
if (keyCode==KeyEvent.VK_SPACE&&count>0){
if (RACKET_WIDTH==100)
RACKET_WIDTH=10000;
count--;
}
}
};
frame.addKeyListener(listener);
drawArea.addKeyListener(listener);
//判断小球是否已经碰壁或者碰到木板或者超出木板的范围
ActionListener task=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//速度修正
if(ballX<=0||ballX>=(TABLE_WIDTH-BALL_SIZE))
{
//---------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
//触发音效
//-----------------------------------------------------------------------
speedX=-speedX;
mark++;
}
if(ballY<=0||(ballY>recketY-BALL_SIZE&&ballX>recketX&&ballX<recketX+RACKET_WIDTH))
{
//---------------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}//触发音效
//--------------------------------------------------
speedY=-speedY;//碰撞到就等于反向速度
mark++;
}
if (ballY>recketY-BALL_SIZE&&(ballX<recketX||ballX>recketX+RACKET_WIDTH))
{
//timer.stop();
isOver=true;
drawArea.repaint();//画布的重绘
}
//判断第二个小球
if (isTwo){
if(ballX2<=0||ballX2>=(TABLE_WIDTH-BALL_SIZE))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedX2=-speedX2;
mark++;
}
if(ballY2<=0||(ballY2>recketY-BALL_SIZE&&ballX2>recketX&&ballX2<recketX+RACKET_WIDTH))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedY2=-speedY2;
mark++;
}
if (ballY2>recketY-BALL_SIZE&&(ballX2<recketX||ballX2>recketX+RACKET_WIDTH))
{
isOver=true;
drawArea.repaint();
}
ballX2+=speedX2;
ballY2+=speedY2;
}
//更新坐标
ballX+=speedX;
ballY+=speedY;
drawArea.repaint();
}
};
//定时器
javax.swing.Timer timer=new javax.swing.Timer(90,task);//定时器让他每一帧一帧重绘出来
timer.start();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
drawArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));//设置最大尺寸
frame.add(drawArea);
Panel p=new Panel();
p.setLayout(new FlowLayout(0));
//------------------------------头上显示标签-----------------------------------------------------------------------------
JButton fanhui=new JButton("返回");
JLabel label=new JLabel();
JLabel mark_JLabel=new JLabel();
JLabel speed_x=new JLabel();
JLabel speed_y=new JLabel();
JLabel count_mark=new JLabel();
Timer time=new Timer();
Timer time_mark=new Timer();
//返回主界面监听事件
fanhui.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clip.close();
try {
timer.stop();
time.cancel();
time_mark.cancel();
frame.dispose();
Thread.sleep(300);
new 主页面().run();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
//这边是定时器,递增或递减速度
time.schedule(new TimerTask() {
@Override
public void run() {
if (speedX>0){
speedX+=2;
}else{
speedX-=2;
}
if (speedY>0){
speedY+=2;
}else {
speedY-=2;
}
if (isTwo) {
if (speedX2 > 0) {
speedX2 += 2;
} else {
speedX2 -= 2;
}
if (speedY2 > 0) {
speedY2 += 2;
} else {
speedY2 -= 2;
}
}
guan++;
label.setText("第"+guan+"关");
if (guan==3)
isTwo=true;
}
},100,3000);
//--------------------------标签更新---------------------------------------------------------
time_mark.schedule(new TimerTask() {
@Override
public void run() {
mark_JLabel.setText("当前分数为" + mark);
speed_x.setText("x速度为:" + speedX);
speed_y.setText("y速度为:" + speedY);
count_mark.setText("超级模式:" + count);
if (isOver) {
speedX = 0;
speedY = 0;
timer.stop();
time.cancel();
time_mark.cancel();
}
//-------------------这里有个技能能使木板边长,但是仅此只有一秒钟因此我们要延迟一秒就让其回复原样----
if (RACKET_WIDTH == 10000) {
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
RACKET_WIDTH = 100;
}
}
},100,100);
p.add(fanhui);
p.add(count_mark);
p.add(speed_x);
p.add(speed_y);
p.add(mark_JLabel);
p.add(label);
frame.setLocation(500,100);
frame.add(p,BorderLayout.NORTH);
frame.pack();
frame.setResizable(false);
// frame.requestFocus();
drawArea.requestFocus();
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
new prinBall().init();
}
}
3.双人合作模式
双人合作模式就和单人闯关一样的原理,只是代码有点长。超级模式也是在木板的右边无限延长需要用户来判断哪个时机适合接小球,核心内容万变不离其宗,我只是添加了两个画布然后两个监听就能实现本地双人游戏的进行,下面就简单展示一下:
在这点进去之前还是有一个需要输入用户名的界面
代码如下:
package JAVA_Lesson_Myprocess;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Double_Login {
public String username;
public void init(){
JFrame frame1=new JFrame("弹珠传说");
JLabel label_uername=new JLabel("用户名称:");
JButton jButton=new JButton("确定");
JPanel panel=new JPanel();
JTextField jTextField=new JTextField(8);
jTextField.setMaximumSize(new Dimension(100,50));
frame1.setLayout(new BorderLayout());
panel.add(label_uername,BorderLayout.WEST);
panel.add(jTextField,BorderLayout.CENTER);
panel.add(jButton,BorderLayout.SOUTH);
frame1.add(panel);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
username=jTextField.getText();
System.out.println(username);
try {
Double_People p2=new Double_People();
p2.setUsername(username);
p2.init();
frame1.dispose();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
// frame1.setLocation(500,300);
frame1.setBounds(500,300,300,100);
frame1.setResizable(false);
frame1.setVisible(true);
}
}
下面是双人合作的界面及源代码:
玩家先结束的一方会等到另一方结束才开始上传到数据库
package JAVA_Lesson_Myprocess;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.net.URI;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class Double_People {
private static String url="jdbc:mysql://localhost:3306/ceshi";
private int o=0;
private int mingci;
private static String username_mysql="root";
private static String password_mysql="123456";
private String username;
private int count_over=0;
public int user_mark;
public void setUsername(String username) {
this.username = username;
}
private JFrame frame=new JFrame("弹珠传说-双人合作");
//判断是否第四关
private int count=5;
private boolean isTwo=false;
private boolean isbegin=false;
public int mark=0;
public int guan=0;
//桌面高度宽度
private final int TABLE_WIDTH=500;
private final int TABLE_HEIGHT=700;
//球拍高度宽度
private int RACKET_WIDTH=100;
private final int RACKET_HEIGHT=20;
//小球大小
private final int BALL_SIZE=30;
//小球坐标
//随机数出现坐标
Random a=new Random();
private int ballX=a.nextInt(200);
private int ballY=a.nextInt(500);
//第二个小球
private int ballX2=a.nextInt(300);
private int ballY2=a.nextInt(200);
public int speedX2=5;
public int speedY2=4;
//小球速度
public int speedX=5;
public int speedY=6;
//球拍的坐标
private int recketX=120;
private final int recketY=540;
private boolean isOver=false;
private static Image offScreenImage = null;//用于实现双缓冲
//双人小游戏的第二个界面***************************************************************************************
private int ballX_2=a.nextInt(200);
private int ballY_2=a.nextInt(500);
//第二界面的第二个小球---------------------------------------------------------------------------------
private int ballX2_2=a.nextInt(300);
private int ballY2_2=a.nextInt(200);
//-----------------------------------------------------
public int speedX_2=5;
public int speedY_2=6;
public int speedX_2_2=5;
public int speedY_2_2=4;
//球拍的坐标
private int recketX_2=120;
private final int recketY_2=540;
private boolean isOver_2=false;
//球拍的大小宽度
private boolean isTwo_2=false;
private int RACKET_WIDTH_2=100;
private final int RACKET_HEIGHT_2=20;
private static Image offScreenImage_2 = null;//用于实现双缓冲
//开始画小球***********************************************************************************************
private class MyCanvas extends Canvas{
@Override
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(TABLE_WIDTH, TABLE_HEIGHT);//创建一张大小和窗口大小一样的虚拟图片
}
Graphics gOffScreen = offScreenImage.getGraphics();//获得画笔
//刷新背景,否则物体运动痕迹会保留
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0,TABLE_WIDTH, TABLE_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);//画到虚拟图片上
g.drawImage(offScreenImage, 0, 0, null);//把图片画到屏幕上
}
@Override
public void paint(Graphics g) {
Color c = g.getColor();//取出原前景色
g.setColor(Color.RED);//设置前景色
if (isOver){
//over
count_over++;
if (count_over==2) {
user_mark=mark;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, username_mysql, password_mysql);
String sql = "INSERT INTO double_people(username,mark) VALUES(?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setInt(2, user_mark);
ps.executeUpdate();
ps.close();
conn.close();
} catch (Exception e1) {
e1.printStackTrace();
}
g.setColor(Color.RED);
g.setFont(new Font("Times",Font.BOLD,30));
g.drawString("游戏结束!您当前的分数为"+mark,50,200);
new MUSIC().defeat();
try {
mingci=new Check_mark().run(username);
g.drawString("排第"+mingci+"名",150,250);
} catch (Exception e) {
throw new RuntimeException(e);
}
}else {
g.setFont(new Font("Times",Font.BOLD,30));
g.drawString("请等待另一个玩家结束",100,300);
}
g.setColor(c);//恢复原前景色
}else{
g.setColor(Color.BLACK);
g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);
g.setColor(c);//恢复原前景色
if (isTwo) {
g.setColor(Color.PINK);
g.fillOval(ballX2, ballY2, BALL_SIZE, BALL_SIZE);
g.setColor(c);//恢复原前景色
}
//球拍
g.setColor(Color.BLACK);
g.fillRect(recketX,recketY,RACKET_WIDTH,RACKET_HEIGHT);
g.setColor(c);//恢复原前景色
}
}
}
//第二个界面
private class MyCanvas_2 extends Canvas{
@Override
public void update(Graphics g) {
if(offScreenImage_2 == null) {
offScreenImage_2 = this.createImage(TABLE_WIDTH, TABLE_HEIGHT);//创建一张大小和窗口大小一样的虚拟图片
}
Graphics gOffScreen_2 = offScreenImage_2.getGraphics();//获得画笔
//刷新背景,否则物体运动痕迹会保留
Color c = gOffScreen_2.getColor();
gOffScreen_2.setColor(Color.white);
gOffScreen_2.fillRect(0, 0,TABLE_WIDTH, TABLE_HEIGHT);
gOffScreen_2.setColor(c);
paint(gOffScreen_2);//画到虚拟图片上
g.drawImage(offScreenImage_2, 0, 0, null);//把图片画到屏幕上
}
@Override
public void paint(Graphics g) {
Color c = g.getColor();//取出原前景色
g.setColor(Color.RED);//设置前景色
if (isOver_2){
//over
count_over++;
if (count_over==2) {
user_mark=mark;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, username_mysql, password_mysql);
String sql = "INSERT INTO double_people(username,mark) VALUES(?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setInt(2, user_mark);
ps.executeUpdate();
ps.close();
conn.close();
} catch (Exception e1) {
e1.printStackTrace();
}
g.setColor(Color.RED);
g.setFont(new Font("Times",Font.BOLD,30));
g.drawString("游戏结束!您当前的分数为"+mark,50,200);
new MUSIC().defeat();
try {
mingci=new Check_mark().run(username);
g.drawString("排第"+mingci+"名",150,250);
} catch (Exception e) {
throw new RuntimeException(e);
}
}else {
g.setFont(new Font("Times",Font.BOLD,30));
g.drawString("请等待另一个玩家结束",100,300);
}
// g.drawString("排第"+"454"+"名",200,250);
g.setColor(c);//恢复原前景色
}else{
g.setColor(Color.BLACK);
g.fillOval(ballX_2,ballY_2,BALL_SIZE,BALL_SIZE);
g.setColor(c);//恢复原前景色
if (isTwo_2) {
g.setColor(Color.PINK);
g.fillOval(ballX2_2, ballY2_2, BALL_SIZE, BALL_SIZE);
g.setColor(c);//恢复原前景色
}
//球拍
g.setColor(Color.BLACK);
g.fillRect(recketX_2,recketY_2,RACKET_WIDTH_2,RACKET_HEIGHT_2);
g.setColor(c);//恢复原前景色
}
}
}
MyCanvas drawArea=new MyCanvas();
MyCanvas_2 drawArea_2=new MyCanvas_2();
//--------------------------------------------------------------------------------------------------------------------------------
public void init() throws Exception {
System.out.println(username);
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Dungeon2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn= AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
//球拍坐标的变化
KeyListener listener=new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode){
case KeyEvent.VK_A:
if(recketX>0)
recketX-=30;
break;
case KeyEvent.VK_D:
if(recketX<(TABLE_WIDTH-RACKET_WIDTH))
recketX+=30;
break;
case KeyEvent.VK_SPACE:
if (RACKET_WIDTH==100&&count>0)
RACKET_WIDTH=10000;
count--;
break;
}
}
};
//球拍2坐标的变化
KeyListener listener_2=new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_LEFT:
if (recketX_2 > 0)
recketX_2 -= 30;
break;
case KeyEvent.VK_RIGHT:
if (recketX_2 < (TABLE_WIDTH - RACKET_WIDTH_2))
recketX_2 += 30;
break;
case KeyEvent.VK_ENTER:
if (RACKET_WIDTH_2 == 100 && count > 0)
RACKET_WIDTH_2 = 10000;
count--;
break;
}
}
};
//zhuce
frame.addKeyListener(listener);
frame.addKeyListener(listener_2);
drawArea.addKeyListener(listener);
drawArea_2.addKeyListener(listener_2);
//ball----------------------------------------------one----------------------------------------------------
ActionListener task=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//速度修正
if(ballX<=0||ballX>=(TABLE_WIDTH-BALL_SIZE))
{
//---------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
//-----------------------------------------------------------------------
speedX=-speedX;
mark++;
}
if(ballY<=0||(ballY>recketY-BALL_SIZE&&ballX>recketX&&ballX<recketX+RACKET_WIDTH))
{
//---------------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
//--------------------------------------------------
speedY=-speedY;
mark++;
}
if (ballY>recketY-BALL_SIZE&&(ballX<recketX||ballX>recketX+RACKET_WIDTH))
{
//timer.stop();
isOver=true;
drawArea.repaint();
}
//判断第二个小球
if (isTwo){
if(ballX2<=0||ballX2>=(TABLE_WIDTH-BALL_SIZE))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedX2=-speedX2;
mark++;
}
if(ballY2<=0||(ballY2>recketY-BALL_SIZE&&ballX2>recketX&&ballX2<recketX+RACKET_WIDTH))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedY2=-speedY2;
mark++;
}
if (ballY2>recketY-BALL_SIZE&&(ballX2<recketX||ballX2>recketX+RACKET_WIDTH))
{
isOver=true;
drawArea.repaint();
}
ballX2+=speedX2;
ballY2+=speedY2;
}
//更新坐标
ballX+=speedX;
ballY+=speedY;
// if (isTwo)
// drawArea.repaint();
drawArea.repaint();
}
};
//第二个界面的定时任务*-----------------------------------------------------------------------**************************
ActionListener task_2=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//速度修正
if(ballX_2<=0||ballX_2>=(TABLE_WIDTH-BALL_SIZE))
{
//---------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
//-----------------------------------------------------------------------
speedX_2=-speedX_2;
mark++;
}
if(ballY_2<=0||(ballY_2>recketY_2-BALL_SIZE&&ballX_2>recketX_2&&ballX_2<recketX_2+RACKET_WIDTH_2))
{
//---------------------------------------------------------------------
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
//--------------------------------------------------
speedY_2=-speedY_2;
mark++;
}
if (ballY_2>recketY_2-BALL_SIZE&&(ballX_2<recketX_2||ballX_2>recketX_2+RACKET_WIDTH_2))
{
//timer.stop();
isOver_2=true;
drawArea_2.repaint();
}
//判断第二个小球
if (isTwo_2){
if(ballX2_2<=0||ballX2_2>=(TABLE_WIDTH-BALL_SIZE))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedX_2_2=-speedX_2_2;
mark++;
}
if(ballY2_2<=0||(ballY2_2>recketY_2-BALL_SIZE&&ballX2_2>recketX_2&&ballX2_2<recketX_2+RACKET_WIDTH_2))
{
try {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\Absorb2.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn=AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}catch (Exception a){
a.printStackTrace();
}
speedY_2_2=-speedY_2_2;
mark++;
}
if (ballY2_2>recketY_2-BALL_SIZE&&(ballX2_2<recketX_2||ballX2_2>recketX_2+RACKET_WIDTH_2))
{
isOver=true;
drawArea_2.repaint();
}
ballX2_2+=speedX_2_2;
ballY2_2+=speedY_2_2;
}
//更新坐标
ballX_2+=speedX_2;
ballY_2+=speedY_2;
// if (isTwo)
// drawArea.repaint();
drawArea_2.repaint();
}
};
//定时器
JPanel p1=new JPanel();
JPanel p2=new JPanel();
javax.swing.Timer timer=new javax.swing.Timer(100,task);
javax.swing.Timer timer_2=new javax.swing.Timer(100,task_2);
new Thread(new Runnable() {
@Override
public void run() {
timer_2.start();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
timer.start();
}
}).start();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
drawArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
drawArea_2.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
p1.add(drawArea);
p2.add(drawArea_2);
frame.setLayout(new BorderLayout(10,30));
frame.add(p1,BorderLayout.WEST);
frame.add(p2,BorderLayout.EAST);
Panel p=new Panel();
//------------------------------头上显示标签-----------------------------------------------------------------------------
JLabel label=new JLabel();
JLabel mark_JLabel=new JLabel();
JLabel speed_x=new JLabel();
JLabel speed_y=new JLabel();
JLabel count_mark=new JLabel();
Timer time=new Timer();
Timer time_mark=new Timer();
JButton fanhui=new JButton("返回");
JLabel jLabel_kong=new JLabel(" ");
fanhui.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clip.close();
try {
timer.stop();
timer_2.stop();
frame.dispose();
Thread.sleep(300);
new 主页面().run();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
time.schedule(new TimerTask() {
@Override
public void run() {
if (speedX>0){
speedX+=2;
}else{
speedX-=2;
}
if (speedY>0){
speedY+=2;
}else {
speedY-=2;
}
if (isTwo) {
if (speedX2 > 0) {
speedX2 += 2;
} else {
speedX2 -= 2;
}
if (speedY2 > 0) {
speedY2 += 2;
} else {
speedY2 -= 2;
}
}
if (speedX_2>0){
speedX_2+=2;
}else{
speedX_2-=2;
}
if (speedY_2>0){
speedY_2+=2;
}else {
speedY_2-=2;
}
if (isTwo) {
if (speedX_2_2 > 0) {
speedX_2_2 += 2;
} else {
speedX_2_2 -= 2;
}
if (speedY_2_2> 0) {
speedY_2_2+= 2;
} else {
speedY_2_2-= 2;
}
}
guan++;
label.setText("第"+guan+"关");
if (guan==3)
{ isTwo=true;
isTwo_2=true;
}
}
},100,3000);
//--------------------------标签更新---------------------------------------------------------
time_mark.schedule(new TimerTask() {
@Override
public void run() {
mark_JLabel.setText("当前分数为" + mark);
speed_x.setText("x速度为:" + speedX);
speed_y.setText("y速度为:" + speedY);
count_mark.setText("超级模式:" + count);
if (isOver) {
speedX = 0;
speedY = 0;
timer.stop();
}
if(isOver_2){
timer_2.stop();
speedX_2 = 0;
speedY_2 = 0;
}
if (isOver&&isOver_2)
{
time.cancel();
time_mark.cancel();
}
//-----------------------
if (RACKET_WIDTH == 10000) {
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
RACKET_WIDTH = 100;
}
if (RACKET_WIDTH_2 == 10000) {
{
try {
Thread.sleep(1000);
} catch (InterruptedException a) {
throw new RuntimeException(a);
}
}
RACKET_WIDTH_2 = 100;
}
}
},0,100);
p.setLayout(new FlowLayout(0));
p.add(fanhui);
p.add(jLabel_kong);
p.add(count_mark);
p.add(speed_x);
p.add(speed_y);
p.add(mark_JLabel);
p.add(label);
///-------------------------------------------标签说明----------------------------------------------------------
JPanel explain=new JPanel();
;
JLabel jLabel_explain=new JLabel("<html><body>"+"按键说明:"+"<br/>"+"玩家1 左(p1):A键+D键+空格键"+"<br/>"+"玩家2 右(p2):←键 + →键+Enter键"+"<body></html>");
// JLabel jLabel_explain_p2=new JLabel("p2:← → Enter");
// explain.setSize(50,50);
// explain.add(jLabel_explain_p2);
explain.add(jLabel_explain);
frame.add(explain,BorderLayout.SOUTH);
frame.add(p,BorderLayout.NORTH);
frame.pack();
// frame.requestFocus();
Timer time_3=new Timer();
time_3.schedule(new TimerTask() {
@Override
public void run() {
if (count_over==2)
time_3.cancel();
if (o==1) {
drawArea.requestFocus();
o=0;
}else{
drawArea_2.requestFocus();
o=1;
}
System.out.println(o);
}
},0,60);
frame.setLocation(500,100);
frame.setResizable(false);
frame.setVisible(true);
}
}
4.数据库连接与操作
在这成绩上传到数据库之前记得要设置好数据库,由于单人闯关模式和双人合作模式在结束时都会显示排名,因此我们需要新建一个类来调用它的方法遍历数据库的内容再对成绩排序,然后遍历每个数组找到相符合的用户名再返回相关排名,一般情况下我们是放到一个二维数组里面去的
接下来就是代码展示
package JAVA_Lesson_Myprocess;
import javax.swing.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Comparator;
public class Check_mark {
public int run_person(String user) throws Exception{
String url = "jdbc:mysql://localhost:3306/ceshi";
String username = "root";
String password = "123456";
Class.forName("com.mysql.cj.jdbc.Driver");
JFrame frame = new JFrame("排行榜");
JPanel panel = new JPanel();
JLabel label_1 = new JLabel("单人闯关排行榜");
JLabel label_2 = new JLabel("双人合作排行榜");
Object[] titles = {"排名", "用户名", "成绩"};
Connection conn = DriverManager.getConnection(url, username, password);//连接数据库
String sql = "SELECT * FROM mark_table";
//选择表
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
// ResultSet rs_2=stat.executeQuery(sql);
//查询所有的数据,先遍历一共有几行
int line=0;
while (rs.next()) {
line++;
}
rs.close();
rs = stat.executeQuery(sql);//清空之后回到原点先将数据存储在数组中
Object[][] data = new Object[line][];
for (int i = 0; rs.next(); i++) {
// number = i + 1;
data[i] = new Object[]{0, rs.getString("username"), rs.getInt("mark"),};
}
rs.close();
Arrays.sort(data, new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) {
return (Integer) o2[2]-(Integer)o1[2];
}
});//定义一个二维数组的比较器 降序排序
for (int i = 0; i < line; i++) {
data[i][0]=i+1;
}
//重新给它排名赋值
for (int i = 0; i < line; i++) {
if (user.equals(data[i][1])){
return (Integer) data[i][0];
//查询相符合的用户名称就返回
}
}
return 0;
}
public int run (String user) throws Exception {
String url = "jdbc:mysql://localhost:3306/ceshi";
String username = "root";
String password = "123456";
Class.forName("com.mysql.cj.jdbc.Driver");
JFrame frame = new JFrame("排行榜");
JPanel panel = new JPanel();
JLabel label_1 = new JLabel("单人闯关排行榜");
JLabel label_2 = new JLabel("双人合作排行榜");
Object[] titles = {"排名", "用户名", "成绩"};
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "SELECT * FROM mark_table";
Statement stat = conn.createStatement();
int line = 0, number;
number = 0;
conn = DriverManager.getConnection(url, username, password);
ResultSet rs = stat.executeQuery(sql);
sql = "SELECT * FROM Double_people";
stat = conn.createStatement();
rs = stat.executeQuery(sql);
// ResultSet rs_2=stat.executeQuery(sql);
line = 0;
while (rs.next()) {
line++;
}
System.out.println(line);
rs.close();
rs = stat.executeQuery(sql);
Object[][] data_2 = new Object[line][];
for (int i = 0; rs.next(); i++) {
// number = i + 1;
data_2[i] = new Object[]{0, rs.getString("username"), rs.getInt("mark"),};
}
rs.close();
Arrays.sort(data_2, new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) {
return (Integer) o2[2]-(Integer)o1[2];
}
});
for (int i = 0; i < line; i++) {
data_2[i][0]=i+1;
}
for (int i = 0; i < line; i++) {
if (user.equals(data_2[i][1])){
return (Integer) data_2[i][0];
}
}
return 0;
}
}
5.数据库连接,排行榜
Navicat 管理mysql
排行榜界面
代码展示如下,上面的原理都讲过了,看一下就能懂
package JAVA_Lesson_Myprocess;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.sql.*;
import java.util.Arrays;
import java.util.Comparator;
public class Mark_user {
public void run()throws Exception {
File file=new File("C:\\Users\\Lenovo\\Desktop\\Music\\排行榜音效.wav");
URI uri=file.toURI();
System.out.println(uri);
AudioInputStream audioIn= AudioSystem.getAudioInputStream(file);
Clip clip=AudioSystem.getClip();
clip.open(audioIn);
clip.start();
int line = 0, number;
String url = "jdbc:mysql://localhost:3306/ceshi";
String username = "root";
String password = "123456";
Class.forName("com.mysql.cj.jdbc.Driver");
JFrame frame = new JFrame("排行榜");
JPanel panel = new JPanel();
JLabel label_1 = new JLabel("单人闯关排行榜");
JLabel label_2 = new JLabel("双人合作排行榜");
Object[] titles = {"排名", "用户名", "成绩"};
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "SELECT * FROM mark_table";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
// ResultSet rs_2=stat.executeQuery(sql);
frame.setResizable(false);
while (rs.next()) {
line++;
}
rs.close();
rs = stat.executeQuery(sql);
Object[][] data = new Object[line][];
for (int i = 0; rs.next(); i++) {
// number = i + 1;
data[i] = new Object[]{0, rs.getString("username"), rs.getInt("mark"),};
}
rs.close();
//SORT
Arrays.sort(data, new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) {
return (Integer) o2[2]-(Integer)o1[2];
}
});
for (int i = 0; i < line; i++) {
data[i][0]=i+1;
}
number = 0;
conn = DriverManager.getConnection(url, username, password);
sql = "SELECT * FROM Double_people";
stat = conn.createStatement();
rs = stat.executeQuery(sql);
// ResultSet rs_2=stat.executeQuery(sql);
line = 0;
while (rs.next()) {
line++;
}
//先确定一共有几行
System.out.println(line);
rs.close();//重启 因为要从原点出发
rs = stat.executeQuery(sql);
Object[][] data_2 = new Object[line][];
for (int i = 0; rs.next(); i++) {
data_2[i] = new Object[]{0, rs.getString("username"), rs.getInt("mark"),};
}
rs.close();
Arrays.sort(data_2, new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) {
return (Integer) o2[2]-(Integer)o1[2];
}
});
for (int i = 0; i < line; i++) {
data_2[i][0]=i+1;
}
conn.close();
stat.close();
rs.close();
panel.setLayout(new FlowLayout(0));
javax.swing.JTable jTable = new javax.swing.JTable(data, titles);
javax.swing.JTable jTable_2 = new javax.swing.JTable(data_2, titles);
JPanel Panel_1=new JPanel();
JLabel kong=new JLabel(" ");
JLabel kong_2=new JLabel(" ");
Panel_1.setLayout(new FlowLayout(0));
JButton jButton=new JButton("返回");
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
clip.close();
clip.flush();
audioIn.close();
frame.dispose();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
try {
Thread.sleep(300);
new 主页面().run();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
Panel_1.add(jButton);
Panel_1.add(kong);
Panel_1.add(label_1);
panel.add(Panel_1);
panel.add(new JScrollPane(jTable));
panel.add(kong_2);
panel.add(label_2);
panel.add(new JScrollPane(jTable_2));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 1000);
frame.setLocation(500,20);
frame.setVisible(true);
}
}
五、总结
把每份代码都复制下来放到同一个包里面,改改数据库连接,音乐文件路径,就能运行。通过本次的课设实践使我更加认识java的实用性,本次使用的版本为JDK17。从界面的绘画、音效素材的寻找与设置、游戏关卡设置、数据库连接,让我更加对一整个游戏体系有了不一样的认识,再者每当我调试自己亲手做的游戏时都会有一种喜悦的心情,我体会到了作为开发者的乐趣。一开始我是使用AWT来绘画的,但是由于画面太过于闪烁于是我找遍各种论坛,经过一下午的学习我了解到了计算机图形基础—双缓存原理。从概念到实践我终于在程序中使用了双缓冲的技术,这是我在本次开发以来最为开心的一件事。游戏音效则是通过RPG Maker MZ一个RPG 的游戏引擎的音效素材库来寻找的,通过事件监听,来使小球碰撞发出声音,给用户一种身临其境的感受。每当用户接不到小球结束时我们设置的是victory的音效,因为在我们看来每个人都是成功的,我们选择音效时都有不同的含义。数据库连接则是通过JTable来实现的,通过一个二维数组和我们对二维数组进行排列来使得内容呈降序呈现,再放入到JTable中。还有就是JFrame的布局,我们采用最多的就是流体式布局和绝对布局,再这布局中我们了解到了每一个组件。
版权归原作者 不知名小德 所有, 如有侵权,请联系我们删除。