用 typescript 做一个贪吃蛇小游戏

Posted 新时代农民工Top

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 typescript 做一个贪吃蛇小游戏相关的知识,希望对你有一定的参考价值。

typescript 做一个贪吃蛇小游戏

搭建环境

创建 tscofig.json 文件

配置如下


  "compilerOptions": 
    "target": "es2015",
    "module": "es2015",
    "strict": true,
    "outDir": "./dist",
    "noEmitOnError": true
  

创建 webpack.config.js 文件

  1. 安装 webpack

    npm i webpack webpack-cli -D
    
  2. 配置
    配置 webpack 项目工程化,配置项目运行打包,兼容,处理 .ts .css .less html 文件

  3. 安装插件

    npm i html-webpack-plugin webpack-dev-server -D
    
    webpack-dev-server 作用

    webpack 内部服务器,可以在开发阶段项目自动运行,比如修改了代码,会检测到改动并且自动运行,不需要每次都手动运行查看,利于开发效率

    html-webpack-plugin

    html 插件,可用来提供 html 模板,打包后的 dist 文件中的 html 会根据这个模板生成

配置如下

const path = require('path')
// html 插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin(
    template: './src/index.html',
    filename: './index.html'
)

module.exports = 
    mode: 'development',
    entry: './src/index.ts',
    output: 
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        environment: 
            // 兼容 IE ,禁止使用箭头函数
            arrowFunction: false,
            // 兼容 IE ,禁止使用es6语法
            const: false
        
    ,
    module: 
        rules: [
                test: /\\.ts$/,
                use: [
                    // 配置babel
                    
                        // 指定加载器
                        loader: 'babel-loader',
                        // 设置 babel
                        options: 
                            // 设置预定义环境
                            presets: [
                                [
                                    // 指定环境插件
                                    "@babel/preset-env",
                                    // 配置信息
                                    
                                        // 要兼容的目标浏览器
                                        targets: 
                                            "chrome": "58"
                                        ,
                                        // 指定 corejs 版本
                                        "corejs": "3",
                                        // 使用 corejs 的方式"usage"表示按需加载
                                        "useBuiltIns": "usage"
                                    
                                ]
                            ]
                        
                    , 'ts-loader'
                ],
                exclude: /node_modules/
            ,
            
                test: /\\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    // 引入 postcss 
                    
                        loader: "postcss-loader",
                        options: 
                            postcssOptions: 
                                plugins: [
                                    [
                                        "postcss-preset-env",
                                        
                                            browsers: 'last 2 versions'
                                        
                                    ]
                                ]
                            
                        
                    ,
                    "less-loader"
                ]
            
        ]
    ,
    plugins: [htmlPlugin],
    resolve: 
        extensions: ['.ts', '.js']
    

创建 package.json 文件

在项目名称是英文的情况下使用

npm init -y

如果项目名称不是英文,使用如下命令,给它设置一个英文名称

npm init

安装项目所需的全部开发依赖,如下

配置就说这么多,下面开始项目代码

采用的是结构与数据分离

先布局基本样式
在项目根目录下创建 src 文件夹,在src 文件夹下创建 index.html 和 index.ts 文件

./src/index.html

<!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 class="box">
        <div class="top">
            // 蛇
            <div id="snake">
                // 蛇的每一节
                <div></div>
            </div>
            // 食物
            <div id="food"></div>
        </div>
        // 记分牌
        <div class="bottom">
            <div>SCORE:<span id="score">3</span></div>
            <div>LEVEL:<span id="level">1</span></div>
        </div>
    </div>
</body>

</html>

在 src 目录下创建 style 文件夹存放样式文件 index.less

* 
  margin: 0;
  padding: 0;
  box-sizing: border-box;

body 
  font: bold 20px "Courier";


.box 
  width: 360px;
  height: 420px;
  background-color: #b7d4a8;
  border: 10px solid #000;
  margin: 100px auto;
  border-radius: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;


.top 
  width: 304px;
  height: 304px;
  border: 2px solid #000;
  position: relative;


.bottom 
  width: 304px;
  display: flex;
  justify-content: space-between;


#snake 
  position: relative;


#snake div 
  width: 10px;
  height: 10px;
  background-color: black;
  border: 1px solid #b7d4a8;
  position: absolute;
  top: 0;
  left: 0;


#food 
  width: 10px;
  height: 10px;
  background-color: black;
  position: absolute;
  border: 1px solid #b7d4a8;

在 index.ts 文件中引入样式

import './style/index.less'
  • 不要忘记安装 less


开始业务逻辑代码

在 src 文件下创建 modules 文件夹,存放每个类

Food.ts , 控制食物随机出现的位置

class Food 
  // 定义一个属性表示事物所对应的元素
  element: HTMLElement

  constructor() 
    // !感叹号的意思是不用管
    this.element = document.getElementById('food')!
  

  // 定义一个获取食物X轴坐标的方法
  get X() 
    return this.element.offsetLeft
  

  // 定义一个获取食物Y轴坐标的方法
  get Y() 
    return this.element.offsetTop
  

  // 修改十五位置的方法
  change() 
    // 生成一个随机数
    // 食物的位置最小时0,最大是290
    // Math.round(Math.random() * 29) * 10
    this.element.style.top = Math.round(Math.random() * 29) * 10 + 'px'
    this.element.style.left = Math.round(Math.random() * 29) * 10 + 'px'
  


// let food = new Food()
// food.change()
// console.log(food.X, food.Y)

export default Food

创建 ScorePanel.ts,控制记分牌的变化

// 定义记分牌
class ScorePanel 
  // score, level 记录分数和等级
  score = 0
  level = 1

  // 分数和等级初始化
  scoreEle: HTMLElement
  levelEle: HTMLElement

  // shezhibianliang
  maxLevel: number
  maxScore: number

  constructor(maxLevel: number = 10, maxScore: number = 10) 
    this.scoreEle = document.getElementById('score')!
    this.levelEle = document.getElementById('level')!
    this.maxLevel = maxLevel
    this.maxScore = maxScore
  

  // 设置加分的方法
  addScore() 
    this.score++
    this.scoreEle.innerHTML = this.score + ''
    if (this.score % this.maxScore === 0) 
      this.levelUp()
    
  

  // 提升等级的方法
  levelUp() 
    if (this.level < this.maxLevel) 
      this.level++
      this.levelEle.innerHTML = this.level + ''
    
  


export default ScorePanel

创建 Snake.ts,控制蛇的长度/位置/是否撞墙或者撞到自己

class Snake 
  // 表示蛇头的元素
  head: HTMLElement
  // 蛇的身体
  bodies: HTMLCollection
  element: HTMLElement

  constructor() 
    this.element = document.getElementById('snake')!
    this.head = document.querySelector('#snake > div')!
    this.bodies = this.element.getElementsByTagName('div')
  

  // 获取蛇的坐标
  get X() 
    return this.head.offsetLeft
  

  get Y() 
    return this.head.offsetTop
  

  // 设置蛇头的坐标
  set X(value: number) 
    if (this.X === value) return
    // 判断是否撞墙 X值的合法范围
    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: number) 
    if (this.Y === value) 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

创建 GameControl.ts,控制蛇的移动,把蛇、食物、记分牌联系到一块

import Snake from "./snake";
import Food from "./food";
import ScorePanel from "./ScorePanel";

class GameControl 
  // 定义三个属性
  // 蛇
  snake: Snake
  food: Food
  scorePanel: ScorePanel

  // c创建一个属性来存储蛇的移动方向
  direction: string = 'Right'

  // 创建一个属性用来记录游戏是否结束
  isLive: boolean = true

  constructor() 
    this.snake = new Snake()
    this.food = new Food()
    this.scorePanel = new ScorePanel()

    this.init()
  

  // 游戏初始化方法
  init() 
    // 绑定键盘事件
    // 修改this指向
    document.addEventListener('keydown', this.keydownHandler.bind(this))
    // 调用 run 方法
    this.run()
  

  // 创建键盘按下的函数
  keydownHandler(e: KeyboardEvent) 
    // 修改 dirention 的值
    this.direction = e.key
  

  // 创建控制蛇移动的方法
  run() 
    // 根据方向来改变蛇的位置
    // 获取蛇现在的坐标
    let X = this.snake.X
    let Y = this.snake.Y

    switch (this.direction) 
      case "ArrowUp":
      case "Up":
        Y -= 10
        break;
      case "ArrowDown":
      case "Down":
        Y += 10
        break;
      case "ArrowRight":
      case "Right":
        X += 10
        break;
      case "ArrowLeft":
      case "Left":
        X -= 10
        break;
    
      default:
        break;
    

    this.checkEat(X, Y)

    try 以上是关于用 typescript 做一个贪吃蛇小游戏的主要内容,如果未能解决你的问题,请参考以下文章

刚学会 TypeScript, 顺手做个贪吃蛇小游戏

刚学会 TypeScript, 顺手做个贪吃蛇小游戏

用HTML做一个贪吃蛇?

用 Python Turtle 模块做小游戏 - 贪吃蛇

TypeScript教程# 16:ts + webpack + less实现贪吃蛇小游戏

用C语言编写 贪吃蛇的思路啥怎么样的