In taught you to play games --JAVA GUI Sokoban (two) , we made the interface, this blog, we will try to move the character to achieve a Sokoban.
1. The role of mobile
We need to write a class monitor button, so that when we press to move around up and down about it.
Wherein, the key code is a value corresponding through System.out.println (code); we can easily obtain the corresponding key numbers we
/**
* 内部游戏按键监听类
*/
class PanelListenner extends KeyAdapter {
// 当按键按下
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
break;
case KeyEvent.VK_RIGHT:
break;
case 87:
// w
break;
case 65:
// a
break;
case 83:
// s
break;
case 68:
// d
break;
default:
break;
}
}
}
Keys well, we need to move ah
So, we need to make a move method, put the key inside the monitor
Which playerx coordinates for the role and playery
Move (1); shall go up.
/**
* 角色移动
* @param direction 方向 1234wasd
*/
private void Move(int direction) {
// TODO Auto-generated method stub
switch (direction) {
// 0墙 1地板 2空箱子 3 箱子 4箱子点 5出生点
case 1:
playerx -= 1;
break;
case 2:
playery -= 1;
break;
case 3:
playerx += 1;
break;
case 4:
playery += 1;
break;
default:
break;
}
}
Then we add the listener in the constructor. Was added and movement method in the listener class
However, still can not move, this is how it happened? In fact, ah, although we did a way to move, but we do not have to refresh the screen. So we need to do a thread to constantly refresh the interface can be achieved.
2. Refresh panel
New brush wire panels in succession Thread. Refresh panel once every 0.01 seconds. Wherein 10 is 10ms (milliseconds). Adjustable.
package cn.edu.caztc.sokobangame;
import javax.swing.JPanel;
public class UpdateThread extends Thread{
JPanel panel;
public UpdateThread(JPanel panel) {
this.panel = panel;
}
@Override
public void run() {
while(true){
panel.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Integration code, complete moving effect
package cn.edu.caztc.sokobangame;
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;
/**
* 游戏主体
*
* @author 莫言情难忘
*
*/
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) {
// System.out.println("选关");
}
});
menu.add(menuItem);
JMenuItem menuItem_1 = new JMenuItem("重新开始");
menuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 重新开始
}
});
menu.add(menuItem_1);
JMenuItem menuItem_2 = new JMenuItem("关于");
menuItem_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// System.out.println("关于");
JOptionPane.showMessageDialog(null, "莫言情难忘开发,csdn:莫言情难忘,个人QQ:1179307527", "关于",
JOptionPane.PLAIN_MESSAGE);
}
});
JMenu menu_1 = new JMenu("\u81EA\u5B9A\u4E49");
menuBar.add(menu_1);
JMenuItem menuItem_3 = new JMenuItem("地图编辑器");
menuItem_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
menu_1.add(menuItem_3);
menuBar.add(menuItem_2);
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
}
}
/**
* 自定义内部游戏面板类
*
* @author 莫言情难忘
*
*/
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:
Move(1);
break;
case KeyEvent.VK_DOWN:
Move(3);
break;
case KeyEvent.VK_LEFT:
Move(2);
break;
case KeyEvent.VK_RIGHT:
Move(4);
break;
case 87:
Move(1);
break;
case 65:
Move(3);
break;
case 83:
Move(2);
break;
case 68:
Move(4);
break;
default:
break;
}
}
}
/**
* 角色移动
*
* @param direction 方向 1234wasd
*/
private void Move(int direction) {
// TODO Auto-generated method stub
switch (direction) {
// 0墙 1地板 2空箱子 3 箱子 4箱子点 5出生点
case 1:
playerx -= 1;
break;
case 2:
playery -= 1;
break;
case 3:
playerx += 1;
break;
case 4:
playery += 1;
break;
default:
break;
}
}
}
3. collision judgment
Let's call it the collision judgment, although our role to move a success. But unscrupulous moving it is not good. We want to add restrictions.
Let's write a check method to determine whether it can be moved.
/**
* 检查能不能走,前方有墙或者两个箱子超界等
*
* @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;
}
Integrate this method into the code, although able to achieve limited functionality. But he did not Sokoban ah
so: We move to modify the method so that it can be achieved with some judgment Sokoban
/**
* 角色移动
*
* @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;
}
}
After the code integration and effectiveness
package cn.edu.caztc.sokobangame;
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;
/**
* 游戏主体
*
* @author 莫言情难忘
*
*/
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) {
// System.out.println("选关");
}
});
menu.add(menuItem);
JMenuItem menuItem_1 = new JMenuItem("重新开始");
menuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 重新开始
}
});
menu.add(menuItem_1);
JMenuItem menuItem_2 = new JMenuItem("关于");
menuItem_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// System.out.println("关于");
JOptionPane.showMessageDialog(null, "莫言情难忘开发,csdn:莫言情难忘,个人QQ:1179307527", "关于",
JOptionPane.PLAIN_MESSAGE);
}
});
JMenu menu_1 = new JMenu("\u81EA\u5B9A\u4E49");
menuBar.add(menu_1);
JMenuItem menuItem_3 = new JMenuItem("地图编辑器");
menuItem_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
menu_1.add(menuItem_3);
menuBar.add(menuItem_2);
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
}
}
/**
* 自定义内部游戏面板类
*
* @author 莫言情难忘
*
*/
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;
}
}
}
/**
* 检查能不能走,前方有墙或者两个箱子超界等
*
* @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;
}
}
}
Mo Yan love memorable 1179307527
See more:
Taught you do Sokoban game --JAVA GUI (a)