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