package.json
我把该文件放在下面,有需要的直接创建package.json将下面的代码复制进去,然后 npm i
下载相关的依赖
{
"name": "webpack-ts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.17.9",
"@babel/preset-env": "^7.16.11",
"babel-loader": "^8.2.4",
"clean-webpack-plugin": "^4.0.0",
"core-js": "^3.21.1",
"html-webpack-plugin": "^5.5.0",
"postcss": "^8.4.12",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.4.3",
"ts-loader": "^9.2.8",
"typescript": "^4.6.3",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.8.1"
},
"dependencies": {
"css-loader": "^6.7.1",
"less": "^4.1.2",
"less-loader": "^10.2.0",
"style-loader": "^3.3.1"
}
}
webpack.config.js
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
entry:'./src/index.ts',
output:{
filename:"js/index.js",
path:resolve(__dirname,'build')
},
module:{
rules:[
{ //处理ts
test:/\.ts$/,
use:[
//配置babel
{
//加载器
loader:'babel-loader',
options:{
//预设环境
presets:[
[
//指定预设环境
"@babel/preset-env",
{
//兼容目标浏览器
targets:{
"chrome":58,
"ie":11
},
//corejs的版本
"corejs":3,
//配置按需加载
"useBuiltIns":"usage"
}
]
]
}
},
//将ts转为js
{loader:'ts-loader'}
],
exclude:/node_modules/
},
{
//处理less
test:/\.less$/,
use:[
"style-loader",
"css-loader",
// 处理css的兼容性问题
{
// 加载器
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:[
[
'postcss-preset-env',
{
browsers:'last 2 versions'
}
]
]
}
}
},
// 将less转为css
"less-loader"
],
exclude:/node_modules/
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
new CleanWebpackPlugin()
],
//用来告诉webpack 哪些文件可以导入
resolve:{
extensions:['.ts','.css','.js']
},
mode:'development'
}
tsconfig.json
{
"compilerOptions":{
"strict": true,
"target": "es2015",
"module": "es2015",
"noEmitOnError": true
}
}
具体代码实现:
index.ts
import '../style/index.less'
import Control from "../modules/Control"
new Control()
Control.ts
import ScorePanel from "../modules/ScorePanel"
import Food from "../modules/Food"
import Snack from "../modules/Snack"
class Control{
food:Food
snack:Snack
scorepanel:ScorePanel
direction = ''
isLive = true
constructor(){
this.food = new Food()
this.snack = new Snack()
this.scorepanel = new ScorePanel()
//初始化游戏,调用则游戏开始
this.init()
}
//定义一个初始化函数
init(){
/*
在这里this会出现问题,因为在这里this是由document调用所以this指向document
解决办法:
- 可以使用箭头函数
- bind()
*/
// document.addEventListener('keydown',(event:KeyboardEvent)=>{
// this.SnackDirection(event)
// })
document.addEventListener('keydown',this.SnackDirection.bind(this))
this.run()
}
//键盘按下事件
SnackDirection(event:KeyboardEvent){
// 修改direction属性
this.direction = event.key
}
//让蛇跑起来
run(){
let x = this.snack.X
let y = this.snack.Y
//判断方向
switch(this.direction){
case "ArrowUp" : y -= 10; break;
case "ArrowDown" : y += 10; break;
case "ArrowLeft" : x -= 10; break;
case "ArrowRight": x += 10; break;
}
this.checkFood(x,y)
try {
// 修改蛇的位置
this.snack.X = x
this.snack.Y = y
} catch (error) {
alert(error)
this.isLive = false
}
this.isLive && setTimeout(()=>{
this.run()
}, 100-(this.scorepanel.num2 - 1)*10);
}
//检查是否吃到东西
checkFood(x:number,y:number){
if(this.food.X === x && this.food.Y === y)
{
//进入判断表示吃到了东西
this.food.foodRandom()
this.snack.addBody()
this.scorepanel.addScore
}
}
}
export default Control
Food.ts
class Food{
element:HTMLElement
constructor(){
this.element = document.querySelector('#food')!
}
// 获取食物当前的位置
get X (){
return this.element.offsetLeft
}
get Y (){
return this.element.offsetTop
}
//修改食物的位置
set X (value){
this.element.style.left = value +'px'
}
set Y(value){
this.element.style.top = value +'px'
}
/*
1.食物随机跳变
分析:
- 跳变的范围 0-290
- 并且你要满足是10的倍数,因为设定
都一步为10格,要不然一直吃不到
*/
foodRandom(){
//生成随机数
let left = Math.round(Math.random()*29)*10
let top = Math.round(Math.random()*29)*10
//设置food的位置
this.X = left
this.Y = top
}
}
export default Food
ScorePanel.ts
class ScorePanel{
score:HTMLElement
level:HTMLElement
num1 = 0 //分数初始值
num2 = 1 //等级初始值
maxLevel:number // 设置最大的等级
setScore:number //设置多少分升一级
constructor(setScore = 10,maxLevel = 10){
this.setScore = setScore
this.maxLevel = maxLevel
this.score = document.querySelectorAll('#score span')[0] as HTMLLinkElement
this.level = document.querySelectorAll('#score span')[1] as HTMLLinkElement
}
// 增加分数
addScore(){
this.score.innerText = ++this.num1 +''
if(this.num1 % this.setScore === 0)
{
this.addLevel()
}
}
// 升级
addLevel(){
if(this.num2 < this.maxLevel)
{
this.level.innerText = ++this.num2 +''
}
}
}
export default ScorePanel
Snack.ts
class Snack{
head:HTMLElement
bodies:HTMLCollection
element:HTMLElement
constructor(){
//获取头部
this.head = document.querySelector('.head')!
//获取身体
this.bodies = document.getElementById('snack')!.getElementsByTagName('div')
//获取snack容器
this.element = document.querySelector('#snack')!
}
//获取头部的位置
get X ()
{
return this.head.offsetLeft
}
get Y ()
{
return this.head.offsetTop
}
//设置头部的位置
set X(value){
//当位置未发生改变则不进行赋值
if(this.X === value)
{
return
}
//限制蛇移动的范围
if(value < 0 || value > 290)
{
throw 'GAME OVER ! 游戏结束!'
}
//解决蛇掉头问题
if(this.bodies[1] && value === (this.bodies[1] as HTMLElement).offsetLeft)
{
//进入判断就表示调头了
if(value > this.X)
{
value -= 20
}else
{
value += 20
}
}
this.moveBody()
this.head.style.left = value + 'px'
this.checkHead()
}
set Y(value){
//当位置未发生改变则不进行赋值
if(this.Y === value)
{
return
}
//限制蛇移动的范围
if(value < 0 || value > 290)
{
throw 'GAME OVER ! 游戏结束!'
}
//解决蛇掉头问题
if(this.bodies[1] && value === (this.bodies[1] as HTMLElement).offsetTop)
{
//进入判断就表示调头了
if(value > this.Y)
{
value -= 20
}else
{
value += 20
}
}
this.moveBody()
this.head.style.top = value + 'px'
this.checkHead()
}
addBody(){
this.element.insertAdjacentHTML('beforeend','')
}
//添加身体移动的方法
/*
实现的逻辑:
第四节的位置 --> 第三节的位置
第三节的位置 --> 第二节的位置
第二节的位置 --> 第一节的位置
*/
moveBody(){
for(let i = this.bodies.length-1; i>0; i--)
{
let left = (this.bodies[i-1] as HTMLElement).offsetLeft;
let top = (this.bodies[i-1] as HTMLElement).offsetTop;
(this.bodies[i] as HTMLElement).style.left = left + 'px';
(this.bodies[i] as HTMLElement).style.top = top + 'px';
}
}
//检查是否撞头
checkHead(){
for(let i = 1;i<this.bodies.length;i++)
{
if(this.X === (this.bodies[i] as HTMLElement).offsetLeft && this.Y === (this.bodies[i] as HTMLElement).offsetTop)
{
// 如果进入了判断就表示撞到自己了
throw '撞到自己了!!游戏结束!!'
}
}
}
}
export default Snack
以上就是今天要讲的内容,希望对大家有所帮助!!!