赞
踩
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>贪吃蛇</title> <link rel="stylesheet" href="css/index.css"> </head> <body> <div id="main"> <!-- 游戏的主要界面 --> <div id="stage"> <!-- 设置蛇 --> <div id="snake"> <!-- 表示蛇的各部分 --> <div></div> </div> <!--设置食物,4个div表示四个角--> <div id="food"> <div></div> <div></div> <div></div> <div></div> </div> </div> <!-- 设置游戏的积分牌 --> <div id="score-panel"> <!-- 积分 --> <div>SCORE:<span id="score">0</span></div> <!-- 等级,默认10, 等级高速度快 --> <div>LEVEL:<span id="level">1</span></div> </div> </div> <script src="TS/index.js"></script> </body> </html>
* { margin: 0; padding: 0; box-sizing: border-box; } /* 清楚默认样式 */ body { font: bold 20px "Courier" } #main { width: 360px; height: 420px; background-color: #b7d4a8; margin: 100px auto; border: 10px solid black; border-radius: 40px; 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 #b7d4a8; position: absolute; } #food { width: 10px; height: 10px; position: absolute; left: 40px; top: 100px; display: flex; flex-flow: row wrap; /* 设置主轴为横轴 超出部分换行 */ /* 设置主轴和侧轴的空白分配到元素之间 */ justify-content: space-between; align-items: center; } #food > div { width: 4px; height: 4px; background-color: black; transform: rotate(45deg); } #score-panel { width: 300px; display: flex; justify-content: space-between; }
tsc -t ES6 -w index.ts
表示使用ES6进行编译,并且对文件进行监控class Food { element : HTMLElement width: number size: number constructor (id:string, width = 29, size = 10 ) { this.element=document.getElementById(id) this.width = width this.size = size } get X(){ return this.element.offsetLeft } get Y() { return this.element.offsetTop } change() { // 生成随机的位置 范围在[0,width*10] 但要求为整数 且是10的倍数 this.element.style.left = Math.round(Math.random()*this.width)*this.size + 'px' this.element.style.top = Math.round(Math.random()*this.width)*this.size + 'px' } // 修改食物的位置 } class ScorePanel { score = 0 level = 1 scoreEle : HTMLElement levelEle : HTMLElement static maxLevel = 10 static upScore = 1 // 设置升1级所需要的分数 constructor (scoreId:string, levelId:string) { this.scoreEle = document.getElementById(scoreId) this.levelEle = document.getElementById(levelId) this.scoreEle.innerText = this.score + '' this.levelEle.innerText = this.level + '' } addScore (d = 1) { this.score += 1 this.scoreEle.innerText = this.score + '' if (this.score % ScorePanel.upScore === 0) this.addLevel() } addLevel () { if (this.level < ScorePanel.maxLevel) { this.levelEle.innerText = ++this.level + '' } } } class Snake { head: HTMLElement // 表示蛇头的元素 bodies: HTMLCollection // 蛇的身体包含蛇头 element: HTMLElement // 获取蛇的容器 range: number // 蛇头所能在的范围 constructor(id, range = 290) { this.element = document.getElementById(id) this.element.innerHTML = '<div></div>' // 初始化 this.bodies = this.element.getElementsByTagName('div') this.head = this.bodies[0] as HTMLElement this.range = range } get X() { return this.head.offsetLeft } // 获取蛇头x坐标 get Y() { return this.head.offsetTop } // 获取蛇头y坐标 set X(value:number) { if (this.X === value) return this.judge(value) this.move() this.head.style.left = value + 'px' } set Y(value:number) { if (this.Y === value) return this.judge(value) this.move() this.head.style.top = value + 'px' } addBody () { this.element.insertAdjacentHTML("beforeend","<div></div>") } move() { for(let i= this.bodies.length-1;i>0;--i){ let x = (this.bodies[i-1] as HTMLElement).offsetLeft let y = (this.bodies[i-1] as HTMLElement).offsetTop; (this.bodies[i] as HTMLElement).style.left = x + 'px'; (this.bodies[i] as HTMLElement).style.top = y + 'px' } } judge(value:number) { if ( value < 0 || value > this.range) { throw new Error('蛇撞墙了') } for(let i= this.bodies.length-1;i>0;--i) { let x = (this.bodies[i] as HTMLElement).offsetLeft let y = (this.bodies[i] as HTMLElement).offsetTop; if (x===this.X && y === this.Y) throw new Error('不能吃自己') } } } class GameControl { snake:Snake scorePanel: ScorePanel food: Food direction:string // 蛇头移动方向 isLive = true // 标记当前蛇仍然存在= static directionKey = new Set(['w','a','s','d',' ']) // 蛇头移动方向可能取值 static speed = 200 // 设置初始速度 constructor() { this.scorePanel = new ScorePanel('score','level') this.food = new Food("food") this.snake = new Snake("snake", this.food.size * this.food.width) this.direction = ' ' this.init() } init() { this.food.change() console.log(this.food.X,this.food.Y) document.addEventListener('keydown',this.keydownHandler.bind(this)) this.run() }// 游戏初始化 keydownHandler(event:KeyboardEvent) { let key = event.key if (GameControl.directionKey.has(key)){ // 不能向反方向移动 if (this.direction === 'w' && key === 's') return if (this.direction === 'a' && key === 'd') return if (this.direction === 's' && key === 'w') return if (this.direction === 'd' && key === 'a') return this.direction = event.key } }//创建一个键盘按下的响应的函数 run(){ let x = this.snake.X, y = this.snake.Y switch(this.direction) { case 'w': y -= 10 break // 向上移动 case 'a': x -= 10 break // 向左移动 case 's': y += 10 break // 向下移动 case 'd': x += 10 break // 向右移动 case ' ': break // 空格表示暂停或者继续 } try { this.checkEat(x, y) this.snake.X = x this.snake.Y = y }catch (err){ this.isLive = false if (window.confirm(err.message + ' 是否继续游戏')) { game = new GameControl() } return } this.isLive && setTimeout(this.run.bind(this),GameControl.speed / this.scorePanel.level) // 开启定时调用 }// 蛇移动的方法 checkEat (x:number, y:number) { if (x === this.food.X && y === this.food.Y) { this.food.change() this.scorePanel.addScore() this.snake.addBody() } } // 检查蛇是否迟到食物 } // 游戏控制器 let game: GameControl = new GameControl()
const path = require('path') const HTMLWebpackPlugin = require('html-webpack-plugin') const {CleanWebpackPlugin} = require('clean-webpack-plugin') module.exports = { context: path.resolve(__dirname, ''), // 基础目录,绝对路径,用于从配置中解析入口起点 (entry point) 和加载器 (loader)。 entry: "./src/index.ts", // 指定入口文件 output: { path: path.resolve(__dirname,'dist') , // 拼接目录 filename: "bundle.js" ,// 打包后文件名 environment: { arrowFunction: false } // 输出文件的语法环境 }, // 指定打包文件所在目录 module: { rules:[ { test: /\.tsx?$/, // 指定规则生效的文件 use: [ { loader: "babel-loader", options: { persets: [ "@babel/preset-env", // 指定环境的插件 { targets: { "chrome": "88", "ie": "10" }, // 要兼容的浏览器 "corejs": "3", "useBuiltIns" : "usage", // 表示按需加载所需要的资源 } ] // 设置预定义的环境 } // 对应加载器的配置项,每个加载器都有自己的配置项 }, "ts-loader" ] ,// 数组的方式使用多个加载器 exclude: "/node-modules/" // 要排除的文件夹 } ] // 指定要加载的规则 }, // 指定webpack打包时要使用的模块 resolve: { extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"], alias: { '@': resolve('src') }, // 配置别名把原来导入路径映射成一个新的导入路径 }, // 配置 webpack 如何寻找模块对应的文件 plugins: [ new CleanWebpackPlugin(), new HTMLWebpackPlugin({ title : 'ts项目构建', // index.html 标题 template: "", // 定义模板位置 }) ], devServer: { } // 提供虚拟服务器,让我们进行开发和调试。需要安装对应插件 webpack-dev-server }
{ "script":{ "build": "webpack", "start": "webpack serve --open chrome.exe" }, "devDependencies": { "clean-webpack-plugin" : "", // webpack中的清除插件,每次构建都会先清除目录 "html-webpack-plugin":"", // webpack中html插件,用来自动创建html文件 "ts-loader":"", // ts加载器,用于在webpack中编译ts文件 "typescript":"", // ts编译器 "webpack": "", // 构建工具webpack "webpack-cli": "", // webpack的命令行工具 "webpack-dev-server": "", "@babel/core": "", "@babel/preset-enb": "", "babel-loader":"", "core-js": "" } }
webpack-dev-server
: 拥有实时重载能力的静态资源服务器Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。