You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.6 KiB
135 lines
3.6 KiB
import "./snake.css";
|
|
import SnakeModel from "./core/model";
|
|
|
|
// view
|
|
import SnakeView from "./core/view";
|
|
|
|
// control
|
|
import SnakeControl from "./core/control";
|
|
|
|
export default class SnakeClass extends SnakeControl {
|
|
constructor({ containerId, onLose }) {
|
|
const container = document.getElementById(containerId);
|
|
const width = container.clientWidth;
|
|
const row = 14;
|
|
const column = 18;
|
|
const height = (width / column) * row;
|
|
const bg = document.createElement("div");
|
|
bg.className = "snake";
|
|
bg.style.paddingTop = `${(240 / 2160) * width}px`;
|
|
|
|
const buttons = document.createElement("div");
|
|
buttons.className = "buttons";
|
|
bg.appendChild(buttons);
|
|
|
|
container.appendChild(bg);
|
|
super(new SnakeModel(), new SnakeView(bg, width, height));
|
|
|
|
Object.assign(this, {
|
|
showModal: true,
|
|
container: bg,
|
|
buttons,
|
|
containerWidth: width,
|
|
});
|
|
|
|
const modal = document.createElement("div");
|
|
modal.className = "modal show";
|
|
modal.addEventListener("click", (e) => {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
if (this.showModal) {
|
|
this.showModal = false;
|
|
modal.className = "modal";
|
|
this.resume();
|
|
}
|
|
});
|
|
bg.appendChild(modal);
|
|
|
|
this.init({
|
|
time: 3000000, // 总时间
|
|
width,
|
|
height,
|
|
row,
|
|
column,
|
|
// 显示屏的边框
|
|
border: 0x414042,
|
|
color: 0x414042, // 蛇的节点颜色
|
|
food: 0x990000, // 食物的颜色
|
|
min: 2, // 初始长度
|
|
speed: 0.5, // 速度标量
|
|
});
|
|
this.event.on("gameover", (res) => {
|
|
onLose(res);
|
|
});
|
|
this.event.on("restart", () => {
|
|
this.showModal = true;
|
|
modal.className = "modal show";
|
|
});
|
|
// snakeGame.event.on("eat", (food) => {
|
|
// console.log("吃到食物,当前长度: " + snakeGame.length);
|
|
// });
|
|
this.start();
|
|
this.addControl();
|
|
}
|
|
dispose() {}
|
|
addControl() {
|
|
let controller = this.buttons;
|
|
let curDirection;
|
|
const { containerWidth } = this;
|
|
let { top, left, width, height } = controller.getBoundingClientRect(),
|
|
x = left + width / 2,
|
|
y = top + height / 2,
|
|
deg45 = Math.PI / 4,
|
|
deg90 = Math.PI / 2,
|
|
deg135 = Math.PI / 2 + deg45,
|
|
deg180 = Math.PI,
|
|
deg225 = Math.PI + deg45,
|
|
deg270 = Math.PI + deg90,
|
|
deg315 = Math.PI * 2 - deg45;
|
|
|
|
controller.addEventListener(
|
|
"touchstart",
|
|
({ targetTouches: [{ clientX, clientY }] }) => {
|
|
checkDirection(clientX - x, clientY - y);
|
|
}
|
|
);
|
|
|
|
controller.addEventListener(
|
|
"touchmove",
|
|
({ targetTouches: [{ clientX, clientY }] }) => {
|
|
checkDirection(clientX - x, clientY - y);
|
|
}
|
|
);
|
|
|
|
controller.addEventListener("touchend", () => {
|
|
curDirection = undefined;
|
|
controller.className = "buttons snake-direction";
|
|
});
|
|
|
|
let checkDirection = (x, y) => {
|
|
let radian = Math.asin(y / Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
|
// 1~2象限
|
|
if ((x > 0 && y < 0) || (x > 0 && y > 0)) {
|
|
radian += deg90;
|
|
}
|
|
// 3~4象限
|
|
else if ((x < 0 && y > 0) || (x < 0 && y < 0)) {
|
|
radian = deg270 - radian;
|
|
}
|
|
|
|
let direction = "up";
|
|
if (radian > deg45 && radian < deg135) {
|
|
direction = "right";
|
|
} else if (radian > deg135 && radian < deg225) {
|
|
direction = "down";
|
|
} else if (radian > deg225 && radian < deg315) {
|
|
direction = "left";
|
|
}
|
|
direction === curDirection ||
|
|
this.turn(
|
|
(curDirection = direction),
|
|
(controller.className = "buttons snake-direction " + direction)
|
|
);
|
|
};
|
|
}
|
|
}
|
|
|