推箱子
main.js
js
/* 入口模块,用来执行其它模块,做整体模块的整合执行,例如数据监控等功能 */
import "./game.js";
map.js
js
/* 地图模块 */
export const SPACE = 0;
export const PLAYER = 1;
export const WALL = 2;
export const BOX = 3;
//地图上所有元素的坐标
export const mapPoint = [
[0, 0, 2, 2, 2, 2, 2, 0, 0],
[0, 0, 2, 0, 1, 0, 2, 0, 0],
[0, 0, 2, 0, 3, 0, 2, 0, 0],
[2, 2, 2, 0, 0, 0, 2, 2, 2],
[2, 0, 0, 0, 3, 0, 0, 0, 2],
[2, 0, 3, 3, 3, 3, 3, 0, 2],
[2, 0, 0, 0, 3, 0, 0, 0, 2],
[2, 2, 0, 3, 3, 3, 0, 2, 2],
[0, 2, 0, 0, 0, 0, 0, 2, 0],
[0, 2, 0, 0, 3, 0, 0, 2, 0],
[0, 2, 0, 0, 0, 0, 0, 2, 0],
[0, 2, 2, 2, 2, 2, 2, 2, 0],
];
// 箱子正确的点位
export const correctPoint = [
{ row: 3, col: 4 },
{ row: 4, col: 4 },
{ row: 5, col: 2 },
{ row: 5, col: 3 },
{ row: 5, col: 4 },
{ row: 5, col: 5 },
{ row: 5, col: 6 },
{ row: 6, col: 4 },
{ row: 7, col: 4 },
{ row: 8, col: 4 },
{ row: 9, col: 4 },
{ row: 10, col: 4 },
];
// 游戏界面盒子的宽高
export const gameWidth = mapPoint[0].length * 45;
export const gameHeight = mapPoint.length * 45;
game.js
js
/* game模块,用来整合整个模块,并且监听事件 */
import playerMove, { UP, DOWN, LEFT, RIGHT, isWin } from "./play.js";
import initMap from "./ui.js";
//页面添加dom元素
initMap();
// 绑定事件
let gameover = false;
window.addEventListener("keydown", function (e) {
if (gameover) return;
let res = false;
if (e.key === "ArrowUp") {
res = playerMove(UP);
} else if (e.key === "ArrowDown") {
res = playerMove(DOWN);
} else if (e.key === "ArrowLeft") {
res = playerMove(LEFT);
} else if (e.key === "ArrowRight") {
res = playerMove(RIGHT);
}
if (res) {
initMap();
if (isWin()) {
gameover = true;
console.log("游戏结束");
}
}
});
play.js
js
/* 操作模块,用来实现操作的逻辑 */
import * as Map from "./map.js";
//
export const UP = "up";
export const DOWN = "down";
export const LEFT = "left";
export const RIGHT = "right";
/**
*玩家移动的函数
* @param {*} direction 方向:up down left right
* @returns {boolean} 是否可以移动
*/
function playerMove(direction) {
const player = getPlayerPoint();
const next = getNextPoint(direction, player.row, player.col);
if (next.value === Map.WALL) {
return false;
} else if (next.value === Map.SPACE) {
exchange(player, next);
return true;
} else if (next.value === Map.BOX) {
const nextNext = getNextPoint(direction, next.row, next.col);
if (nextNext.value === Map.SPACE) {
exchange(next, nextNext);
exchange(player, next);
return true;
} else {
return false;
}
}
}
/**
*
* @param {*} direction 将移动的方向
* @param {*} row 当前行
* @param {*} col 当前列
* @returns 下一个位置的坐标点信息{row:下个位置的行,col:下个位置的列,value:地图上该处的值 0|1|2|3}
*/
function getNextPoint(direction, row, col) {
if (direction === UP) {
return {
row: row - 1,
col,
value: Map.mapPoint[row - 1][col],
};
} else if (direction === DOWN) {
return {
row: row + 1,
col,
value: Map.mapPoint[row + 1][col],
};
} else if (direction === LEFT) {
return {
row,
col: col - 1,
value: Map.mapPoint[row][col - 1],
};
} else if (direction === RIGHT) {
return {
row,
col: col + 1,
value: Map.mapPoint[row][col + 1],
};
}
}
/**
* 获取当前玩家所在的行和列
* @returns row:当前行,col:当前列 {row,col,value}
*/
function getPlayerPoint() {
/* forEach中使用return只会终止当前循环,立即进入下一次循环 */
let playerInfo = null;
Map.mapPoint.forEach((_row, rowIndex) => {
_row.forEach((_col, colIndex) => {
if (_col === Map.PLAYER) {
playerInfo = {
row: rowIndex,
col: colIndex,
value: _col,
};
}
});
});
if (playerInfo) return playerInfo;
throw new Error("没有找到玩家");
}
/**
* 交换地图中玩家与点位的位置
* @param point1 玩家当前位置信息
* @param point2 下一个点位信息
*/
function exchange(point1, point2) {
[Map.mapPoint[point2.row][point2.col], Map.mapPoint[point1.row][point1.col]] =
[
Map.mapPoint[point1.row][point1.col],
Map.mapPoint[point2.row][point2.col],
];
// ...
}
/**判断箱子是否全部在正确的点位 */
export function isWin() {
return Map.correctPoint.every(
(item) => Map.mapPoint[item.row][item.col] === Map.BOX
);
}
export default playerMove;
ui.js
js
/* UI模块,用来渲染页面 */
import * as Map from "./map.js";
//
const ogame = document.querySelector("#game");
const eleWidth = 45;
const eleHeight = 45;
/**
*设置一个元素到#game容器中
* @param {*} row 要新增元素的行坐标
* @param {*} col 要新增元素的列坐标
*/
function setOneItem(row, col) {
const div = document.createElement("div");
div.classList.add("item");
div.style.left = col * eleWidth + "px";
div.style.top = row * eleHeight + "px";
const type = Map.mapPoint[row][col];
const isRight = isRightPoint(row, col);
// console.log("type", type);
if (type === Map.PLAYER) {
div.classList.add("player");
} else if (type === Map.WALL) {
div.classList.add("wall");
} else if (type === Map.BOX) {
if (isRight) {
div.classList.add("correct-box");
} else {
div.classList.add("box");
}
} else {
if (isRight) {
div.classList.add("correct");
} else {
return;
}
}
ogame.appendChild(div);
}
/**
* 判断是否在正确的位置
* @param {*} row 行数
* @param {*} col 列数
* @returns boolean 在true 不在false
*/
function isRightPoint(row, col) {
return (
Map.correctPoint.find((item) => row === item.row && col === item.col) !==
undefined
);
}
// 设置总容器
function createContainer() {
ogame.style.width = Map.gameWidth + "px";
ogame.style.height = Map.gameHeight + "px";
}
//设置dom内容
function setDom() {
ogame.innerHTML = "";
Map.mapPoint.forEach((_rowItem, rowIndex) => {
_rowItem.forEach((_colItem, colIndex) => {
// console.log(rowIndex, colIndex);
setOneItem(rowIndex, colIndex);
});
});
}
export default function () {
createContainer();
setDom();
}