大数据最新TypeScript实现小游戏---贪吃蛇(超详细)_typescript游戏项目,2024年最新先睹为快

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    path: path.resolve(__dirname,'dist'),
    //打包后文件的名字
    filename: "bundle.js",

    //告诉webpack不使用箭头函数
    environment: {
        arrowFunction: false
    }
},
mode: 'development',
//指定webpack打包时要使用的模块
module: {
    //指定要加载的规则
    rules: [
        {
            //test指定规则生成的文件
            test: /\.ts$/,
            //要使用的loader
            use : [
                //配置babel
                {
                    // 指定加载器
                    loader: "babel-loader",
                    //设置babel
                    options: {
                        //设置预定义的环境
                        presets:[
                            [
                                //指定环境的插件
                                "@babel/preset-env",
                                //配置信息
                                {
                                    //要兼容的目标浏览器
                                    targets : {
                                        "chrome" : "101"
                                    },
                                    //指定core.js的版本
                                    "corejs":"3",
                                    //使用core.js的方式 usage 按需加载
                                    "useBuiltIns": "usage"
                                }
                            ]
                        ]
                    }
                }
                ,
                '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"
            ]
        }
    ]
},
//配置webpack插件
plugins: [
    new CleanWebpackPlugin(),
    new HTMLWebpackPlugin({
        // title: "自定义的title"
        template: "./src/index.html"
    }),
],


//用来设置引用模块
resolve: {
    extensions: ['.ts', '.js']
}

}



> 
> 到这里,我们要配置的文件都已经配置结束,接下来正式进入项目的开发
> 
> 
> 


## 项目结构搭建



> 
> 首先要进行我们的html和css样式搭建,搭建出来项目的页面!
> 
> 
> 


### html文件



贪吃蛇
    <!--设置食物-->
    <div id="food">
        <!--添加四个小div 来设置食物的样式-->
        <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>

### css文件(这里使用的是less)



// 设置变量
@bg-color: #b7d4a8;
//清除默认样式
* {
margin: 0;
padding: 0;
//改变盒子模型的计算方式
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;
position: absolute;
left: 40px;
top: 100px;

  // 开启弹性盒
  display: flex;
  // 设置横轴为主轴,wrap表示会自动换行
  flex-flow: row wrap;

  // 设置主轴和侧轴的空白空间分配到元素之间
  justify-content: space-between;
  align-content: space-between;

&>div{
width: 4px;
height: 4px;
background-color: black;

    // 使四个div旋转45度
    transform: rotate(45deg);
  }
}

}

// 记分牌
#score-panel{
width: 300px;
display: flex;
// 设置主轴的对齐方式
justify-content: space-between;
}
}


### 项目页面


![在这里插入图片描述](https://img-blog.csdnimg.cn/3a7465b1ba3c45f49ae1444c9c36e844.png#pic_center)


## 多模块搭建


在项目开发中我们不可能把所有的代码写到一个文件中,所以项目开发必须会灵活运用`模块化`开发思想,把实现的功能细化成一个个模块。


### 完成Food(食物)类



//定义食物类
class Food {
element : HTMLElement;

constructor() {
    //获取页面中的food元素并赋给element
    this.element = document.getElementById('food')!;
}
//获取食物x轴坐标的方法
get X() {
    return this.element.offsetLeft;
}
//获取食物y轴坐标的方法
get Y() {
    return this.element.offsetTop;
}
//修改食物位置的方法
change() {
    //生成随机位置
    //食物的最小位置是0 最大是290
    let left = Math.round(Math.random() \* 29) \* 10
    let top = Math.round(Math.random() \* 29) \* 10
    this.element.style.left = left + 'px';
    this.element.style.top = top + 'px';
}

}
export default Food


**代码分析:**


1. 由于在配置typescript时我们设置了strict(严格)模式,因此  
 `this.element = document.getElementById('food')!`中如果我们不加`!`会让编译器不确定我们是否会获取到food的dom元素而发生报错
2. 准备了`get()`方法可以在控制模块中随时获取food的具体定位
3. `change()`方法为随机刷新一次food的位置
4. `export default Food` 代码加在最后。为的是把food成为全局模块暴露出去,这样的话其他的模块可以调用这个food模块


### 完成ScorePanel(记分牌)类



//定义表示记分牌的类
class ScorePanel {
score : number = 0;
level : number = 1;
scoreSpan :HTMLElement;
levelEle : HTMLElement;
//设置变量限制等级
maxLevel : number;
//设置一个变量多少分升级
upScore : number;
constructor(maxLevel : number = 10,Score : number = 10) {
this.scoreSpan = document.getElementById(‘score’)!;
this.levelEle = document.getElementById(‘level’)!;
this.maxLevel = maxLevel
this.upScore = Score
}
//设置加分的方法
AddScore() {
this.score++;
this.scoreSpan.innerHTML = this.score + ‘’
if (this.score % this.upScore === 0 ) {
this.AddLevel()
}
}
//提升等级
AddLevel() {
if (this.level < this.maxLevel) {
this.levelEle.innerHTML = ++this.level +‘’
}
}
}
export default ScorePanel


**代码分析:**  
 在记分牌模块主要是两种方法`AddScore()`和`AddLevel()`,分别用来控制分数增加和等级提升,重点也有设置一个变量来限制等级和设置变量来判断多少分上升一个等级


### 完成Snake(蛇)类



class Snake {
//表示蛇头的元素
head : HTMLElement;
bodies : HTMLCollectionOf;
//获取蛇的容器
element : HTMLElement;
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(this.X === value) {
        return;
    }
    if(value < 0 || value > 290) {
        throw new Error('蛇撞墙了!')
    }
    //修改x时,是在修改水平坐标,蛇在左右移动,蛇在向左移动时,不能向右掉头
    if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
        //如果发生的掉头,让蛇向反方向继续移动
        if(value > this.X) {
            //如果value大于旧值X,则说明蛇在向右走,此时应该发生掉头,应该使蛇继续向左走
            value = this.X - 10
        } else {
            value = this.X + 10
        }
    }
    this.moveBody()
    this.head.style.left = value +'px'
    this.checkHeadBody()
}
set Y(value) {
    if(this.Y === value) {
        return;
    }
    if(value < 0 || value > 290) {
        throw new Error('蛇撞墙了!')
    }
    //修改Y时,是在修改水平坐标,蛇在上下移动,蛇在向上移动时,不能向下掉头
    if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
        //如果发生的掉头,让蛇向反方向继续移动
        if(value > this.Y) {
            //如果value大于旧值X,则说明蛇在向右走,此时应该发生掉头,应该使蛇继续向左走
            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].offsetLeft && this.Y === this.bodies[i].offsetTop) {
//进入判断说明蛇头撞到了身体,游戏结束
throw new Error(‘撞到自己了’)
}
}
}
}
export default Snake


**代码分析:**


1. 首先它自身只添加了三个功能函数addbody,movebody和checkHeadBody
2. `movebody`的实现逻辑非常的巧妙,根据从后往前的顺序来确定位置,根据前一节的位置,从而让后边的位置替换到前一节的位置上,从而实现蛇可以移动的逻辑。
3. 为什么get,set,判断蛇是否死亡机制以及之后的蛇移动的代码一定要写在constructor()函数中而不是写在外面?  
 在后面还有一个控制模块中  
 首先利用get()方法获得蛇头坐标,当蛇头移动一次以后,立刻刷新后的蛇头坐标反馈给蛇对象  
 蛇这个对象更新以后constructor代码就会执行一遍,执行过程中首先蛇头的坐标用set()函数重新设置,然后蛇的`movebody`函数就会执行一次。最后对蛇进行判断死没死。  
 这样一次代码就执行完成啦。此时整条蛇都前进了一次。然后我们通过定时器定个时间不断让蛇移动就可以了。


### 完成GameControl(控制)类



import Food from “./food”;
import Snake from “./Snake”;
import ScorePanel from “./ScorePanel”;
//游戏控制器,控制其他所有类
class GameControl {
snake : Snake;
food : Food;
scorePanel : ScorePanel

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

“./food”;
import Snake from “./Snake”;
import ScorePanel from “./ScorePanel”;
//游戏控制器,控制其他所有类
class GameControl {
snake : Snake;
food : Food;
scorePanel : ScorePanel

[外链图片转存中…(img-tF7loLSM-1715769007482)]
[外链图片转存中…(img-CCUL9MbD-1715769007482)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值