Java实现推箱子小游戏(idea+mySQL)
就是我们学校实训有个推箱子的小游戏,一开始只是完成任务,然后……【想法越来越多,我的第一个小游戏就诞生了,虽然可能就我一个人玩了,但是很高兴能和你分享制作的过程!】
完整的白嫖代码以及资料可以通过下面的百度云连接获取
(大家可以根据源码和看文章中对各个板块的说明这样更加清晰一点)
链接:https://pan.baidu.com/s/18LGcssj8ms-A7WgPNH3bwQ 提取码:yncd
复制这段内容后打开百度网盘手机App,操作更方便哦
游戏部分功能及部分地图展示
一、游戏设定
1.玩法
把箱子推到指定的地方,这里我把箱子替换成了礼物,需要把礼物搬运到指定的地点,就能进入下一关。
2.剧情
小熊要给小兔子过生日,在每一年都会准备不同的礼物,当所有礼物都送达的时候,小熊就会给小兔子送上这一年的生日祝福!小兔子也能按时长大一岁。
二、需求分析
1.用户登录界面
玩家凭借用户名和密码登录,没有账号时可以选择注册
2.游戏界面
(1)窗体标题栏
玩家登入成功后就会在窗体的标题栏上显示用户昵称
(2)窗体菜单栏
玩家可以在通过菜单栏的点击实现相应的功能
(3)主要按钮
玩家可以点击按钮实现相应的功能
(4)主面版
玩家可以通过键盘,实现小熊位置的移动,箱子的推动,所有箱子推到指定位置(就是小熊爪印的时候)就会自动进入下一关,在右侧的版面,有关卡的提示功能,记录步骤,送达礼物,用时,实现所有玩家的排行(前三名),并在右下角有当前的时间显示。
三、数据库设计
1.用MySQL设计存储玩家信息的表
这里我们用到的是mySQL
创建数据库-> mygame
创建数据表-> user
2.为了后续方便操作,我们可以使用idea的Database功能
填写用户名和密码一般就可以连接成功了,但是MySQL(8.0)好像是要配置时区的
四、需要提前创建的一些接口类
工程总览
1.class GameUtil【负责实现图面的读取】
package yuixiangzi;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
public class GameUtil {
// 工具类最好将构造器私有化。
private GameUtil() {
}
public static Image getImage(String path) {
BufferedImage bi = null;
try {
URL u = GameUtil.class.getClassLoader().getResource(path);
bi = ImageIO.read(GameUtil.class.getResourceAsStream(path));
} catch (IOException e) {
e.printStackTrace();
}
return bi;
}
}
2.class SetImage【这是我对文件夹中的图片进行的处理】
package yuixiangzi;
import java.awt.*;
public class SetImage {
private SetImage() {
}
public static Image[] GetImage(int year) {
Image img1 = GameUtil.getImage("/pic/1.png");
Image img2 = GameUtil.getImage("/pic/2.png");
Image img3 = GameUtil.getImage("/pic/3.png");
Image img4 = GameUtil.getImage("/pic/4.png");
Image img5 = GameUtil.getImage("/pic/5.png");
Image img6 = GameUtil.getImage("/pic/6.png");
Image img7 = GameUtil.getImage("/pic/7.png");
Image img8 = GameUtil.getImage("/pic/8.png");
Image img9 = GameUtil.getImage("/pic/9.png");
Image img10 = GameUtil.getImage("/pic/10.png");
Image img11 = GameUtil.getImage("/pic/11.png");
Image img12 = GameUtil.getImage("/pic/12.png");
Image img13= GameUtil.getImage("/pic/13.png");
Image img14 = GameUtil.getImage("/pic/14.png");
Image img15 = GameUtil.getImage("/pic/001.png");
Image img16 = GameUtil.getImage("/pic/002.png");
Image img17 = GameUtil.getImage("/pic/003.png");
Image img18 = GameUtil.getImage("/pic/004.png");
Image img19 = GameUtil.getImage("/pic/005.png");
Image img20 = GameUtil.getImage("/pic/006.png");
Image img21 = GameUtil.getImage("/pic/007.png");
Image img22 = GameUtil.getImage("/pic/008.png");
Image img23 = GameUtil.getImage("/pic/009.png");
Image img24 = GameUtil.getImage("/pic/010.png");
Image img25 = GameUtil.getImage("/pic/011.png");
Image img26 = GameUtil.getImage("/pic/012.png");
Image img27 = GameUtil.getImage("/pic/013.png");
Image img28 = GameUtil.getImage("/pic/014.png");
Image img29 = GameUtil.getImage("/pic/015.png");
Image img30 = GameUtil.getImage("/pic/016.png");
Image img31 = GameUtil.getImage("/pic/017.png");
Image img32 = GameUtil.getImage("/pic/018.png");
Image img33 = GameUtil.getImage("/pic/019.png");
Image img34 = GameUtil.getImage("/pic/020.png");
Image img35 = GameUtil.getImage("/pic/021.png");
Image img36 = GameUtil.getImage("/pic/022.png");
Image img37 = GameUtil.getImage("/pic/023.png");
Image img38 = GameUtil.getImage("/pic/024.png");
Image img39 = GameUtil.getImage("/pic/025.png");
Image img40 = GameUtil.getImage("/pic/026.png");
Image img41 = GameUtil.getImage("/pic/027.png");
Image img42 = GameUtil.getImage("/pic/028.png");
Image img43 = GameUtil.getImage("/pic/029.png");
Image img44 = GameUtil.getImage("/pic/030.png");
Image img45 = GameUtil.getImage("/pic/031.png");
Image img46 = GameUtil.getImage("/pic/032.png");
Image img47 = GameUtil.getImage("/pic/033.png");
Image img48 = GameUtil.getImage("/pic/034.png");
Image img49 = GameUtil.getImage("/pic/035.png");
Image img50 = GameUtil.getImage("/pic/036.png");
Image img51 = GameUtil.getImage("/pic/037.png");
Image img52 = GameUtil.getImage("/pic/038.png");
Image img53 = GameUtil.getImage("/pic/039.png");
Image img54 = GameUtil.getImage("/pic/040.png");
Image img55 = GameUtil.getImage("/pic/041.png");
Image img56 = GameUtil.getImage("/pic/042.png");
Image img57 = GameUtil.getImage("/pic/043.png");
Image img58 = GameUtil.getImage("/pic/044.png");
Image img59 = GameUtil.getImage("/pic/045.png");
Image img60 = GameUtil.getImage("/pic/046.png");
Image img61 = GameUtil.getImage("/pic/047.png");
Image img62 = GameUtil.getImage("/pic/048.png");
Image img63 = GameUtil.getImage("/pic/049.png");
Image img64 = GameUtil.getImage("/pic/050.png");
Image img65 = GameUtil.getImage("/pic/051.png");
Image img66 = GameUtil.getImage("/pic/052.png");
Image img67 = GameUtil.getImage("/pic/053.png");
Image img68 = GameUtil.getImage("/pic/054.png");
Image img69 = GameUtil.getImage("/pic/055.png");
Image img70 = GameUtil.getImage("/pic/056.png");
Image img71 = GameUtil.getImage("/pic/057.png");
Image img72 = GameUtil.getImage("/pic/058.png");
Image img73 = GameUtil.getImage("/pic/059.png");
Image img74 = GameUtil.getImage("/pic/060.png");
Image img75 = GameUtil.getImage("/pic/061.png");
Image img76 = GameUtil.getImage("/pic/062.png");
Image img77 = GameUtil.getImage("/pic/063.png");
Image img78 = GameUtil.getImage("/pic/064.png");
Image img79 = GameUtil.getImage("/pic/065.png");
Image img80 = GameUtil.getImage("/pic/066.png");
Image img81 = GameUtil.getImage("/pic/067.png");
Image img82 = GameUtil.getImage("/pic/068.png");
Image img83 = GameUtil.getImage("/pic/069.png");
//imag40 6 7 3不变其他自己配置 00命名的记得加14
Image[] maping = new Image[10];
if(year%7==1){
maping = new Image[]{
img34, img36, img40, img6, img7, img3, img3, img3, img3, img5,
};
}
else if(year%7==2){
maping = new Image[]{
img35, img64, img40, img6, img7, img3, img3, img3, img3, img60,
};
}
else if(year%7==3){
maping = new Image[]{
img68, img71, img40, img6, img7, img3, img3, img3, img3, img69,
};
}
else if(year%7==4){
maping = new Image[]{
img41, img50, img40, img49, img58,img37, img37, img37, img37, img42,
};
}
else if(year%7==5){
maping = new Image[]{
img13, img23, img40, img6, img7,img3, img3, img3, img3, img66,
};
}
else if(year%7==6){
maping = new Image[]{
img46,img56, img40, img6, img7,img3, img3, img3, img3, img65,
};
}
else{
maping = new Image[]{
img54,img42, img40, img6, img7,img3, img3, img3, img3, img2,
};
}
return maping;
}
}
3.class JDBCUtils【数据库连接工具类】
package yuixiangzi;
import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
//JDBC工具了
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
try {
Properties pro=new Properties();
pro.load(new FileReader("src\\jdbc.properties"));
url = pro.getProperty("url");
user=pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,user,password);
}
public static void close(Statement stmt,Connection conn){
if(stmt !=null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(conn !=null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
public static void close(ResultSet rs,Statement stmt, Connection conn){
if(rs !=null){
try{
rs.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(stmt !=null){
try{
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if(conn !=null){
try{
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
4.jdbc.properties【方便更改数据库】
特别特别要注意,不要多打空格!!!(当初连数据库的时候就是因为这里多打了空格找了好久的原因QVQ)
url=jdbc:mysql:///mygame
user=root
password=root
driver=com.mysql.cj.jdbc.Driver
五、登入窗口实现
1.界面外观设计
我就是喜欢这样可可爱爱(花里胡哨)的设计!谁说程序员就不可以粉粉嫩嫩的嘛!
class MyGameLogin extends JFrame {
String username = null;
String password = null;
public MyGameLogin() {
super("时光登入口");
String path = "/pic/10.png";
//设置窗体图标
try {
Image image = ImageIO.read(getClass().getResource(path));
setIconImage(image);
} catch (IOException e) {
e.printStackTrace();
}
setSize(400, 400);
Container C = getContentPane();
C.setLayout(null);
C.setBackground(new Color(255, 228, 196));
JLabel lblTitle = new JLabel("时光登入口");
lblTitle.setForeground(new Color(255, 140, 0));
lblTitle.setFont(new Font("幼圆", Font.BOLD, 35));
lblTitle.setBounds(100, 35, 200, 35);
add(lblTitle);
JLabel lblLogin = new JLabel("玩家名:");
lblLogin.setForeground(new Color(244, 164, 96));
lblLogin.setFont(new Font("幼圆", Font.BOLD, 20));
lblLogin.setBounds(70, 160, 100, 35);
add(lblLogin);
JLabel lblLogin1 = new JLabel("密码:");
lblLogin1.setForeground(new Color(244, 164, 96));
lblLogin1.setFont(new Font("幼圆", Font.BOLD, 20));
lblLogin1.setBounds(70, 220, 100, 35);
add(lblLogin1);
JButton btnLogin;
btnLogin = new JButton("注册");
btnLogin.setForeground(new Color(255, 127, 80));
btnLogin.setBackground(new Color(255, 222, 173));
btnLogin.setBounds(230, 270, 80, 30);
C.add(btnLogin);
JPasswordField passWord = new JPasswordField();
passWord.setForeground(new Color(255, 140, 0));
passWord.setBounds(170, 220, 140, 35);
C.add(passWord);
JTextField userName = new JTextField();
userName.setForeground(new Color(255, 140, 0));
userName.setBounds(170, 160, 140, 35);
C.add(userName);
JButton btnLogin1;
btnLogin1 = new JButton("登入");
btnLogin1.setForeground(new Color(255, 127, 80));
btnLogin1.setBackground(new Color(255, 222, 173));
btnLogin1.setBounds(100, 270, 80, 30);
C.add(btnLogin1);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Image imagetx = GameUtil.getImage("/pic/1.png");
Image imagexx = GameUtil.getImage("/pic/3.png");
Image imageLove = GameUtil.getImage("/pic/13.png");
Image imageFlower1 = GameUtil.getImage("/pic/003.png");
Image imageFlower2 = GameUtil.getImage("/pic/009.png");
Image imageFlower3 = GameUtil.getImage("/pic/005.png");
Image imageFlower4 = GameUtil.getImage("/pic/012.png");
public void paint(Graphics g) {
super.paint(g);
g.drawImage(imageFlower1, 90, 150, null);
g.drawImage(imageFlower3, 120, 150, null);
g.drawImage(imagetx, 150, 150, null);
g.drawImage(imageLove, 180, 150, null);
g.drawImage(imagexx, 210, 150, null);
g.drawImage(imageFlower2, 240, 150, null);
g.drawImage(imageFlower4, 270, 150, null);
}
}
2.登录功能实现
(1)登录按钮监听
按下登录按钮后,开始判断用户名和密码是否不为空,如果不为空,则进行查询语句的判断。
btnLogin1.addActionListener(new AbstractAction() {
@Override
/*[为什么这里不能判断是否为空]
如果这个遗留问题不解决,那么后面的注册插入数据库的操作有没有办法执行*/
public void actionPerformed(ActionEvent e) {
username = userName.getText();
password = new String(passWord.getPassword());
System.out.println("test:" + username);
System.out.println("test:" + password);
if (StringUtils.isNullOrEmpty(username)) {
JOptionPane.showMessageDialog(null, "小兔子:真是的!你连名字都不告诉我");
}
if (StringUtils.isNullOrEmpty(password)) {
JOptionPane.showMessageDialog(null, "咦?你忘记了我们之间的暗号!不是不是小兔子乖乖,把门开开啦!");
}
if (!StringUtils.isNullOrEmpty(username) && !StringUtils.isNullOrEmpty(password)) {
//【这里执行查找语句】
if (login()) {
JOptionPane.showMessageDialog(null, "小兔子:你好!" + username + "又见面了!");
dispose();
long startTime = System.currentTimeMillis();
System.out.println(startTime);
int[] result= null;
result=select(username);
select(username);
new myGame(startTime,username,result[0],result[1],result[2]);
} else {
JOptionPane.showMessageDialog(null, "小兔子:我好像不认识你哦!");
}
}
}
});
(2)查询数据库判断该用户密码是否正确
public boolean login() {
if (username == null || password == null) {
return false;
}
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
String sql = "select* from user where id= ? and password = ? ";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,username);
pstmt.setString(2,password);
rs = pstmt.executeQuery();
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
return false;
}
(3)用户登录后查询保存的游戏信息
public int[] select(String username){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int[] result= null;
try {
int grift,level,step;
conn = JDBCUtils.getConnection();
String sql = "select grift,lever,step from user where id= ? ";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,username);
rs = pstmt.executeQuery();
result=new int[3];
while (rs.next()){
grift=rs.getInt("grift");
level=rs.getInt("lever");
step=rs.getInt("step");
result[0]=grift;
result[1]=level;
result[2]=step;
}
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
return result;
}
3.注册功能的实现
(1)注册按钮的监听
btnLogin.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
username = userName.getText();
password = new String(passWord.getPassword());
//[这里执行插入语句]
if (!StringUtils.isNullOrEmpty(username) && !StringUtils.isNullOrEmpty(password)) {
JOptionPane.showMessageDialog(null, "小兔子:你好!" + username + "很高兴和你做朋友");
insert(username,password);
dispose();
long startTime = System.currentTimeMillis();
System.out.println(startTime);
new myGame(startTime,username,0,1,0);
}
else {
JOptionPane.showMessageDialog(null, "小兔子:我好像不认识你哦!");
}
}
});
(2)插入用户信息功能的实现
//这是插入语句
public void insert(String userName,String passWord) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = JDBCUtils.getConnection();
String sql = "insert into user values (?,?,0,1,0)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userName);
pstmt.setString(2, passWord);
int count = pstmt.executeUpdate();
if (count > 0) {
System.out.println("注册成功");
} else {
System.out.println("插入失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt, conn);
}
}
六、游戏版面的实现
1.实现游戏地图的导入及图形的显示
(1)游戏地图的读取
每一关有又相应的由int map[20][20]的二维数组组成,我们只需要读取响应的数字,然后放置相应名字的图片在面板上就好了。
class ReadMap{
private int map[][];
//人物位置
private int mx,my;
//游戏关卡编号
private int level;
public ReadMap(int level){
this.level=level;
//文件路径
String sfilename ="src\\maps\\"+level+".map";
String content="";
//文件字符流读取文件src\maps\0.map
try{
FileReader fr = new FileReader(sfilename);
BufferedReader br = new BufferedReader(fr);
String temp = "";
//一行一行地读取文件,如果读到文件的末尾返回null
while ((temp = br.readLine())!=null){
content += temp;
}
//转化成字节数组
byte b[] = content.getBytes();
map = new int[20][20];
int c =0;
for(int i=0;i<20;i++){
for(int j=0;j<20;j++){
map[i][j]=b[c]-48;
c++;
//返回人物的位置
if(map[i][j]==5){
mx=i;
my=j;
}
}
}
}
catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public int[][] getMap(){
return map;
}
public int getMx() {
return mx;
}
public int getMy() {
return my;
}
}
2.游戏显示界面实现
(1)设计总的组件
//设置按钮
JButton btnBack, btnNext, btnPrev, btnSelect, btnReset,
//撤销一步,下一关,上一关,选择关卡,重新游戏
btnMusic,//选择音乐
btnLook;//查看当前排名
JComboBox cbMusic;//下拉链表框,选择音乐
JMenuBar menuBar;//菜单条
JMenu menuOption, mnuSet, mnuHelp;
//菜单条选项,关卡选择,音乐设置,帮助
JMenuItem miReset, miPrev, miNext, miSelect, miExit, miBack;
JMenuItem miMusic1, miMusic2;
//帮助信息
JMenuItem miHelp;
//只有50关
//定义一个数组存放音乐
//创建MyPanel类
MyPanel mainPanel;
(2)设计窗体
//设置窗体图标
try {
Image image = ImageIO.read(this.getClass().getResource(path));
this.setIconImage(image);
} catch (IOException e) {
e.printStackTrace();
}
Color bgColor = new Color(230, 230, 250);
//设置窗体大小
setSize(800, 840);
//设置窗体颜色
Container C = getContentPane();
C.setLayout(null);
C.setBackground(new Color(255, 240, 245));
//将标题设置
JLabel lblTitle = new JLabel("Happy Birthday !", JLabel.CENTER);
lblTitle.setForeground(new Color(205, 92, 92));
lblTitle.setFont(new Font("幼圆", Font.BOLD, 30));
lblTitle.setBounds(100, 20, 500, 30);
add(lblTitle);
//设置主面板大小和背景颜色
mainPanel = new MyPanel();
mainPanel.setBounds(10, 90, 760, 600);
mainPanel.setBackground(bgColor);
C.add(mainPanel);
createButton(C);
//设置窗体可见
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
(3)设计按钮、音乐下拉选择框和下方标签
//创建按钮函数
public void createButton(Container C) {
//设置显示文字
btnReset = new JButton("重新游戏");
btnBack = new JButton("赖皮一下");
btnNext = new JButton("跳过这关");
btnPrev = new JButton("回溯一关");
btnLook = new JButton("保存当前进度");
btnSelect = new JButton("选择关卡");
btnMusic = new JButton("关闭音乐");
cbMusic = new JComboBox(sMusic);
//设置按钮监听
btnBack.addActionListener(this);
btnMusic.addActionListener(this);
btnNext.addActionListener(this);
btnPrev.addActionListener(this);
btnBack.addActionListener(this);
btnLook.addActionListener(this);
btnReset.addActionListener(this);
btnSelect.addActionListener(this);
//设置绝对位置
btnReset.setBounds(10, 50, 95, 30);
btnMusic.setBounds(110, 50, 95, 30);
btnSelect.setBounds(210, 50, 95, 30);
btnBack.setBounds(310, 50, 95, 30);
btnPrev.setBounds(410, 50, 95, 30);
btnNext.setBounds(510, 50, 95, 30);
btnLook.setBounds(610, 50, 160, 30);
btnReset.setBackground(new Color(255, 174, 185));
btnMusic.setBackground(new Color(255, 174, 185));
btnSelect.setBackground(new Color(255, 174, 185));
btnBack.setBackground(new Color(255, 174, 185));
btnPrev.setBackground(new Color(255, 174, 185));
btnNext.setBackground(new Color(255, 174, 185));
btnLook.setBackground(new Color(255, 174, 185));
cbMusic.addItemListener(this);
C.add(btnReset);
C.add(btnMusic);
C.add(btnSelect);
C.add(btnLook);
C.add(btnPrev);
C.add(btnNext);
C.add(btnBack);
JLabel lblMusic = new JLabel("选择音乐");
lblMusic.setBounds(610, 700, 160, 30);
JLabel lblText1 = new JLabel("小熊:今天是小兔子的生日,我要赶紧把礼物给她送过去!");
lblText1.setForeground(new Color(205, 92, 92));
lblText1.setBounds(10, 700, 460, 30);
C.add(lblText1);
JLabel lblText2 = new JLabel("小熊:你问我是什么礼物?这是秘密!是小兔子喜欢的……");
lblText2.setForeground(new Color(205, 92, 92));
lblText2.setBounds(10, 730, 460, 30);
C.add(lblText2);
C.add(lblMusic);
cbMusic.setBounds(610, 730, 160, 30);
C.add(cbMusic);
}
(4)设计菜单选项
public void createMenus() {
//选项子菜单
menuOption = new JMenu("选项(O)");
menuOption.setMnemonic('O');//设置热键
miReset = new JMenuItem("重置");
miPrev = new JMenuItem("上一关");
miNext = new JMenuItem("下一关");
miSelect = new JMenuItem("选择");
miExit = new JMenuItem("退出");
miBack = new JMenuItem("撤销一步");
menuOption.add(miReset);
menuOption.add(miPrev);
menuOption.add(miNext);
menuOption.add(miSelect);
menuOption.add(miBack);
menuOption.addSeparator();//添加分隔条
menuOption.add(miExit);
//音乐子菜单
mnuSet = new JMenu("设置(S)");
mnuSet.setMnemonic('S');//设置热键
miMusic1 = new JMenuItem(sMusic[0]);
miMusic2 = new JMenuItem(sMusic[1]);
ButtonGroup bg = new ButtonGroup();
bg.add(miMusic1);
bg.add(miMusic2);
//帮助子菜单
//默认选第一首
setMenuState(0);
mnuSet.add(miMusic1);
mnuSet.add(miMusic2);
mnuHelp = new JMenu("帮助(H)");
mnuHelp.setMnemonic('H');
miHelp = new JMenuItem("关于我们……");
mnuHelp.add(miHelp);
//监听
miReset.addActionListener(this);
miPrev.addActionListener(this);
miNext.addActionListener(this);
miBack.addActionListener(this);
miSelect.addActionListener(this);
miExit.addActionListener(this);
miMusic1.addActionListener(this);
miMusic2.addActionListener(this);
miHelp.addActionListener(this);
menuBar = new JMenuBar();
menuBar.add(menuOption);
menuBar.add(mnuSet);
menuBar.add(mnuHelp);
setJMenuBar(menuBar);
}
(5)一些面板显示文字以及图片的实现
public void paint(Graphics g) {
Image[] maping = SetImage.GetImage(level);
super.paint(g);
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
g.drawImage(maping[tempmap[j][i]], i * 30, j * 30, null);
}
}
g.drawImage(img11, 580, 30, null);
g.drawImage(imagetx, 620, 550, null);
g.drawImage(imagetx, 650, 550, null);
g.drawImage(imagetx, 680, 550, null);
g.drawImage(imagetx, 710, 550, null);
g.drawImage(imageff, 595, 280, null);
g.drawImage(imageff, 625, 280, null);
g.drawImage(imageff, 700, 280, null);
g.drawImage(imageff, 730, 280, null);
g.setColor(new Color(233,150,122));
g.setFont(new Font("幼圆", Font.BOLD, 20));
g.drawString("小兔几" + level + "岁啦", 625, 30);
nowlever=level;
g.setColor(new Color(250,128,114));
g.setFont(new Font("幼圆", Font.BOLD, 14));
g.drawString("小熊熊在努力派送礼物", 605, 220);
g.setColor(new Color(255,160,122));
g.drawString("已经走了:" +nowstep + "步啦", 605, 240);
g.setFont(new Font("幼圆", Font.BOLD, 16));
g.setColor(new Color(205,92,92));
g.drawString("排行榜", 655, 300);
g.setFont(new Font("幼圆", Font.BOLD, 14));
g.setColor(new Color(255,99,71));
//[排行榜实现 6.22]要有查询操作 返回一个字符数组(排序)
// g.drawString("第一名:"+id1+" "+"礼物:"+lw1+"步骤"+bz1);
order();
for(int i=0;i<sites.size();i++){
g.drawString(sites.get(i),605,330+i*30);
}
sites.clear();
g.setFont(new Font("幼圆", Font.BOLD, 14));
g.setColor(new Color(255,165,0));
g.drawString("已经送去:" + nowgrift + "礼物", 605, 260);
long usedTimem = (endTime-startTime)/60000;
long usedTimes =(endTime-startTime)%60000/1000;
Date date = new Date();
g.setColor(new Color(255,140,0));
if(usedTimem>=0||usedTimes>=0)
g.drawString("用时:" +usedTimem+ "分钟"+usedTimes+"秒", 605, 280);
g.drawString(date.toString(), 600, 590);
}
(6)关于版面中的order函数实现排行榜功能
//实现排行榜功能取前三名
public void order(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
String sql = "select grift,step,id from user order by grift desc,step asc limit 3 ";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
String s="";
int fc=1;
while(rs.next()){
s="第"+fc+"名:"+rs.getNString("id");
sites.add(s);
s="礼物:"+rs.getInt("grift")+" "
+"步骤"+rs.getInt("step");
sites.add(s);
s="";
fc++;
}
System.out.println(sites);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
}
3.完善具体的功能
在之前的代码中已经完善了监听
(1)帮助功能的实现
if (e.getSource() == miHelp) {
String str = "游戏简介:快帮小熊把礼物送到指定的位置吧\n";
str += "版本信息:lcy制作,希望每一个小朋友都可以收到生日祝福!\n";
JOptionPane.showMessageDialog(this, str, "帮助", JOptionPane.INFORMATION_MESSAGE);
}
(2)退出功能的实现
else if (e.getSource() == miExit) {
System.exit(0);
}
关于setLevel()函数实现关卡
//设置关卡
public void setLevel(int level) {
if (level == 0) {
this.level = 1;
} else if (level == 50) {
this.level = 50;
} else if (level > 1) {//选择关卡
this.level = level;
} else {
this.level = level + this.level;
}
//要在关卡范围之内
if (this.level <= 0) {
this.level = 1;
} else if (this.level >= 50) {
this.level = 50;
}
readFile(this.level);
//清空
step.clear();
//设置焦点
requestFocus();
}
public void setLevel() {
readFile(this.level);
//清空上一关保存在堆栈中的所有步骤
step.clear();
//设置焦点
requestFocus();
}
(3)下一关功能的实现
else if (e.getSource() == btnNext || e.getSource() == miNext) {
mainPanel.setLevel(1);
}
(4)上一关功能的实现
else if (e.getSource() == btnPrev || e.getSource() == miPrev) {
mainPanel.setLevel(-1);
}
(5)输入数字实现关卡跳转
else if (e.getSource() == btnSelect || e.getSource() == miSelect) {
String slevel = JOptionPane.showInputDialog(this, "请输入你想祝福的年龄(1~50)", "时光直通车", JOptionPane.OK_CANCEL_OPTION);
if (slevel != null) {
try {
int level = Integer.parseInt(slevel);
if (level <= 0 || level >= 50) {
JOptionPane.showMessageDialog(this, "小兔子说:要输入1~50之间的数字");
return;
}
System.out.println("test:" + level);
mainPanel.setLevel(level);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "哎呀!是数字,请输入1~50之间的数字");
return;
}
}
}
关于goBack()函数实现撤退一步拿向左退一步举例
我们需要用一个栈存储每一步(上下左右)每一步的两种情况(推到了箱子,没有推到箱子)
public void goBack() {
//判断堆栈是否为空
if (step.isEmpty()) {
JOptionPane.showMessageDialog(null, "小熊已经回到出发点了!");
return;
}
//1没有退箱子 11推了箱子
int n = step.pop();//取出栈顶元素
switch (n) {
case 1:
case 11:
backLeft(n);
}
requestFocus();
}
当我们每次从栈中取出上一步的时候就要开始进行判断
1.如果上一步没有推箱子,原来人的位置就会变成空地
2.如果上一步推了箱子,那么原来人的位置就会变成箱子,而箱子的位置就会变成空地
public void backLeft(int step) {
if (step == 1) { //没有推箱子
tempmap[mx][my + 1] = 6;
//原来站人的地方,现在变成草地
if (map[mx][my] == 4 || map[mx][my] == 9)
tempmap[mx][my] = 4;
else
tempmap[mx][my] = 2;
my++;
} else {//推了箱子
tempmap[mx][my + 1] = 6;
//原来站人的地方,现在放箱子
if (map[mx][my] == 4 || map[mx][my] == 9) {
tempmap[mx][my] = 9;
} else {
tempmap[mx][my] = 3;
}
//原来放箱子的地方,现在变成空地
if (map[mx][my - 1] == 4 || map[mx][my - 1] == 9) {
tempmap[mx][my - 1] = 4;
} else {
tempmap[mx][my - 1] = 2;
}
my++;
}
//重画界面
repaint();
}
(6)实现赖皮一步的功能
else if (e.getSource() == btnBack || e.getSource() == miBack) {
mainPanel.goBack();
mainPanel.requestFocus();
}
关于sound函数实现音乐的控制
读取音乐文件,注意如果你想要自己喜欢的音乐请使用mid格式的音乐!
class Sound {
String path = new String("src\\music\\");
//默认背景音乐
String file = new String("1.mid");
Sequence seq;
Sequencer midi;
//判断是否在播放音乐
boolean sign;
public Sound() {
loadSound();
}
//播放背景音乐的函数
void loadSound() {
try {
seq = MidiSystem.getSequence(new File(path + file));
midi = MidiSystem.getSequencer();
midi.open();
midi.setSequence(seq);
midi.start();
midi.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
}
catch ( Exception ex ) {
ex.printStackTrace();
}
sign = true;
}
void mystop() {
midi.stop();
midi.close();
sign = false;
}
//判断是否在播放背景音乐
boolean isplay() {
return sign;
}
//设置在下拉框中选择的背景音乐文件名称
void setMusic(String e) {
file = e;
}
}
(7)实现音乐的开关功能
else if (e.getSource() == btnMusic) {
String title = btnMusic.getText();
if (title.equals("关闭音乐")) {
if (sound.isplay()) {
sound.mystop();
}
//设置按钮标题
btnMusic.setText("打开音乐");
} else {
btnMusic.setText("关闭音乐");
sound.loadSound();
}
}
(8)实现音乐的选择功能
else if (e.getSource() == miMusic1) {
cbMusic.setSelectedIndex(0);
}
else if (e.getSource() == miMusic2) {
cbMusic.setSelectedIndex(1);
}
(9)实现重新选择功能
else if (e.getSource() == btnReset || e.getSource() == miReset) {//重来
mainPanel.setLevel();
}
关于save函数实现将当前进度存入数据库
public void save(int gift,int level,int step,String username) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = JDBCUtils.getConnection();
String sql = "update user set grift = ?, lever = ? , step = ? where id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, gift);
pstmt.setInt(2, level);
pstmt.setInt(3,step);
pstmt.setString(4,username);
int count = pstmt.executeUpdate();
if (count > 0) {
System.out.println("保存:"+step+" "+gift+" "+level+" "+username);
System.out.println("保存成功");
} else {
System.out.println("保存失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt, conn);
}
}
(10)实现保存的当前进度功能
else if (e.getSource() == btnLook) {
JOptionPane.showMessageDialog(this, "咔嚓!时光定格,已经记录下了当前状态期待与你下次的会面");
System.out.println("test:"+level);
save(nowgrift,nowlever,nowstep,username);
}
七、玩家交互代码实现
1.键盘动态交互
(1)实现键盘的监听
public MyPanel() {
//监听键盘事件
this.addKeyListener(this);
setSize(600, 600);
readFile(level);
}
(2)读取键盘输入做出响应
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyCode());
nowstep++;
//方向键左键
if (e.getKeyCode() == 37) {
goLeft();
}
//方向键向上
else if (e.getKeyCode() == 38) {
goUp();
}
//方向键向右
else if (e.getKeyCode() == 39) {
goRight();
} //方向键向下
else if (e.getKeyCode() == 40) {
goDown();
}
if (isWin()) {
//这是我设置的通关剧情,你们也可以自行输入了!!
String zf[] = {
"很开心一年前你诞生在这个世界!",
"现在的你软糯糯的像夏天里的棉花糖",
"听说你会啃胡萝卜了,我准备在这个春天给你种下胡萝卜的种子",
"我的胡萝卜丰收了!所以今年的礼物是胡萝卜",
"送你一罐蜂蜜,但是要小心蛀牙哦",
};
nowgrift += needGift;
endTime = System.currentTimeMillis();
System.out.println(endTime);
JOptionPane.showMessageDialog(null, "小熊:祝你" + level + "岁生日快乐!" + zf[level - 1]);
setLevel(1);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
(3)判断箱子是否推到位
public boolean isWin() {
boolean isok = true;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
if ((map[i][j] == 4 || map[i][j] == 9) && tempmap[i][j] != 9) {
isok = false;
break;
}
}
if (!isok)
break;
}
return isok;
}
2.推箱子过程的实现
拿向上推箱子举例,在这段代码中我们其实也完成了当前步骤的入栈,用于实现之后的撤销一步的功能
public void goUp() {
//如果向上推到箱子了(人的前面有箱子)
if (tempmap[mx - 1][my] == 3 || tempmap[mx - 1][my] == 9) {
//判断箱子的上面是什么,如果是目的地或者是空地就可以推动箱子
if (tempmap[mx - 2][my] == 2 || tempmap[mx - 2][my] == 4) {
//如果箱子推到是是空地
if (tempmap[mx - 2][my] == 2) {
//交换空地和箱子的位置
tempmap[mx - 2][my] = 3;//箱子前面
tempmap[mx - 1][my] = 8;//人前面
}
//如果推到的是目的地
else {
//改变箱子的状态
tempmap[mx - 2][my] = 9;
tempmap[mx - 1][my] = 8;
}
//要与原始地图作对比才可以对原来人的位置进行判断
if (map[mx][my] == 4 || map[mx][my] == 9) {
tempmap[mx][my] = 4;
}
//如果推到的是目的地
else {
tempmap[mx][my] = 2;
}
//改变人物的三视图状态(暂时还没有找到三视图)
mx--;//改变人物的位置
step.push(22);
}
}
//如果人的前面是空地
else if (tempmap[mx - 1][my] == 2 || tempmap[mx - 1][my] == 4 || tempmap[mx - 1][my] == 5) {
tempmap[mx - 1][my] = 8;
if (map[mx][my] == 4 || map[mx][my] == 9) {
tempmap[mx][my] = 4;
}
//如果推到的是目的地
else {
tempmap[mx][my] = 2;
}
mx--;
step.push(2);
}
repaint();
}
制作所遇到的困难和解决方法
1.再制作窗口图标时,无法正常更改窗体做上角的图标。
解决办法,将原先的语句用try-catch异常处理包起来,于是发现是路径设置出现问题(input==null),修改正确 的路径就可以正常显示了。
try{
Image image = ImageIO.read(this.getClass().getResource(path));
this.setIconImage(image);
}
catch (IOException e){
e.printStackTrace();
}
2.登录注册时候,玩家输入是否为空时,我用了判断是否为(null),是否为(“”)都不能完成我想要的功能:输入为空的时候不能注册,最后改为StringUtils.isNullOrEmpty(username),成功解决
if (StringUtils.isNullOrEmpty(username)) {
JOptionPane.showMessageDialog(null, "小兔子:真是的!你连名字都不告诉我");
}
if (StringUtils.isNullOrEmpty(password)) {
JOptionPane.showMessageDialog(null, "咦?你忘记了我们之间的暗号!不是不是小兔子乖乖,把门开开啦!");
}