TS项目(贪吃蛇)

1. 项目搭建配置

// webpack.config.js  tsconfig.json  package.json配置代码
// 1. package.json
{
  "name": "part5",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development",
    "start": "webpack serve --open --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.13",
    "@babel/preset-env": "^7.18.10",
    "babel-loader": "^8.2.5",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.25.0",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.3.1",
    "typescript": "^4.8.2",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.10.1"
  }
}

// 2. tsconfig.json
{
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": true,
        "noEmitOnError": true
    }
}

// 3 .webpack.config.js

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

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

    // 指定打包文件所在目录
    output: {
        // 指定打包的目录
        path: path.resolve(__dirname, 'dist'),

        // 打包后的文件
        filename: "bundle.js",

        // 告诉webpack不使用箭头函数
        environment: {
            arrowFunction: false
        }
    },

    // 指定webpack打包时要使用模块
    module: {
        // 指定要加载的规则
        rules: [
            {
                // test指定的是规则生效的文件
                test: /\.ts$/,
                // 要使用的loader
                use: [
                    // 配置babel
                    {
                        // 指定加载器
                        loader: "babel-loader",
                        // 设置babel
                        options: {
                            // 设置预定义的环境
                            presets: [
                                [
                                    // 指定环境的插件
                                    "@babel/preset-env",
                                    // 配置信息
                                    {
                                        // 要兼容的目标浏览器
                                        targets: {
                                            
                                            "chrome": "88"
                                        },
                                        // 指定corejs版本
                                        "corejs": "3",
                                        // 使用codejs的方式:usage表示按需加载
                                        "useBuiltIns": "usage"
                                    }
                                ]
                            ]
                        }
                    },
                    'ts-loader' // 后面的先执行
                ],
                // 要排除的文件
                exclude: /node_modules/
            },

            // 设置less文件的处理
            {
                test: /\.less$/,
                use: [ // 从下往上执行,先less 后css 最后style
                    "style-loader",
                    // 引入postcss
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    [
                                        "postcss-preset-env",
                                        {
                                            // 兼容最新的2个浏览器
                                            browsers: 'last 2 versions'
                                        }
                                    ]
                                ]
                            }
                        }
                    },
                    "css-loader",
                    "less-loader"
                ]
            }
        ]
    },

    // 配置webpack插件
    plugins: [
        new CleanWebpackPlugin(),
        new HTMLWebpackPlugin({
            // title: "这是一个自定义的title"
            template: "./src/index.html"
        })
    ],

    // 用来设置引用模块, 告诉它凡是以js,ts结尾都是可以使用模块化
    resolve: {
        extensions: ['.ts', '.js']
    }
};





2. 创建part5文件夹

// 创建part文件夹, 将上方三个配置放置part文件夹下方,然后使用npm i安装依赖
// 在part文件夹下创建src,src下创建index.html和index.ts, 然后使用npm run build打包
// 安装less,npm i -D less less-loader css-loader style-loader
// webpack配置完less后,直接npm start运行项目

// 在src下创建style文件夹,style下创建index.less
body {
    background: 'red';
}

// 在index.ts 引入样式, 然后就可以检测页面是否生效
import './style/index.less';

// 继续安装依赖, 然后在webpack配置
npm i -D postcss postcss-loader postcss-preset-env

3. 贪吃蛇ts代码(本例子只填写关于ts,html和css在这不做笔记)

// 定义类
class Food {
    // 定义一个属性表示食物所对应的元素
    element: HTMLElement;
    constructor () {
        // 后面不加!会报错,因为document.getElementById('food')可能为空,后面加!表示一定不会为空
        this.element = document.getElementById('food')!;
    }

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

    get Y () {
        return this.element.offsetTop;
    }

    // 修改食物的位置
    change () {
        // 生成一个随机的位置
        // 食物的位置最小是0最大是290
        // 蛇移动一次就是一格,一格的大小就是10,所以食物的坐标必须是整10
        //  Math.random(Math.random() * 29); 0-29
        const top = Math.round(Math.random() * 29) * 10;
        const left = Math.round(Math.random() * 29) * 10;
        this.element.style.left = left + 'px';
        this.element.style.top = top + 'px';
    }
}

// 测试代码
// const food = new Food();
// console.log(food.X, food.Y); // 40 100
// food.change();
// console.log(food.X, food.Y); // 80 180

// 定义表示记分牌的类
class ScorePanel {
    // score和level用来记录分数和等级
    score = 0;
    level = 1;

    // 分数和等级所在的元素, 在构造函数中进行初始化
    scoreEle: HTMLElement;
    levelEle: HTMLElement;

    // 设置一格变量限制等级
    maxLevel: number;
    // 设置一个变量表示多少分时升级
    upScore: number

    constructor (maxLevel: number = 10, upScore: number = 10) {
        this.scoreEle = document.getElementById('score')!;
        this.levelEle = document.getElementById('level')!;
        this.maxLevel = maxLevel;
        this.upScore = upScore;
    }

    // 设置一个加分的方法
    addScore () {
        // 分数自增
        this.score++;
        this.scoreEle.innerHTML = this.score + '';

        if (this.score % this.upScore === 0) {
            this.levelUp();
        }
    }

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

// 测试

const scorePanel = new ScorePanel();
scorePanel.addScore();

// 蛇的类
class Snack {
    // 表示蛇头的元素
    head: HTMLElement;
    // 蛇的身体(包括蛇头)
    bodies: HTMLCollection;
    // 获取蛇的容器
    element: HTMLElement;

    constructor () {
        this.element  = document.getElementById('snack')!;
        this.head = document.querySelector('#snack > div')! as HTMLElement;
        this.bodies = document.getElementById('snack')!.getElementsByTagName('div');
    }

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

    // 获取蛇的Y轴坐标
    get Y() {
        return this.head.offsetTop;
    }

    set X (value: number) {
        // 如果新值和旧值相同,则直接返回,不再修改
        if (this.X === value) {
            return;
        }

        // X的值的合法范围0-290之间
        if (value < 0 || value > 290) {
            // 进入判断,说明蛇撞墙了, 抛出一个异常
            throw new Error('蛇撞墙了');
        }

        this.head.style.left = value + 'px';
    }

    set Y (value: number) {
        // 如果新值和旧值相同,则直接返回,不再修改
        if (this.Y === value) {
            return;
        }

        // Y的值的合法范围0-290之间
        if (value < 0 || value > 290) {
            // 进入判断,说明蛇撞墙了, 抛出一个异常
            throw new Error('蛇撞墙了');
        }

        this.head.style.top = value + 'px';
    }

    // 蛇增加身体的方法
    addBody() {
        // 向element中添加一个div
        this.element.insertAdjacentHTML('afterend', "<div></div>");
    }
}

// 游戏控制器, 控制其他的所有类
class gameControl {
    // 定义三个属性
    // 蛇
    snack: Snack;
    // 食物
    food: Food;
    // 记分牌
    scorePanel: ScorePanel;

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

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

    constructor () {
        this.snack = new Snack();
        this.food = new Food;
        this.scorePanel = new ScorePanel;
        this.init();
    }

    // 游戏初始化方法, 调用后游戏即开始
    init () {
        // 绑定键盘按键按下的事件
        document.addEventListener('keydown', this.keyDownHandler.bind(this));
        // 调用init方法

        this.run();
    }

    // 创建一个键盘按下的响应函数
    keyDownHandler = (event: KeyboardEvent) => {
        // chrome      IE
        // ArrowUp     up
        // ArrowDown   down
        // ArrowLeft   left
        // ArrowRight  right
        // 在IE和Chrome值不一样
        // console.log(event.key);
        // 需要检查值是否合法(用户是否按了正确的按键)
        this.direction = event.key;
    }

    // 创建一个控制蛇移动的方法
    run () {
        // 根据方向(this.direction)来使蛇的位置改变
        /**
         * 向上 top减少
         * 向下 top增加
         * 向左 left减少
         * 向右 left增加
         */
        // 获取蛇现在的坐标
        let X = this.snack.X;
        let Y = this.snack.Y;

        // 根据按键方向来修改X值和Y值
        switch (this.direction) {
            case 'ArrowUp':
            case 'up':
                // 向上移动  top减少
                Y -= 10;
                break;
            case 'ArrowDown':
            case 'down':
                // 向下移动 top增加
                Y += 10;
                break;
            case 'ArrowLeft':
            case 'left':
                // 向左移动 left减少
                X -= 10;
                break;
            case 'ArrowRight':
            case 'right':
                X += 10;
                // 向右移动 left增加
                break;
        }

        // 检查蛇是否迟到了食物
        this.checkEat(X, Y);

        // 修改蛇的X和Y值
        try {
            // 修改蛇的X和Y值
            this.snack.X = X;
            this.snack.Y = Y;
        } catch (error) {
            // 进入catch 说明出现了异常,游戏结束,弹出一个提示信息
            alert((error as Error).message);
            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.snack.addBody();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值