本篇博客主要是推箱子游戏界面功能的代码讲解。
首先先给出这段代码的部分运行截图:
重难点:
游戏界面主要有五个重难点:
固定好地图的位置
地图的显示
构建菜单栏
读取地图数据
玩家操作功能实现
地图的位置
首先是地图位置的确定,地图通过label的二维数组(大小为20*20)来显示,确定好位置后,只需要改变每个label上显示的图片,就可以显示不同的地图。label就像显示屏,根据需要显示不同内容。
JLabel[][] jl=new JLabel[20][20];//20*20的label,用于显示地图
for(int i=0;i<20;i++) {
//实例化label数组,并设置各label的大小和位置
for(int j=0;j<20;j++) {
jl[i][j]=new JLabel();
this.add(jl[i][j]);
jl[i][j].setBounds(i*30, j*30+40, 30, 30);
}
}
地图的显示
其次是地图的显示,固定好每个label的位置后,根据地图数据显示相对应的图片,而地图数据由mymap二维数组存放。每次移动只需改变二维数组的数据,再通过方法将新的地图内容显示。
public void paint() {
ImageIcon[] icon = new ImageIcon[7];//icon数组
//各种图片路径设置,根据实际自行修改
icon[0] = new ImageIcon();
icon[1] = new ImageIcon("shiyan4_image/wall.png"); //墙
icon[2] = new ImageIcon();
icon[3] = new ImageIcon("shiyan4_image/box1.png"); //箱子
icon[4] = new ImageIcon("shiyan4_image/destination.png"); //目的地
icon[5] = new ImageIcon("shiyan4_image/player.png"); //玩家
icon[6] = new ImageIcon("shiyan4_image/box2.png"); //到达目的地的箱子
//显示地图内容
for(int i=0;i<20;i++) {
for(int j=0;j<20;j++) {
jl[i][j].setIcon(icon[mymap[i][j]]);
}
}
}
菜单栏
添加菜单栏来是实现对游戏各种功能的控制,可以执行上一关,下一关,重新开始本关,返回首页等操作
public void MENU() {
//菜单栏位置和大小
menuBar.setBounds(0, 0, 900, 20);
//菜单栏内容
JMenu menu_1 = new JMenu("菜单");
JMenu menu_2 = new JMenu("更多");
//菜单条目
JMenuItem menuItem_1 = new JMenuItem("下一关");
JMenuItem menuItem_5 = new JMenuItem("上一关");
JMenuItem menuItem_2 = new JMenuItem("重新开始");
JMenuItem menuItem_3 = new JMenuItem("返回首页");
JMenuItem menuItem_4 = new JMenuItem("关于我们");
//添加控件
menuBar.add(menu_1);
menuBar.add(menu_2);
menu_1.add(menuItem_1);
menu_1.add(menuItem_5);
menu_1.add(menuItem_2);
menu_1.add(menuItem_3);
menu_2.add(menuItem_4);
//每一栏添加事件
menuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//菜单栏事件
}
});
menuItem_5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//菜单栏事件
}
});
menuItem_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//菜单栏事件
}
});
menuItem_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//菜单栏事件
}
});
menuItem_4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//菜单栏事件
}
});
}
也可以为菜单栏添加快捷键,这样通过键盘也可以实现上述功能,更加的便捷。
地图的读取
这个游戏的地图一般以文件形式存储在文件夹中,根据关卡读取文件的数据,并将数据存放到mymap数组中。
public void readmap(int k) {
//读取第k关的地图
BufferedReader br = null;
String bb="";
int c=0;
String s;
try
{
File f;
f=new File("shiyan4_maps\\"+k+".map");//地图文件地址,根据实际修改路径
br=new BufferedReader(new FileReader(f));
while ((s=br.readLine())!=null)//读取文件每一行,不为空添加到bb中
{
bb=bb+s;
}
}
catch (IOException e)//异常抛出
{
System.out.println(e);
}
byte[] d=bb.getBytes();//读取bb中的每一个字节,存放到d数组中
int[] x=new int[bb.length()];
for(int i=0;i<bb.length();i++)x[i]=d[i]-48;//每个字节从char数字变成int数字
for(int i=0;i<20;i++)
{
for(int j=0;j<20;j++)//将数据存到mymap数组中
{
mymap[j][i]=x[c];
c++;
}
}
}
玩家控制功能
通过上下左右键控制玩家箱子的移动,且要列举出所有可能的移动情况,根据情况来写各种移动结果。
以左移为例
可能出现的大致情况:
左侧为墙体:
不移动
左侧为箱子:
(分两种情况)
1.左侧的左侧为墙体,箱子,到达目的地 的箱子:不移动
2.左侧没障碍:可以移动
左侧为目的地:
移动后做好标记,离开时要重新显示目的地
下面是根据上面的情况细分后写出的代码:
public void key_left() {
int x=player_x;
int y=player_y;
//1为墙体,0和2为空白,3为箱子,4为目的地,5为玩家操控,6为到达目的地的箱子
if(mymap[x-1][y]==1) {
}
else if(mymap[x-1][y]==3) {
if(mymap[x-2][y]==1||mymap[x-2][y]==3||mymap[x-2][y]==6) {
}
else if(pd==1) {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}}
else {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}}
}
else if(mymap[x-1][y]==6) {
if(mymap[x-2][y]==1||mymap[x-2][y]==3||mymap[x-2][y]==6) {
step--;}
else if(pd==1) {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}}
else {
if(mymap[x-2][y]==4){
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}}
}
else if(mymap[x-1][y]==4) {
if(pd==1) {
mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}else {
mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}}
else {
if(pd==1) {
mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}
else {
mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}}
player_x=x;
player_y=y;
paint();//移动后重新显示新的地图
}
最后附上本块内容完整的代码和运行截图
游戏界面完整代码
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.*;
public class game_tui_2 extends JFrame{
JLabel[][] jl=new JLabel[20][20];//20*20的label,用于显示地图
int[][] mymap =new int[20][20];//二维数组,用于存储地图数据
JLabel jb_title =new JLabel();//显示第几关
JLabel jb_step=new JLabel();//显示第几步
JMenuBar menuBar = new JMenuBar();//菜单栏
int level=1,player_x=0,player_y=0;
int pd=0,step=0,MAX_level=10;
public game_tui_2() {
for(int i=0;i<20;i++) {
//实例化label数组,并设置各label的大小和位置
for(int j=0;j<20;j++) {
jl[i][j]=new JLabel();
this.add(jl[i][j]);
jl[i][j].setBounds(i*30, j*30+40, 30, 30);
}
}
//向窗体添加控件
this.add(jb_title);
this.add(jb_step);
this.add(menuBar);
jb_title.setBounds(670, 300, 100, 40);
jb_title.setFont(new java.awt.Font("Dialog", 1, 30));//设置字体
jb_step.setBounds(660, 400, 150, 40);
jb_step.setFont(new java.awt.Font("Dialog", 1, 20));//设置字体
//自己定义的函数
MENU();//设置菜单的内容
read_paint_map(level);
//添加键盘事件
this.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if(pd_victory()==1) {
}
else if(e.getKeyCode()==KeyEvent.VK_UP) {
step++;jb_step.setText("本关走了:"+step+"步");key_up();}
else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
step++;jb_step.setText("本关走了:"+step+"步");key_down();}
else if(e.getKeyCode()==KeyEvent.VK_LEFT) {
step++;jb_step.setText("本关走了:"+step+"步");key_left();}
else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
step++;jb_step.setText("本关走了:"+step+"步");key_right();}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
});
//窗体属性
this.setTitle("推箱子");//窗体名称
this.setSize(900, 730);//窗体大小
this.setDefaultCloseOperation(3);//窗体关闭按钮功能
this.setLocationRelativeTo(null);//窗体居中
this.setResizable(false);//窗体不可拉伸
this.setLayout(null);//null可以使控件放到任意位置
this.setVisible(true);//窗体可视
}
public int pd_victory() {
//判断胜利条件是否满足
for(int i=0;i<20;i++) {
for(int j=0;j<20;j++) {
if(mymap[i][j]==4||mymap[i][j]==3) {
return 0;}
}
}
return 1;
}
public void MENU() {
//菜单栏位置和大小
menuBar.setBounds(0, 0, 900, 20);
//菜单栏内容
JMenu menu_1 = new JMenu("菜单(E)");
JMenu menu_2 = new JMenu("更多(T)");
//快捷键
menu_1.setMnemonic(KeyEvent.VK_E);
menu_2.setMnemonic(KeyEvent.VK_T);
//菜单条目
JMenuItem menuItem_1 = new JMenuItem("下一关(V)");
JMenuItem menuItem_5 = new JMenuItem("上一关(B)");
JMenuItem menuItem_2 = new JMenuItem("重新开始(N)");
JMenuItem menuItem_3 = new JMenuItem("返回首页(M)");
JMenuItem menuItem_4 = new JMenuItem("关于我们(H)");
//快捷键
menuItem_1.setMnemonic(KeyEvent.VK_V);
menuItem_5.setMnemonic(KeyEvent.VK_B);
menuItem_2.setMnemonic(KeyEvent.VK_N);
menuItem_3.setMnemonic(KeyEvent.VK_M);
menuItem_4.setMnemonic(KeyEvent.VK_H);
//添加控件
menuBar.add(menu_1);
menuBar.add(menu_2);
menu_1.add(menuItem_1);
menu_1.add(menuItem_5);
menu_1.add(menuItem_2);
menu_1.add(menuItem_3);
menu_2.add(menuItem_4);
//每一栏添加事件
menuItem_1.addActionListener(new ActionListener() {
//下一关
public void actionPerformed(ActionEvent arg0) {
if(level!=MAX_level) {
read_paint_map(++level);}
else JOptionPane.showMessageDialog(null, "已经是最后一关了!!", "警告",JOptionPane.WARNING_MESSAGE);
}
});
menuItem_5.addActionListener(new ActionListener() {
//上一关
public void actionPerformed(ActionEvent arg0) {
if(level!=1) {
read_paint_map(--level);}
else JOptionPane.showMessageDialog(null, "已经是第一关了!!", "警告",JOptionPane.WARNING_MESSAGE);
}
});
menuItem_2.addActionListener(new ActionListener() {
//重新开始
public void actionPerformed(ActionEvent arg0) {
read_paint_map(level);
}
});
menuItem_3.addActionListener(new ActionListener() {
//返回首页
public void actionPerformed(ActionEvent e) {
//new game_tui_1();
//dispose();
//由于单独代码,做了注释处理
}
});
menuItem_4.addActionListener(new ActionListener() {
//关于我们
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "java小游戏\n经供参考\n版本:7.1.5\n", "关于我们",JOptionPane.PLAIN_MESSAGE);
}
});
}
public void read_paint_map(int k) {
//读取与绘制地图
step=0;
jb_step.setText("本关走了:"+step+"步");
jb_title.setText("第"+k+"关");
readmap(k);//读取地图文件
for(int i=0;i<20;i++) {
for(int j=0;j<20;j++) {
if(mymap[i][j]==5) {
player_x=i;player_y=j;//获取玩家操控人物的位置
}
}
}
paint();//绘制地图
}
public void paint() {
//绘制地图
ImageIcon[] icon = new ImageIcon[7];//icon数组
//各种图片路径设置,根据实际自行修改
icon[0] = new ImageIcon();
icon[1] = new ImageIcon("shiyan4_image/wall.png"); //墙
icon[2] = new ImageIcon();
icon[3] = new ImageIcon("shiyan4_image/box1.png"); //箱子
icon[4] = new ImageIcon("shiyan4_image/destination.png"); //目的地
icon[5] = new ImageIcon("shiyan4_image/player.png"); //玩家
icon[6] = new ImageIcon("shiyan4_image/box2.png"); //到达目的地的箱子
//显示地图内容
for(int i=0;i<20;i++) {
for(int j=0;j<20;j++) {
jl[i][j].setIcon(icon[mymap[i][j]]);
}
}
if(pd_victory()==1) {
JOptionPane.showMessageDialog(null, " 恭喜你通过本关!!", "消息",
JOptionPane.PLAIN_MESSAGE);
if(level!=MAX_level) {
read_paint_map(++level);}
else JOptionPane.showMessageDialog(null, " 你已经完成所有关卡!!!", "恭喜",
JOptionPane.PLAIN_MESSAGE);}
}
public void readmap(int k) {
//读取第k关的地图
BufferedReader br = null;
String bb="";
int c=0;
String s;
try
{
File f
f=new File("shiyan4_maps\\"+k+".map");//地图文件地址,根据实际自行修改路径
br=new BufferedReader(new FileReader(f));
while ((s=br.readLine())!=null)//读取文件每一行,不为空添加到bb中
{
bb=bb+s;
}
}
catch (IOException e)//异常抛出
{
System.out.println(e);
}
byte[] d=bb.getBytes();//读取bb中的每一个字节,存放到d数组中
int[] x=new int[bb.length()];
for(int i=0;i<bb.length();i++)x[i]=d[i]-48;//每个字节从char数字变成int数字
for(int i=0;i<20;i++)
{
for(int j=0;j<20;j++)//将数据存到mymap数组中
{
mymap[j][i]=x[c];
c++;
}
}
}
public void key_up() {
//上移
int x=player_x;
int y=player_y;
if(mymap[x][y-1]==1) {
step--;}
else if(mymap[x][y-1]==3) {
if(mymap[x][y-2]==1||mymap[x][y-2]==3||mymap[x][y-2]==6) {
step--;}
else if(pd==1) {
if(mymap[x][y-2]==4) {
mymap[x][y-2]=6;mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;pd=0;}
else {
mymap[x][y-2]=3;mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;pd=0;}}
else {
if(mymap[x][y-2]==4) {
mymap[x][y-2]=6;mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;}
else {
mymap[x][y-2]=3;mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;}}
}
else if(mymap[x][y-1]==6) {
if(mymap[x][y-2]==1||mymap[x][y-2]==3||mymap[x][y-2]==6) {
step--;}
else if(pd==1) {
if(mymap[x][y-2]==4) {
mymap[x][y-2]=6;mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;}
else {
mymap[x][y-2]=3;mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;}}
else {
if(mymap[x][y-2]==4){
mymap[x][y-2]=6;mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;pd=1;}
else {
mymap[x][y-2]=3;mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;pd=1;}}
}
else if(mymap[x][y-1]==4) {
if(pd==1) {
mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;}else {
mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;pd=1;}}
else {
if(pd==1) {
mymap[x][y-1]=5;mymap[x][y]=4;y=y-1;pd=0;}
else {
mymap[x][y-1]=5;mymap[x][y]=2;y=y-1;}}
player_x=x;
player_y=y;
paint();
}
public void key_down() {
//下移
int x=player_x;
int y=player_y;
if(mymap[x][y+1]==1) {
step--;}
else if(mymap[x][y+1]==3) {
if(mymap[x][y+2]==1||mymap[x][y+2]==3||mymap[x][y+2]==6) {
step--;}
else if(pd==1) {
if(mymap[x][y+2]==4) {
mymap[x][y+2]=6;mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;pd=0;}
else {
mymap[x][y+2]=3;mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;pd=0;}}
else {
if(mymap[x][y+2]==4) {
mymap[x][y+2]=6;mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;}
else {
mymap[x][y+2]=3;mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;}}
}
else if(mymap[x][y+1]==6) {
if(mymap[x][y+2]==1||mymap[x][y+2]==3||mymap[x][y+2]==6) {
step--;}
else if(pd==1) {
if(mymap[x][y+2]==4) {
mymap[x][y+2]=6;mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;}
else {
mymap[x][y+2]=3;mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;}}
else {
if(mymap[x][y+2]==4){
mymap[x][y+2]=6;mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;pd=1;}
else {
mymap[x][y+2]=3;mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;pd=1;}}
}
else if(mymap[x][y+1]==4) {
if(pd==1) {
mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;}else {
mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;pd=1;}}
else {
if(pd==1) {
mymap[x][y+1]=5;mymap[x][y]=4;y=y+1;pd=0;}
else {
mymap[x][y+1]=5;mymap[x][y]=2;y=y+1;}}
player_x=x;
player_y=y;
paint();
}
public void key_left() {
//左移
int x=player_x;
int y=player_y;
if(mymap[x-1][y]==1) {
step--;}
else if(mymap[x-1][y]==3) {
if(mymap[x-2][y]==1||mymap[x-2][y]==3||mymap[x-2][y]==6) {
step--;}
else if(pd==1) {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}}
else {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}}
}
else if(mymap[x-1][y]==6) {
if(mymap[x-2][y]==1||mymap[x-2][y]==3||mymap[x-2][y]==6) {
step--;}
else if(pd==1) {
if(mymap[x-2][y]==4) {
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}}
else {
if(mymap[x-2][y]==4){
mymap[x-2][y]=6;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}
else {
mymap[x-2][y]=3;mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}}
}
else if(mymap[x-1][y]==4) {
if(pd==1) {
mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;}else {
mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;pd=1;}}
else {
if(pd==1) {
mymap[x-1][y]=5;mymap[x][y]=4;x=x-1;pd=0;}
else {
mymap[x-1][y]=5;mymap[x][y]=2;x=x-1;}}
player_x=x;
player_y=y;
paint();
}
public void key_right() {
//右移
int x=player_x;
int y=player_y;
if(mymap[x+1][y]==1) {
step--;}
else if(mymap[x+1][y]==3) {
if(mymap[x+2][y]==1||mymap[x+2][y]==3||mymap[x+2][y]==6) {
step--;}
else if(pd==1) {
if(mymap[x+2][y]==4) {
mymap[x+2][y]=6;mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;pd=0;}
else {
mymap[x+2][y]=3;mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;pd=0;}}
else {
if(mymap[x+2][y]==4) {
mymap[x+2][y]=6;mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;}
else {
mymap[x+2][y]=3;mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;}}
}
else if(mymap[x+1][y]==6) {
if(mymap[x+2][y]==1||mymap[x+2][y]==3||mymap[x+2][y]==6) {
step--;}
else if(pd==1) {
if(mymap[x+2][y]==4) {
mymap[x+2][y]=6;mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;}
else {
mymap[x+2][y]=3;mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;}}
else {
if(mymap[x+2][y]==4){
mymap[x+2][y]=6;mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;pd=1;}
else {
mymap[x+2][y]=3;mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;pd=1;}}
}
else if(mymap[x+1][y]==4) {
if(pd==1) {
mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;}else {
mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;pd=1;}}
else {
if(pd==1) {
mymap[x+1][y]=5;mymap[x][y]=4;x=x+1;pd=0;}
else {
mymap[x+1][y]=5;mymap[x][y]=2;x=x+1;}}
player_x=x;
player_y=y;
paint();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new game_tui_2();
}
}