TypeScript 学习笔记 第三部分 贪吃蛇游戏

尚硅谷TypeScript教程(李立超老师TS新课)

1. 创建开发环境

  1. 创建工程,使用学习笔记的第二部分
  2. 安装css部分
npm i -D less less-loader css-loader style-loader
  1. 对css部分处理,能够运行在低版本浏览器
npm i -D postcss postcss-loader postcss-preset-env
  1. 修改webpack.config.json文件
    在这里插入图片描述
// 设置less文件的处理
            {
                test: /\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions:{
                                plugins: [
                                    [
                                        "postcss-preset-env",
                                        {
                                            browsers:"last 2 versions"
                                        }
                                    ]
                                ]
                            }
                        }
                    },
                    "less-loader"
                ]
            }

2. 工程目录结构

在这里插入图片描述

3. 代码部分

  • index.js
import './style/index.less'

import GameControl from "./modules/GameControl";

new GameControl()
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>贪吃蛇</title>
</head>
<body>
<div id="main" >

    <div id="stage">
        <div id="snake">
            <div></div>
        </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>
        <div>
            LEVEL: <span id="level">1</span>
        </div>
    </div>
</div>
</body>
</html>
  • /style/index.less
// 设置变量
@bg-color:#b7d4a8;

*{
  margin: 0;
  padding: 0;
  caret-color: transparent;
  // 改变盒子模型的计算方式
  box-sizing: border-box;
}
body{
  font: bold 20px "Courier";

}

#main{
  width: 360px;
  height: 420px;
  background-color: @bg-color;

  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: #000;
        border:1px solid @bg-color;
        // 开启绝对定位
        position: absolute;
      }
    }
    #food{
      width: 10px;
      height: 10px;
      border:1px solid @bg-color;
      // 开启绝对定位
      position: absolute;
      display: flex;
      flex-wrap: wrap;
      align-content: space-between;
      justify-content: space-between;
      &>div{
        width: 4px;
        height: 4px;
        background-color: black;
        transform: rotate(45deg);
      }
    }
  }
  #score-panel{
    width: 300px;
    display: flex;
    justify-content: space-between;
  }
}


  • /modules/snake.ts
export default class Snake{
    // 蛇头
    head:HTMLElement
    // 蛇身体,包括蛇头
    bodies:HTMLCollection
    // 蛇的父容器
    element:HTMLElement
    constructor() {
        this.element = document.getElementById("snake")!
        this.bodies = this.element.children
        this.head = this.element.firstElementChild as HTMLElement
    }
    // 蛇头的坐标
    get X(){
        return this.head.offsetLeft
    }
    get Y(){
        return this.head.offsetTop
    }

    // 设置蛇头的坐标
    set X(value){

        //  当蛇的第二节与蛇头的x轴坐标重合,说明发生了水平方向的掉头
        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'
    }
    set Y(value){
        // 当蛇的第二节与蛇头的Y轴坐标重合,发生了垂直方向的掉头
        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'
    }

    // 蛇增加身体
    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';


        }
    }

    checkHandBody():boolean{
        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){
                return false
            }
        }
        return true
    }
}
  • /modules/ScorePanel.ts
export default class ScorePanel{
    score = 0
    level = 1
    scoreElement : HTMLElement
    levelElement : HTMLElement
    maxLevel : number
    upScore : number
    constructor(maxLevel = 10,upScore = 10) {
        this.scoreElement = document.getElementById('score')!
        this.levelElement = document.getElementById('level')!
        this.maxLevel = maxLevel // 最大等级
        this.upScore = upScore // 多少分升一级
    }
    // 增加积分,每吃一个食物增加1分,在此处设置等级的增加
    addScore(){
        this.score ++
        this.scoreElement.innerText = this.score.toString()
        if (this.score % this.upScore === 0){
            this.addLevel()
        }
    }
    // 增加等级
    addLevel(){
        if ( ++this.level <= this.maxLevel) {
            this.levelElement.innerText = this.level.toString()
        }
    }
}

// const a = new ScorePanel()
// for (let i = 0; i < 200; i++) {
//     a.addScore()
// }
  • /modules/Gamecontrol.ts
import Snake from "./snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";

export default class GameControl {
    snake: Snake
    food: Food
    scorePanel: ScorePanel
    dircter = '' // 保存按键的值

    constructor() {
        this.snake = new Snake()
        this.food = new Food()
        this.scorePanel = new ScorePanel()
        this.init()
    }
    // 初始化操作,监听按键事件
    init() {
        // 第二个参数如果不写bind(this),那调用的函数中的this就是document,而不是类的实例化对象
        document.addEventListener("keydown", this.keydownHandler.bind(this))
        this.run()
    }
    // 按键的回调函数
    keydownHandler(event: KeyboardEvent) {
        this.dircter = event.key
    }

    run() {
        // 蛇头的原坐标
        let x = this.snake.X
        let y = this.snake.Y
        // 按下按键后,4个方向中某一个方向的坐标需要修改
        switch (this.dircter) {
            case 'ArrowUp':
            case 'Up':
                y = y - 10
                break;
            case 'ArrowDown':
            case 'Down':
                y = y + 10
                break
            case 'ArrowLeft':
            case 'Left':
                x = x - 10
                break
            case 'ArrowRight':
            case 'Right':
                x = x + 10
                break
        }

        // 蛇头下一步是不是撞墙了
        if (x < 0 || x > 290 || y < 0 || y > 290) {
            alert("蛇撞墙了")
            return
            // 检测蛇头是否撞到自己
        } else if (!this.snake.checkHandBody()) {
            alert('你咬到自己尾巴了')
            return
        } else {
            this.eachFood()
            // 同一时间只可能有一个轴的位置发生改变
            if (this.snake.Y === y) {
                this.snake.X = x
            }
            else if (this.snake.X === x) {
                this.snake.Y = y
            }
            // 开启定时器,随着等级的升高,蛇的移动速度越来越快
            let time = this.scorePanel.level * 50
            setTimeout(this.run.bind(this), 250 - time)
        }


    }

    // 检测蛇是否吃到食物,吃到食物后:新增食物,增加积分,增加蛇的身体
    eachFood() {
        if (this.snake.X === this.food.X && this.snake.Y === this.food.Y) {
            this.food.change()
            this.scorePanel.addScore()
            this.snake.addBody()

        }
    }

}
  • /modules/Food.ts
class Food{
    element:HTMLElement
    constructor() {
        this.element = document.getElementById('food')!
        this.change()
    }
    // 获取食物坐标
    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'
    }
    // 随机在地图上新增食物
    change(){
        let top = Math.round(Math.random()*29) *10
        let left = Math.round(Math.random()*29) *10
        this.X = left
        this.Y = top
    }
}

export default Food

// const a = new Food()
// console.log(a.X,a.Y);
// a.change()
// console.log(a.X,a.Y);

4. 配置文件

  • package.json
{
  "name": "part2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.23.3",
    "@babel/preset-env": "^7.23.3",
    "babel-loader": "^9.1.3",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.33.3",
    "css-loader": "^6.8.1",
    "html-webpack-plugin": "^5.5.3",
    "less": "^4.2.0",
    "less-loader": "^11.1.3",
    "postcss": "^8.4.31",
    "postcss-loader": "^7.3.3",
    "postcss-preset-env": "^9.3.0",
    "style-loader": "^3.3.3",
    "ts-loader": "^9.5.1",
    "typescript": "^5.3.2",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  }
}

  • tsconfig.json
{
  "compilerOptions": {
    "module": "ES6",
    "target": "ES6",
    "strict": true,
    "noEmitOnError": true
  },
}
  • webpack.config.js
// 引入一个包
const path = require('path')
const HTMlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// webpack中的所有的配置信息都应该写在moudle.exports中
module.exports = {
    // 当前为开发模式
    mode: 'development',
    // 指定入口文件
    entry: "./src/index.ts",

    // 打包文件的设置项
    output: {
        // 打包后文件的目录
        path: path.resolve(__dirname,'dist'),
        //  打包后文件的名字
        filename: "bundle.js",
        // 打包后文件不使用箭头函数,不使用const
        environment: {
            arrowFunction: false,
            const:false
        },

    },

    // 指定webpack打包时要使用的模块
    module: {
        // 指定要加载的规则
        rules: [
            {
                // test指定的是规则生效的文件
                test: /\.ts$/,
                // 要使用的loader
                use: [
                    // 将新版本的js转换为旧版本的js,提高代码的兼容性
                    {
                        // 指定加载器
                        loader:'babel-loader',
                        // 设置上面这个加载器的配置项
                        options: {
                            // 设置预定义的环境(代码要在那些浏览器中运行)
                            presets: [
                                [
                                    '@babel/preset-env',
                                    {
                                        // 要兼容的目标浏览器
                                        targets:{
                                            // 'chrome':'88',
                                            'ie':'10'
                                        },
                                        // 指定corejs的版本
                                        'corejs':'3',
                                        // 使用corejs的方式:usage 按需加载
                                        'useBuiltIns':'usage'
                                    }
                                ]
                            ]
                        }
                    },
                    'ts-loader', // 将ts转换为js
                ],
                // 要排除的文件
                exclude: /node_moudles/
            },
            // 设置less文件的处理
            {
                test: /\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions:{
                                plugins: [
                                    [
                                        "postcss-preset-env",
                                        {
                                            browsers:"last 2 versions"
                                        }
                                    ]
                                ]
                            }
                        }
                    },
                    "less-loader"
                ]
            }
        ]
    },
    // 插件
    plugins: [
        // 自动生成html文件,并且引入相关资源
        new HTMlWebpackPlugin({
            // 自动生成的网页以路径中的网页为模板
            template: "./src/index.html"
        }),
        // 自动清除上次编译后的文件
        new CleanWebpackPlugin(),
    ],

    // 设置那些文件可以作为模块可以被引用
    resolve: {
        extensions: ['.ts','.js']
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】从零开始:9.Docker命令:Push推送仓库(Docker Hub,阿里云)

【Docker】从零开始&#xff1a;9.Docker命令:Push推送仓库 知识点1.Docker Push有什么作用&#xff1f;2.Docker仓库有哪几种2.1 公有仓库2.2 第三方仓库2.3 私有仓库2.4 搭建私有仓库的方法有哪几种 3.Docker公有仓库与私有仓库的优缺点对比 Docker Push 命令标准语法操作参数…

Design Guidelines for 100 Gbps

文章目录 Stratix V GT Transceiver ChannelsCFP2 Host Connector Assembly and PinoutStratix V GT to CFP2 Interface Layout DesignBoard Stack Up DimensionsExample Design Channel PerformanceSimulation Results for Stratix V GT to CFP2 Connector Layout Design Desi…

【JavaSE】基础笔记 - 异常(Exception)

目录 1、异常的概念和体系结构 1.1、异常的概念 1.2、 异常的体系结构 1.3 异常的分类 2、异常的处理 2.1、防御式编程 2.2、异常的抛出 2.3、异常的捕获 2.3.1、异常声明throws 2.3.2、try-catch捕获并处理 3、自定义异常类 1、异常的概念和体系结构 1.1、异常的…

Mac安装配置typescript及在VSCode上运行ts

一、Mac上安装typescript sudo npm install -g typescript 测试一下&#xff1a;出现Version则证明安装成功 tsc -v 二、在VSCode上运行 新建一个xxx.ts文件&#xff0c;测试能否运行 console.log("helloworld") 运行报错&#xff1a;ts-node: command not…

LabVIEW中如何达到NI SMU最大采样率

LabVIEW中如何达到NI SMU最大采样率 NISMU的数字化仪功能对于捕获SMU详细的瞬态响应特性或表征待测设备&#xff08;DUT&#xff09;响应&#xff08;例如线性调整率和负载调整率&#xff09;至关重要。没有此功能&#xff0c;将需要一个外部示波器。 例如&#xff0c;假设在…

uniapp 轮播图(含组件封装,自动注册全局组件)

效果预览 组件封装 src\components\SUI_Swiper.vue 可参考官网配置更多属性 swipernavigator <script setup lang"ts"> import { ref } from vue defineProps({config: Object, })const activeIndex ref(0) const change: UniHelper.SwiperOnChange (e) &…

关于elementui和ant design vue无法禁止浏览器自动填充问题

以and design vue 为例&#xff1a; 图标用来显隐账号密码 html&#xff1a; <a-form-model-item label"账号密码:" prop"password"><a-input v-if"passwordTab" ref"passwordInput" v-model"form.password" typ…

element中el-switch的v-model自定义值

一、问题 element中的el-switch的值默认都是true或false&#xff0c;但是有些时候后端接口该字段可能是0或者1&#xff0c;如果说再转换一次值&#xff0c;那就有点太费力了。如下所示&#xff1a; <template><el-switchinactive-text"否"active-text&quo…

计算机网络——路由

文章目录 1. 前言&#xff1a;2. 路由基础2.1. 路由的相关概念2.2. 路由的特征2.3. 路由的过程 3 路由协议3.1. 静态路由&#xff1a;3.2. 动态路由&#xff1a;3.2.1. 距离矢量协议3.2.2. OSPF协议&#xff1a;3.2.2.1.OSPF概述OSPF的工作原理路由计算功能特性 3.2.2.2.OSPF报…

Axios 拦截器 请求拦截器 响应拦截器

请求拦截器 相当于一个关卡&#xff0c;如果满足条件就放行请求&#xff0c;不满足就拦截 响应拦截器 在处理结果之前&#xff0c;先对结果进行预处理&#xff0c;比如&#xff1a;对数据进行一下格式化的处理 全局请求拦截器 axios.interceptors.request.use(config > { /…

一起学docker系列之七docker容器卷技术

目录 1 为什么使用容器数据卷&#xff1f;2 数据卷的特点和优势3 使用数据卷的方法3.1 创建容器并挂载数据卷3.2 容器间数据卷的共享与继承 4 数据卷的权限设置5 注意事项5.1 解决权限问题5.2 路径自动创建 结语 对于容器化应用程序的数据管理和持久化&#xff0c;Docker 数据卷…

【2023 云栖】阿里云刘一鸣:Data+AI 时代大数据平台建设的思考与发布

云布道师 本文根据 2023 云栖大会演讲实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a;刘一鸣 | 阿里云自研大数据产品负责人 演讲主题&#xff1a;DataAI 时代大数据平台应该如何建设 今天分享的主题是 DataAI 时代大数据平台应该如何建设&#xff0…

深度学习技术前沿:探索与挑战

深度学习技术前沿&#xff1a;探索与挑战 一、引言 近年来&#xff0c;深度学习作为人工智能领域的重要分支&#xff0c;取得了令人瞩目的成就。它凭借强大的学习能力和出色的性能&#xff0c;在图像识别、语音识别、自然语言处理等众多任务中展现出巨大潜力。本文将深入探讨深…

后渗透持久性-– 服务控制管理器

执行以下命令将快速检索服务控制管理器实用程序的 SDDL 权限。 sc sdshow scmanager服务控制管理器 – 安全描述符 PowerShell 还可用于枚举所有用户组的 SDDL 权限并将其转换为可读格式。 $SD Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\Schedule\S…

vue3 终端实现 (vue3+xterm+websocket)

目录 一、xterm介绍 二、效果展示 三、vue文件实现代码 一、xterm介绍 xterm是一个使用 TypeScript 编写的前端终端组件&#xff0c;可以直接在浏览器中实现一个命令行终端应用&#xff0c;通常与websocket一起使用。 二、效果展示 三、vue文件实现代码 <template>…

芯能转债上市价格预测

芯能转债-113679 基本信息 转债名称&#xff1a;芯能转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;8.8亿元。 正股名称&#xff1a;芯能科技&#xff0c;今日收盘价&#xff1a;12.63元&#xff0c;转股价格&#xff1a;13.1元。 当前转股价值 转债面…

Nginx结合cpolar实现内网穿透多个Windows Web站点端口

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

spark数据倾斜的解决思路

数据倾斜是&#xff1a;多个分区中&#xff0c;某个分区的数据比其他分区的数据多的多 数据倾斜导致的问题&#xff1a; 导致某个spark任务耗时较长&#xff0c;导致整个任务耗时增加&#xff0c;甚至出现OOM运行速度慢&#xff1a;主要发生在shuffle阶段&#xff0c;同样的k…

【第一部分:概述】ARM Realm Management Monitor specification

目录 概述机密计算系统软件组成MonitorRealmRealm Management Monitor (RMM)Virtual Machine (VM)HypervisorSecure Partition Manager (SPM)Trusted OS (TOS)Trusted Application (TA) Realm Management Monitor 参考文献 概述 RMM是一个软件组件&#xff0c;它构成了实现ARM…

振弦式土压力计在岩土工程安全监测应用的方案

振弦式土压力计在岩土工程安全监测应用的方案 振弦式土压力计是一种常见的土压力测量仪器&#xff0c;其原理是利用振弦在土中传播的速度与土的应力状态有关的特点测量土压力。在岩土工程安全监测中&#xff0c;振弦式土压力计可以应用于以下方面&#xff1a; 1. 地下连续墙和…