目录
2、选关类继承JDilog类,采用弹出模态对话框,同时构建选关的按钮、确定、取消等并且给出地图打不开的提示。
一.实验目的和要求
-
深入了解图形用户界面基本组件窗口、按钮、文本框、选择框、滚动条等的使用方法,了解如何使用布局管理器对组件进行管理,以及如何使用 Java 的事件处理机制。
-
将所学知识进行综合运用,模仿设计具有实际意义的应用程序。
-
锻炼使用新类(没有介绍的)类的能力。
二、实验原理分析
- test.java:主类。
- MapConfig.java: 素材图片定义、整合接口
- GetLevelDialog.java: 选关类继承JDilog类,采用弹出模态对话框,同时构建选关的按钮、确定、取消等并且给出地图打不开的提示
- Utils.java:工具类用于游戏主体判断是否存在地图文件
- UpdateThread.java:刷线面板类,继承Thread。每0.01秒刷新面板一次。其中10为10ms(毫秒)
- MainGame.java:游戏主体类继承JFrame同时实现MapConfig接口
- 游戏面板:创建JPanel对象panel组建面板并且添加标题、菜单、选关按钮。
- 定义GetMAp()方法,使用try{}catch来读取放在D盘推箱子文件夹内的地图
- 自定义内部游戏面板类MyPanel并且继承JPanel,通过数组的下标来确定图片的位置,通过GetGameImage方法获取对应数字的图片
- 定义内部游戏按键监听类PanelListenner继承KeyAdapter,同时定义Move()方法以0墙 1地板 2空箱子 3 箱子 4箱子点 5出生点(人物所在位置)为基础通过监听用户的按键改变对应的playerx的值并且定义check()方法来进行碰撞检测,通过检查角色所在位置周围的坐标数组内存储的值来判断1.超界 2.前面是墙 3.前面是箱子或者空箱子 再前面是箱子或者墙或者空箱子在用户进行的操作是否执行来实现角色正常的移动,从而实现推箱子。
- 定义IsSuccess()方法来遍历地图数组判断地图上是否存在空箱子来判断游戏是否成功,定义GetNextMap()方法来实现选关,最后定义Success()方法来判断用户是否通过所有关卡,从而判断是否全部闯关成功。
三、部分源码分析
1、素材接口
package 推箱子2;
import javax.swing.ImageIcon;
public interface MapConfig { //素材图片定义、整合接口
/**素材宽度*/
int SOUREC_WIDTH = 50;
/**素材高度*/
int SOUREC_HEIGHT = 50;
/**地图宽度*/
int MAP_WIDTH = 800;
/**地图高度*/
int MAP_HEIGHT= 800;
/**地图保存的位置 */
String PATH = "D:\\推箱子";
ImageIcon icon101 = new ImageIcon("images/墙.png");
ImageIcon icon102 = new ImageIcon("images/地板.png");
ImageIcon icon103 = new ImageIcon("images/空箱子.png");
ImageIcon icon104 = new ImageIcon("images/箱子.png");
ImageIcon icon105 = new ImageIcon("images/箱子点.png");
ImageIcon icon106 = new ImageIcon("images/player.png");
//将所有的图片素材对象放入一个数组中,便于选择所有的图片素材
ImageIcon[]allicons={icon101,icon102,icon103,icon104,icon105,icon106};
}
2、选关类继承JDilog类,采用弹出模态对话框,同时构建选关的按钮、确定、取消等并且给出地图打不开的提示。
package 推箱子2;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.border.EmptyBorder;
public class GetLevelDialog extends JDialog {//选关类继承JDilog类,采用弹出模态对话框,同时构建选关的按钮、确定、取消等并且给出地图打不开的提示
private DefaultListModel<String> model;
int levelmax, diylevelmax;
JList list;
boolean xuanzhong = true;
int level =0;
private final JPanel contentPanel = new JPanel();
/**
* Create the dialog.
*/
public GetLevelDialog() {
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModal(true);
setTitle("选关");
setBounds(100, 100, 512, 340);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(328, 52, 103, 173);
contentPanel.add(scrollPane);
model = new DefaultListModel<String>();
diylevelmax = 1;
levelmax = 1;
while (true) {
if (IsExistence("D:\\推箱子\\diy" + diylevelmax + ".map")) {
diylevelmax++;
} else if (IsExistence("D:\\推箱子\\" + levelmax + ".map")) {
levelmax++;
} else {
break;
}
}
list = new JList(model);
UpdataModel(diylevelmax);
scrollPane.setViewportView(list);
JTextPane txtpndtxtdiytxt = new JTextPane();
txtpndtxtdiytxt.setText(
"选关界面,你就可以选择开发者做出来的地图,地图文件夹在D盘推箱子中");
txtpndtxtdiytxt.setFont(new Font("楷体", Font.PLAIN, 15));
txtpndtxtdiytxt.setBounds(45, 52, 224, 173);
contentPanel.add(txtpndtxtdiytxt);
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("确定");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
level = list.getSelectedIndex()+1;
dispose();
}
});
okButton.setActionCommand("Cancel");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("取消");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
setLocationRelativeTo(null);
setVisible(true);
}
void UpdataModel(int level){
model.removeAllElements();
for (int i = 1; i < level; i++) {
model.addElement("第"+ i +"关");
}
}
/**
* 判断是否存在文件file
*
* param file 如:D:\\推箱子\\1.txt
* return 存在即为true
*/
boolean IsExistence(String file) {
File fileuser = new File(file);
if (!fileuser.exists()) {
return false;
}
return true;
}
/**
* main得到信息
* return 0 为取消 1-n为选关
*/
int getValue() {
return level;
}
/**
* 返回是否diy地图
* return
*/
boolean isdiy() {
return xuanzhong;
}
}
3、工具类用于游戏主体判断是否存在地图文件
package 推箱子2;
import java.io.File;
public class Utils{ //工具类用于游戏主体判断是否存在地图文件
/**
* 判断是否存在文件file
*
* @param file 如:D:\\推箱子\\1.map
* @return 存在即为true
*/
static boolean IsExistence(String file) {
File fileuser = new File(file);
if (!fileuser.exists()) {
return false;
}
return true;
}
}
4、游戏主体
package 推箱子2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/**
* 游戏主体
*
*
*
*/
public class MainGame extends JFrame implements MapConfig {
int[][][] map1 = new int[18][18][1];// 地图数组
int playerx = 0;// 玩家坐标
int playery = 0;// 玩家坐标
boolean diy = false;//
int level = 1;// 关卡
// 游戏面板
JPanel panel;
public MainGame() {
// TODO Auto-generated constructor stub
this.setTitle("推箱子");
this.setSize(900, 950);
this.setLayout(new FlowLayout());
this.setDefaultCloseOperation(3);
// 设置窗体居中
this.setLocationRelativeTo(null);
// 不可拉伸
this.setResizable(false);
JMenuBar menuBar = new JMenuBar();
this.add(menuBar, BorderLayout.NORTH);
JMenu menu = new JMenu("菜单");
menuBar.add(menu);
JMenuItem menuItem = new JMenuItem("选关");
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
GetLevelDialog dialog;
dialog = new GetLevelDialog();
if (dialog.getValue()!=0) {
diy = dialog.isdiy();
level = dialog.getValue();
GetMAP(level, diy);
}
}
});
menu.add(menuItem);
JMenuItem menuItem_1 = new JMenuItem("重新开始");
menuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 重新开始
GetMAP(level,diy);
}
});
menu.add(menuItem_1);
//JMenu menu_1 = new JMenu("\u81EA\u5B9A\u4E49");
//menuBar.add(menu_1);
//GetMAP(level, diy);
// 创建游戏面板
panel = setpanel();
this.add(panel);
this.setVisible(true);
// 安装键盘监听器
PanelListenner plis = new PanelListenner();
this.addKeyListener(plis);
// 启动刷新面板线程
UpdateThread ut = new UpdateThread(panel);
ut.start();
}
/**
* 读取地图数据
*
* @param level 关卡
* @param diy
*/
void GetMAP(int level, boolean diy) {
String stringdiy = "";
if (diy) {
stringdiy = "diy";
}
try {
DataInputStream in = new DataInputStream(
new BufferedInputStream(new FileInputStream(PATH + "\\" + stringdiy + level + ".map")));
int i = in.readInt();
int j = in.readInt();
for (int ii = 0; ii < i; ii++) {
for (int jj = 0; jj < j; jj++) {
map1[ii][jj][0] = in.readInt();
if (map1[ii][jj][0] == 5) {
playerx = ii;
playery = jj;
map1[ii][jj][0] = 1;
}
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* 自定义内部游戏面板类
*
*
*
*/
class MyPanel extends JPanel {
@Override
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < MAP_HEIGHT / SOUREC_HEIGHT; i++) {
for (int j = 0; j < MAP_WIDTH / SOUREC_WIDTH; j++) {
g.drawImage(GetGameImage(map1[i][j][0]), getDrawX(j), getDrawY(i), SOUREC_WIDTH, SOUREC_HEIGHT,
null);
}
}
g.drawImage(icon106.getImage(), getDrawX(playery), getDrawY(playerx), SOUREC_WIDTH, SOUREC_HEIGHT, null);
}
// 将数组下标转化成对应的图片左上角坐标
public int getDrawX(int j) {
int x = j * 50;
return x;
}
// 将数组下标转化成对应的图片左上角坐标
public int getDrawY(int i) {
int y = i * 50;
return y;
}
}
/**
* 设置游戏面板
*/
public JPanel setpanel() {
JPanel panel = new MyPanel();
panel.setPreferredSize(new Dimension(MAP_WIDTH, MAP_HEIGHT));
panel.setLayout(null);
panel.setBackground(Color.black);
return panel;
}
/**
* 获取到数字对应的图片
*
* @param i 数字
* @return
*/
Image GetGameImage(int i) {
if (i > 5) {
i = 0;
}
return allicons[i].getImage();
}
/**
* 内部游戏按键监听类
*/
class PanelListenner extends KeyAdapter {
// 当按键按下
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_UP:
if (check(1)) {
Move(1);
}
break;
case KeyEvent.VK_DOWN:
if (check(3)) {
Move(3);
}
break;
case KeyEvent.VK_LEFT:
if (check(2)) {
Move(2);
}
break;
case KeyEvent.VK_RIGHT:
if (check(4)) {
Move(4);
}
break;
case 87:
if (check(1)) {
Move(1);
}
break;
case 65:
if (check(3)) {
Move(3);
}
break;
case 83:
if (check(2)) {
Move(2);
}
break;
case 68:
if (check(4)) {
Move(4);
}
break;
default:
break;
}
if (IsSuccess()) {
GetNextMap();
}
}
}
/**
* 检查能不能走,前方有墙或者两个箱子超界等
*
* @param direction 方向 1234wasd
* @return
*/
boolean check(int direction) {
switch (direction) {
case 1:
// 判断1.超界 2.前面是墙 3.前面是箱子或者空箱子 再前面是箱子或者墙或者空箱子
if (playerx == 0) {
return false;
} else if (map1[playerx - 1][playery][0] == 0) {
return false;
} else if (map1[playerx - 1][playery][0] == 2 || map1[playerx - 1][playery][0] == 3) {
if (map1[playerx - 2][playery][0] == 2 || map1[playerx - 2][playery][0] == 3
|| map1[playerx - 2][playery][0] == 0) {
return false;
}
}
break;
case 2:
if (playery == 0) {
return false;
} else if (map1[playerx][playery - 1][0] == 0) {
return false;
} else if (map1[playerx][playery - 1][0] == 2 || map1[playerx][playery - 1][0] == 3) {
if (map1[playerx][playery - 2][0] == 2 || map1[playerx][playery - 2][0] == 3
|| map1[playerx][playery - 2][0] == 0) {
return false;
}
}
break;
case 3:
if (playerx == 17) {
return false;
} else if (map1[playerx + 1][playery][0] == 0) {
return false;
} else if (map1[playerx + 1][playery][0] == 2 || map1[playerx + 1][playery][0] == 3) {
if (map1[playerx + 2][playery][0] == 2 || map1[playerx + 2][playery][0] == 3
|| map1[playerx + 2][playery][0] == 0) {
return false;
}
}
break;
case 4:
if (playery == 17) {
return false;
} else if (map1[playerx][playery + 1][0] == 0) {
return false;
} else if (map1[playerx][playery + 1][0] == 2 || map1[playerx][playery + 1][0] == 3) {
if (map1[playerx][playery + 2][0] == 2 || map1[playerx][playery + 2][0] == 3
|| map1[playerx][playery + 2][0] == 0) {
return false;
}
}
break;
default:
break;
}
return true;
}
/**
* 角色移动
*
* @param direction 方向 1234wasd
*/
private void Move(int direction) {
// TODO Auto-generated method stub
switch (direction) {
// 0墙 1地板 2空箱子 3 箱子 4箱子点 5出生点
case 1:
if (map1[playerx - 1][playery][0] == 2) {
if (map1[playerx - 2][playery][0] == 4) {
map1[playerx - 1][playery][0] = 1;
map1[playerx - 2][playery][0] = 3;
} else {
map1[playerx - 1][playery][0] = 1;
map1[playerx - 2][playery][0] = 2;
}
} else if (map1[playerx - 1][playery][0] == 3) {
map1[playerx - 1][playery][0] = 4;
map1[playerx - 2][playery][0] = 2;
}
playerx -= 1;
break;
case 2:
if (map1[playerx][playery - 1][0] == 2) {
if (map1[playerx][playery - 2][0] == 4) {
map1[playerx][playery - 1][0] = 1;
map1[playerx][playery - 2][0] = 3;
} else {
map1[playerx][playery - 1][0] = 1;
map1[playerx][playery - 2][0] = 2;
}
} else if (map1[playerx][playery - 1][0] == 3) {
map1[playerx][playery - 1][0] = 4;
map1[playerx][playery - 2][0] = 2;
}
playery -= 1;
break;
case 3:
if (map1[playerx + 1][playery][0] == 2) {
if (map1[playerx + 2][playery][0] == 4) {
map1[playerx + 1][playery][0] = 1;
map1[playerx + 2][playery][0] = 3;
} else {
map1[playerx + 1][playery][0] = 1;
map1[playerx + 2][playery][0] = 2;
}
} else if (map1[playerx + 1][playery][0] == 3) {
map1[playerx + 1][playery][0] = 4;
map1[playerx + 2][playery][0] = 2;
}
playerx += 1;
break;
case 4:
if (map1[playerx][playery + 1][0] == 2) {
if (map1[playerx][playery + 2][0] == 4) {
map1[playerx][playery + 1][0] = 1;
map1[playerx][playery + 2][0] = 3;
} else {
map1[playerx][playery + 1][0] = 1;
map1[playerx][playery + 2][0] = 2;
}
} else if (map1[playerx][playery + 1][0] == 3) {
map1[playerx][playery + 1][0] = 4;
map1[playerx][playery + 2][0] = 2;
}
playery += 1;
break;
default:
break;
}
}
/**
* 检查是否成功,即地图上没有空箱子
* @return
*/
boolean IsSuccess() {
for (int i = 0; i < MAP_WIDTH/SOUREC_WIDTH; i++) {
for (int j = 0; j < MAP_HEIGHT/SOUREC_HEIGHT; j++) {
if (map1[i][j][0]==2) {
return false;
}
}
}
return true;
}
/**
* 闯过本关,开启下一关
*/
void GetNextMap() {
if (diy) {
if (Utils.IsExistence(PATH + "\\diy" + (level+1) + ".map")) {
JOptionPane.showMessageDialog(null, "下一关", "确定", JOptionPane.PLAIN_MESSAGE);
level++;
GetMAP(level, diy);
}else {
Success();
}
} else {
if (Utils.IsExistence(PATH + "\\" + (level+1) + ".map")) {
JOptionPane.showMessageDialog(null, "下一关", "确定", JOptionPane.PLAIN_MESSAGE);
level++;
GetMAP(level, diy);
}else {
Success();
}
}
}
/**
* 全部闯关成功,闯关成功即弹出提示且调到第一关或者其他操作
*/
void Success() {
JOptionPane.showMessageDialog(null, "恭喜你,全部闯关成功", "恭喜", JOptionPane.PLAIN_MESSAGE);
level=1;
GetMAP(level, diy);
}
}