master
commit
e1dc2551e2
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "snake",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "webpack --mode development --config webpack.config.js",
|
||||||
|
"start": "webpack serve --open chrome.exe"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.18.2",
|
||||||
|
"@babel/preset-env": "^7.18.2",
|
||||||
|
"babel-loader": "^8.2.5",
|
||||||
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
|
"core-js": "^3.22.8",
|
||||||
|
"css-loader": "^6.7.1",
|
||||||
|
"html-webpack-plugin": "^5.5.0",
|
||||||
|
"less": "^4.1.2",
|
||||||
|
"less-loader": "^11.0.0",
|
||||||
|
"postcss": "^8.4.14",
|
||||||
|
"postcss-loader": "^7.0.0",
|
||||||
|
"postcss-preset-env": "^7.7.1",
|
||||||
|
"style-loader": "^3.3.1",
|
||||||
|
"ts-loader": "^9.3.0",
|
||||||
|
"typescript": "^4.7.3",
|
||||||
|
"webpack": "^5.73.0",
|
||||||
|
"webpack-cli": "^4.9.2",
|
||||||
|
"webpack-dev-server": "^4.9.1"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>贪食蛇</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- 游戏的主容器 -->
|
||||||
|
<div id="main">
|
||||||
|
<!-- 游戏的舞台 -->
|
||||||
|
<div id="stage">
|
||||||
|
<!-- 蛇 -->
|
||||||
|
<div id="snake">
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 食物 -->
|
||||||
|
<div id="food"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 游戏的积分牌 -->
|
||||||
|
<div id="score-panel">
|
||||||
|
<div>
|
||||||
|
SCORE:<span id="score">0</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
LEVEL:<span id="level">1</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,6 @@
|
|||||||
|
// 引入样式
|
||||||
|
import "./style/index.less";
|
||||||
|
import GameController from "./modules/GameController";
|
||||||
|
|
||||||
|
const game = new GameController();
|
||||||
|
game.init();
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* 记分牌
|
||||||
|
*/
|
||||||
|
class ScorePanel
|
||||||
|
{
|
||||||
|
protected score = 0;
|
||||||
|
protected level = 1;
|
||||||
|
protected scoreElement: HTMLElement;
|
||||||
|
protected levelElement: HTMLElement;
|
||||||
|
|
||||||
|
constructor(protected maxLavel: number = 10, protected upScore: number = 10)
|
||||||
|
{
|
||||||
|
this.scoreElement = document.getElementById("score")!;
|
||||||
|
this.levelElement = document.getElementById("level")!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加分
|
||||||
|
*/
|
||||||
|
public addScore(): void
|
||||||
|
{
|
||||||
|
this.scoreElement.innerText = (++this.score).toString();
|
||||||
|
|
||||||
|
// 分数达到设置的数则升级
|
||||||
|
if (this.score % this.upScore === 0) {
|
||||||
|
this.levelUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 升级
|
||||||
|
*/
|
||||||
|
protected levelUp(): void
|
||||||
|
{
|
||||||
|
if (this.level <= this.maxLavel) {
|
||||||
|
this.levelElement.innerText = (++this.level).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前等级
|
||||||
|
*/
|
||||||
|
get nowLevel(): number
|
||||||
|
{
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ScorePanel;
|
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* 蛇
|
||||||
|
*/
|
||||||
|
class Snake
|
||||||
|
{
|
||||||
|
protected element: HTMLElement;
|
||||||
|
// 蛇头元素
|
||||||
|
protected head: HTMLElement;
|
||||||
|
// 蛇的身体(包括蛇头)
|
||||||
|
protected bodies: HTMLCollectionOf<HTMLElement>;
|
||||||
|
// 蛇当前的行走方向
|
||||||
|
protected direction = "";
|
||||||
|
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
this.element = document.getElementById("snake")!;
|
||||||
|
this.head = document.querySelector("#snake > div")!;
|
||||||
|
this.bodies = this.element.getElementsByTagName("div");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置蛇头的X坐标值
|
||||||
|
*/
|
||||||
|
set X(value: number)
|
||||||
|
{
|
||||||
|
if (this.X === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > 290) {
|
||||||
|
throw new Error("蛇撞墙了!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moveBody();
|
||||||
|
|
||||||
|
this.head.style.left = value + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回蛇头的X坐标值
|
||||||
|
*/
|
||||||
|
get X(): number
|
||||||
|
{
|
||||||
|
return this.head.offsetLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置蛇头的Y坐标值
|
||||||
|
*/
|
||||||
|
set Y(value: number)
|
||||||
|
{
|
||||||
|
if (this.Y === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > 290) {
|
||||||
|
throw new Error("蛇撞墙了!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moveBody();
|
||||||
|
|
||||||
|
this.head.style.top = value + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回蛇头的Y坐标值
|
||||||
|
*/
|
||||||
|
get Y(): number
|
||||||
|
{
|
||||||
|
return this.head.offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置蛇的行走方向
|
||||||
|
*/
|
||||||
|
set nowDirection(value: string)
|
||||||
|
{
|
||||||
|
this.direction = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取蛇的身体
|
||||||
|
*/
|
||||||
|
get nowBodies(): HTMLCollectionOf<HTMLElement>
|
||||||
|
{
|
||||||
|
return this.bodies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 吃完食物增加身体
|
||||||
|
*/
|
||||||
|
public addBody(): void
|
||||||
|
{
|
||||||
|
const div = document.createElement("div");
|
||||||
|
this.element.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多节蛇的移动
|
||||||
|
*/
|
||||||
|
public moveBody(): void
|
||||||
|
{
|
||||||
|
for (let i = this.bodies.length - 1; i > 0; i--) {
|
||||||
|
let x = this.bodies[i - 1].offsetLeft;
|
||||||
|
let y = this.bodies[i - 1].offsetTop;
|
||||||
|
|
||||||
|
this.bodies[i].style.left = x + "px";
|
||||||
|
this.bodies[i].style.top = y + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追尾检查
|
||||||
|
*/
|
||||||
|
public checkRearEnd(): void | never
|
||||||
|
{
|
||||||
|
// 只要蛇头与其他任何蛇身重叠则为追尾
|
||||||
|
for (let i = 1; i < this.bodies.length; i++) {
|
||||||
|
if (this.X === this.bodies[i].offsetLeft && this.Y === this.bodies[i].offsetTop) {
|
||||||
|
throw new Error("蛇追尾了!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 蛇头走
|
||||||
|
*/
|
||||||
|
public run(): void
|
||||||
|
{
|
||||||
|
let x = this.X;
|
||||||
|
let y = this.Y;
|
||||||
|
|
||||||
|
switch(this.direction) {
|
||||||
|
case "ArrowUp" :
|
||||||
|
case "Up" :
|
||||||
|
y -= 10;
|
||||||
|
break;
|
||||||
|
case "ArrowDown" :
|
||||||
|
case "Down" :
|
||||||
|
y += 10;
|
||||||
|
break;
|
||||||
|
case "ArrowLeft" :
|
||||||
|
case "Left" :
|
||||||
|
x -= 10;
|
||||||
|
break;
|
||||||
|
case "ArrowRight" :
|
||||||
|
case "Right" :
|
||||||
|
x += 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.X = x;
|
||||||
|
this.Y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Snake;
|
@ -0,0 +1,74 @@
|
|||||||
|
// 颜色变量
|
||||||
|
@bg-color: #b7d4a8;
|
||||||
|
|
||||||
|
// 清除默认样式
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
// 改变盒子模型的计算方式
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面公共样式
|
||||||
|
body {
|
||||||
|
font: bold 20px "Courier";
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主窗口的样式
|
||||||
|
#main {
|
||||||
|
width: 360px;
|
||||||
|
height: 420px;
|
||||||
|
background-color: @bg-color;
|
||||||
|
margin: 100px auto;
|
||||||
|
border: 10px solid black;
|
||||||
|
border-radius: 20px;
|
||||||
|
|
||||||
|
// 开启弹性盒模型
|
||||||
|
display: flex;
|
||||||
|
// 设置主轴的方向
|
||||||
|
flex-flow: column;
|
||||||
|
// 设置侧轴的对齐方式
|
||||||
|
align-items: center;
|
||||||
|
// 设置主轴的对齐方式
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 游戏舞台
|
||||||
|
#stage {
|
||||||
|
width: 304px;
|
||||||
|
height: 304px;
|
||||||
|
border: 2px solid black;
|
||||||
|
// 开启相对定位(因蛇元素和食物元素需要绝对定位,遵循子绝父相的定律)
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 蛇
|
||||||
|
#snake > div {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: black;
|
||||||
|
border: 1px solid @bg-color;
|
||||||
|
// 开启绝对定位
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 食物
|
||||||
|
#food {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: black;
|
||||||
|
border: 1px solid @bg-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
// 开启绝对定位
|
||||||
|
position: absolute;
|
||||||
|
left: 40px;
|
||||||
|
top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记分牌
|
||||||
|
#score-panel {
|
||||||
|
width: 300px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "ES2015",
|
||||||
|
"target": "ES2015",
|
||||||
|
"strict": true,
|
||||||
|
"noEmitOnError": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue