ADD file via upload

main
p6xlcrq3f 4 months ago
parent 0f0066ab4a
commit f7dbc3406a

@ -0,0 +1,376 @@
package cn.edu.caztc.sokobangame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class DualGame extends JFrame implements MapConfig {
private int[][][] map1;
private int player1x = -1, player1y = -1;
private int player2x = -1, player2y = -1;
private int level = 1;
private boolean diy = false;
private JPanel panel;
private static DualGame instance;
private ImageIcon[] currentIcons;
private UpdateThread updateThread;
public static DualGame getInstance() {
return instance;
}
public DualGame() {
instance = this;
currentIcons = ThemeSwitcher.getCurrentThemeIcons().clone();
initUI();
loadInitialMap();
setVisible(true);
}
public void updateTheme(ImageIcon[] newIcons) {
currentIcons = newIcons.clone();
panel.repaint();
}
private void initUI() {
setTitle("推箱子-双人模式");
setSize(900, 950);
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
initMenu();
initGamePanel();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cleanupResources();
System.out.println("双人模式程序终止"); // 添加终止信息
}
});
}
private void initMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("菜单");
JMenuItem levelItem = new JMenuItem("选关");
levelItem.addActionListener(e -> selectLevel());
menu.add(levelItem);
JMenuItem restartItem = new JMenuItem("重新开始");
restartItem.addActionListener(e -> GetMAP(level, diy));
menu.add(restartItem);
JMenuItem singleModeItem = new JMenuItem("切换到单人模式");
singleModeItem.addActionListener(e -> switchToSingleMode());
menu.add(singleModeItem);
menuBar.add(menu);
setJMenuBar(menuBar);
}
private void initGamePanel() {
panel = new DualPanel();
panel.setPreferredSize(new Dimension(MAP_WIDTH, MAP_HEIGHT));
panel.setBackground(Color.BLACK);
add(panel);
panel.setFocusable(true);
panel.requestFocusInWindow();
panel.addKeyListener(new DualKeyListener());
}
private void loadInitialMap() {
GetMAP(1, false);
updateThread = new UpdateThread(panel);
updateThread.start();
}
private void cleanupResources() {
MusicPlayer.getInstance().stopMusic();
if (updateThread != null) {
updateThread.stopRunning();
}
}
void GetMAP(int level, boolean diy) {
String prefix = diy ? "双人diy" : "双人";
String filePath = PATH + "\\" + prefix + level + ".map";
try {
File mapFile = new File(filePath);
loadMapData(filePath);
validateSpawnPoints();
} catch (Exception e) {
JOptionPane.showMessageDialog(null,
"地图加载失败: " + e.getMessage() + "\n文件路径: " + filePath,
"错误", JOptionPane.ERROR_MESSAGE);
}
refreshGameDisplay();
}
private void loadMapData(String filePath) throws IOException {
try (DataInputStream in = new DataInputStream(
new BufferedInputStream(new FileInputStream(filePath)))) {
resetPlayerPositions();
int rows = in.readInt();
int cols = in.readInt();
map1 = new int[rows][cols][1];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int cellValue = in.readInt();
map1[i][j][0] = cellValue;
if (cellValue == 5) { // 玩家一出生点
player1x = i;
player1y = j;
map1[i][j][0] = 1; // 出生点变为空地
} else if (cellValue == 6) { // 玩家二出生点
player2x = i;
player2y = j;
map1[i][j][0] = 1; // 出生点变为空地
}
}
}
}
}
private void validateSpawnPoints() {
if (player1x == -1 || player2x == -1) {
JOptionPane.showMessageDialog(null,
"地图必须包含两个出生点(5-玩家一,6-玩家二)", "错误", JOptionPane.ERROR_MESSAGE);
}
}
class DualPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
if (map1 != null) {
for (int i = 0; i < map1.length; i++) {
for (int j = 0; j < map1[0].length; j++) {
int cellValue = map1[i][j][0];
if (cellValue >= 0 && cellValue < currentIcons.length) { // 使用currentIcons
Image img = currentIcons[cellValue].getImage();
if (img != null) {
g.drawImage(img, j*SOUREC_WIDTH, i*SOUREC_HEIGHT,
SOUREC_WIDTH, SOUREC_HEIGHT, this);
}
}
}
}
}
// 绘制玩家同样使用currentIcons
if (player1x >= 0 && player1y >= 0) {
g.drawImage(currentIcons[5].getImage(), player1y*SOUREC_WIDTH, player1x*SOUREC_HEIGHT,
SOUREC_WIDTH, SOUREC_HEIGHT, this);
}
if (player2x >= 0 && player2y >= 0) {
g.drawImage(currentIcons[6].getImage(), player2y*SOUREC_WIDTH, player2x*SOUREC_HEIGHT,
SOUREC_WIDTH, SOUREC_HEIGHT, this);
}
}
}
class DualKeyListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP: tryMove(1, 1); break;
case KeyEvent.VK_DOWN: tryMove(1, 3); break;
case KeyEvent.VK_LEFT: tryMove(1, 2); break;
case KeyEvent.VK_RIGHT: tryMove(1, 4); break;
case KeyEvent.VK_W: tryMove(2, 1); break;
case KeyEvent.VK_S: tryMove(2, 3); break;
case KeyEvent.VK_A: tryMove(2, 2); break;
case KeyEvent.VK_D: tryMove(2, 4); break;
}
panel.repaint();
}
private void tryMove(int playerNum, int direction) {
if (canMove(playerNum, direction)) {
if (isPushingBox(playerNum, direction)) {
if (canPushBox(playerNum, direction)) {
movePlayer(playerNum, direction);
}
} else {
movePlayer(playerNum, direction);
}
if (IsSuccess()) {
Success();
}
}
}
}
// 其他辅助方法...
private void movePlayer(int playerNum, int direction) {
int x = playerNum == 1 ? player1x : player2x;
int y = playerNum == 1 ? player1y : player2y;
int newX = x, newY = y;
int frontX = x, frontY = y;
int beyondX = x, beyondY = y;
switch (direction) {
case 1: newX--; frontX--; beyondX -= 2; break;
case 2: newY--; frontY--; beyondY -= 2; break;
case 3: newX++; frontX++; beyondX += 2; break;
case 4: newY++; frontY++; beyondY += 2; break;
}
if ((playerNum == 1 && newX == player2x && newY == player2y) ||
(playerNum == 2 && newX == player1x && newY == player1y)) {
return;
}
if (map1[frontX][frontY][0] == 2 || map1[frontX][frontY][0] == 3) {
if ((beyondX == player1x && beyondY == player1y) ||
(beyondX == player2x && beyondY == player2y)) {
return;
}
map1[beyondX][beyondY][0] = (map1[beyondX][beyondY][0] == 4) ? 3 : 2;
map1[frontX][frontY][0] = (map1[frontX][frontY][0] == 3) ? 4 : 1;
}
if (playerNum == 1) {
player1x = newX;
player1y = newY;
} else {
player2x = newX;
player2y = newY;
}
}
boolean IsSuccess() {
for (int i = 0; i < map1.length; i++) {
for (int j = 0; j < map1[0].length; j++) {
if (map1[i][j][0] == 2) {
return false;
}
}
}
return true;
}
void Success() {
String prefix = diy ? "双人diy" : "双人";
// 先检查是否是最后一关
if (!new File(PATH + "\\" + prefix + (level+1) + ".map").exists()) {
// 是最后一关
JOptionPane.showMessageDialog(null,
"恭喜您已通关所有关卡!",
"全部通关", JOptionPane.INFORMATION_MESSAGE);
level = 1;
GetMAP(level, diy);
} else {
// 不是最后一关
JOptionPane.showMessageDialog(null,
"恭喜通关!即将进入下一关",
"成功", JOptionPane.INFORMATION_MESSAGE);
GetNextMap();
}
}
void GetNextMap() {
String prefix = diy ? "双人diy" : "双人";
level++;
GetMAP(level, diy);
}
private void refreshGameDisplay() {
panel.repaint();
panel.requestFocusInWindow();
}
private void selectLevel() {
GetLevelDialog dialog = new GetLevelDialog(true);
if (dialog.getValue() != 0) {
diy = dialog.isdiy();
level = dialog.getValue();
GetMAP(level, diy);
}
}
private void switchToSingleMode() {
new MainGame().setVisible(true);
dispose();
}
private void resetPlayerPositions() {
player1x = player1y = player2x = player2y = -1;
}
private boolean canMove(int playerNum, int direction) {
int x = playerNum == 1 ? player1x : player2x;
int y = playerNum == 1 ? player1y : player2y;
switch (direction) {
case 1: return x > 0 && map1[x-1][y][0] != 0;
case 2: return y > 0 && map1[x][y-1][0] != 0;
case 3: return x < map1.length-1 && map1[x+1][y][0] != 0;
case 4: return y < map1[0].length-1 && map1[x][y+1][0] != 0;
}
return false;
}
private boolean isPushingBox(int playerNum, int direction) {
int x = playerNum == 1 ? player1x : player2x;
int y = playerNum == 1 ? player1y : player2y;
switch (direction) {
case 1: return x > 0 && (map1[x-1][y][0] == 2 || map1[x-1][y][0] == 3);
case 2: return y > 0 && (map1[x][y-1][0] == 2 || map1[x][y-1][0] == 3);
case 3: return x < map1.length-1 && (map1[x+1][y][0] == 2 || map1[x+1][y][0] == 3);
case 4: return y < map1[0].length-1 && (map1[x][y+1][0] == 2 || map1[x][y+1][0] == 3);
}
return false;
}
private boolean canPushBox(int playerNum, int direction) {
int x = playerNum == 1 ? player1x : player2x;
int y = playerNum == 1 ? player1y : player2y;
int frontX = x, frontY = y;
int beyondX = x, beyondY = y;
switch (direction) {
case 1: frontX--; beyondX -= 2; break;
case 2: frontY--; beyondY -= 2; break;
case 3: frontX++; beyondX += 2; break;
case 4: frontY++; beyondY += 2; break;
}
if (frontX < 0 || frontY < 0 ||
frontX >= map1.length || frontY >= map1[0].length ||
(map1[frontX][frontY][0] != 2 && map1[frontX][frontY][0] != 3)) {
return false;
}
if (beyondX < 0 || beyondY < 0 ||
beyondX >= map1.length || beyondY >= map1[0].length ||
map1[beyondX][beyondY][0] == 0 ||
map1[beyondX][beyondY][0] == 2 ||
map1[beyondX][beyondY][0] == 3) {
return false;
}
return true;
}
}
Loading…
Cancel
Save