基于ts的贪吃蛇小游戏

贪吃蛇小游戏,基于Ts开发的,做着玩。

实物类

class Food{
  element: HTMLElement

  constructor() {
    this.element = document.querySelector('#food')!;

  }
  get X() {
    return this.element.offsetLeft
  }
  get Y() {
    return this.element.offsetTop
  }
  change() {
    let top = Math.round(Math.random() * 29) * 10;
    let left = Math.round(Math.random() * 29) * 10;
    this.element.style.top=top + 'px'
    this.element.style.left=left + 'px'
  }
  
  
}
export default Food;

游戏控制类

import Food from "./Food";
import ScorePanel from "./ScorePanel";
import Snake from "./Snake";
class GameControls{
  snake: Snake
  food: Food
  scorePanel: ScorePanel
  direction=''
  isLive = true
  constructor() {
    this.snake = new Snake()
    this.food = new Food()
    this.scorePanel = new ScorePanel(10,2)
    this.init()
  }
  init() {
    document.addEventListener('keydown',this.keydownHandler.bind(this))
    this.run()
  }
  keydownHandler(event: KeyboardEvent) {
    this.direction = event.key;
  }
  run() {
    let X = this.snake.X;
    let Y = this.snake.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.checkEat(X, Y);
    try{
      this.snake.X = X;
    this.snake.Y = Y;
    }catch (e) {
      alert('Your snake is died!')
      this.isLive = false
    }
    this.isLive && setTimeout(this.run.bind(this),300-(this.scorePanel.level-1)*30)

  }
  checkEat(X: number, Y:number) {
    if (X === this.food.X && Y === this.food.Y) {
      this.food.change()
      this.scorePanel.addScore()
      this.snake.addBody()
    }
  }
}
export default GameControls

计分类


class ScorePanel{
  score = 0;
  level = 1;
  scoreEle: HTMLElement
  levelEle: HTMLElement
  maxLevel: number
  upScore:number
  constructor(maxLevel:number=10,upScore:number=10) {
    this.scoreEle = document.querySelector('#score')!;
    this.levelEle = document.querySelector('#level')!;
    this.maxLevel = maxLevel
    this.upScore = upScore
  }
  addScore() {
    this.scoreEle.innerHTML = ++this.score + '';
    if (this.score % this.upScore === 0)
    {
      this.levelUp()
      }
  }
  levelUp() {
    if (this.level < this.maxLevel) {
      this.levelEle.innerHTML = ++this.level + '';
    }
  } 

}
export default ScorePanel;

class Snake{
  element: HTMLElement
  head: HTMLElement;

    // 蛇的身体(包括蛇头)
    bodies: HTMLCollection;
  constructor() {
    this.element = document.getElementById('snake')!
    this.head = document.querySelector('#snake>div') as HTMLElement;
    this.bodies = this.element.getElementsByTagName('div')
  }
  get X() {
    return this.head.offsetLeft
  }
  get Y() {
    return this.head.offsetTop
  }
  set X(value) {
    if (value === this.X) {
      return;
    }
    if (value < 0 || value > 290) {
      throw new Error
    }
    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
      if (value > this.X) {
        value = this.X - 10;
      }
      else {
        value = this.X + 10;
      }
    }

    this.moveBody()
    this.head.style.left = value + 'px';
    this.checkHeadBody()
  }
  set Y(value) {
    if (value === this.Y) {
      return;
    }
    if (value < 0 || value > 290) {
      throw new Error
    }
      if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
      if (value > this.Y) {
        value = this.Y - 10;
      }
      else {
        value = this.Y + 10;
      }
    }

    this.moveBody()
    this.head.style.top = value + 'px'
    this.checkHeadBody()

  }
  addBody() {
    this.element.insertAdjacentHTML("beforeend","<div></div>")
  }
  moveBody() {
    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';
    }
  }
  checkHeadBody() {
    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 new Error
      }
    }
  }
}
export default Snake;

相关的包依赖

 "@babel/core": "^7.13.15",
        "@babel/preset-env": "^7.13.15",
        "babel-loader": "^8.2.2",
        "clean-webpack-plugin": "^4.0.0-alpha.0",
        "core-js": "^3.10.1",
        "css-loader": "^5.2.1",
        "html-webpack-plugin": "^5.3.1",
        "less": "^4.1.1",
        "less-loader": "^8.1.0",
        "postcss": "^8.2.10",
        "postcss-loader": "^5.2.0",
        "postcss-preset-env": "^6.7.0",
        "style-loader": "^2.0.0",
        "ts-loader": "^8.1.0",
        "typescript": "^4.2.4",
        "webpack": "^5.32.0",
        "webpack-cli": "^4.6.0",
        "webpack-dev-server": "^3.11.2"

webback-config.js的配置

// 引入一个包
const path = require('path');
// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin');
//引入clean插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

// npm init -y 初始化 创建package.json文件
// npm i -D webpack webpack-cli typescript ts-loader  安装四个依赖
// 编写webpack配置文件
// 编写tsconfig.json文件
// 修改package.json中加上build命令
// npm i -D html-webpack-plugin //自动生成html
// npm i -D webpack-dev-server //自动响应浏览器更新
// npm i -D clean-webpack-plugin //清楚dist目录旧文件

//webpack 中所有的配置信息都应该写在module.exports中
module.exports = {
  // 指定入口文件
  entry: './src/index.ts',

  // 指定打包文件所在目录
  output: {
    //指定打包文件的目录
    path: path.resolve(__dirname, 'dist'),
    //打包后文件的名字
    filename: 'bundle.js',
    //告诉webpack不使用箭头函数
    environment: {
      arrowFunction: false,
      const: false, //兼容ie10
    },
  },
  //指定webpack打包时要使用的模块
  module: {
    // 指定要loader加载的规则
    rules: [
      // 设置ts文件的处理
      {
        // test指定的时规则生效的文件
        test: /\.ts$/, //以ts结尾的文件
        // 要使用的loader
        use: [
          // 配置babel
          {
            //指定加载器
            loader: 'babel-loader',
            // 设置babel
            options: {
              //设置预定义的环境
              presets: [
                [
                  //指定环境的插件
                  '@babel/preset-env',
                  // 配置信息
                  {
                    // 要兼容的目标浏览器及版本
                    targets: {
                      chrome: '58',
                      ie: '11',
                    },
                    //指定corejs的版本
                    corejs: '3',
                    //使用corejs的方式 "usage"  表示按需加载
                    useBuiltIns: 'usage',
                  },
                ],
              ],
            },
          },
          // 'babel-loader',
          'ts-loader',
        ],
        // 要排除的文件
        exclude: /node-modules/,
      },
      // 设置less文件的处理
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          //  引入postcss
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      browsers: 'last 2 versions', //兼容每个浏览器最新的两个版本
                    },
                  ],
                ],
              },
            },
          },
          'less-loader',
        ],
      },
    ],
  },
  // mode: "development", //设置mode
  //配置Webpack 插件
  plugins: [
    new CleanWebpackPlugin(),
    new HTMLWebpackPlugin({
      // title: "这是一个自定义的title"、
      template: './src/index.html',
    }),
  ],

  // 用来设置引用模块,可以将这些文件识别为模块
  resolve: {
    extensions: ['.ts', '.js'],
  },
};

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值