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, "咦?你忘記了我們之間的暗号!不是不是小兔子乖乖,把門開開啦!");
}