您的位置:首页 > Web前端 > JavaScript

TypeScript实战 -- 贪吃蛇游戏(1)--项目简介与具体实现、实现食物类和计分板类

2021-04-20 17:07 1121 查看

TypeScript实战 – 贪吃蛇(1)

目的

使用typescript以及面向对象的方式编写简易版贪吃蛇的项目,实现:蛇自主移动,吃到食物检测并增加身体长度,食物随机生成,计分板,撞墙检测,键盘事件检测等基本功能。

界面


分析

总体来说,整个游戏中所含的类可以分为四个:蛇(Snake),食物(Food),计分板(Scoreboard),游戏控制器(GameController)。

  • Snake:获取与设置蛇身体部分的位置,增加长度,处理撞墙,检测是否吃到自己,禁止掉头
  • Food:获取与设置食物位置,随机改变位置
  • Scoreboard:获取积分和等级,增加积分,增加等级
  • GameController:控制游戏开始和结束,吃到食物检测,蛇移动,调用其他各对象的方法完成游戏的逻辑。

还需要一个HTML作为界面展示,具体typescript简单项目搭建,webpack配置可以看我另外一个文章讲了如何从0开始搭建简单的webpack编译ts的项目

HTML整体结构与样式不多赘述

注意的地方就是:因为每次吃到食物后,增加一段,增加的是蛇容器里面的子元素,所以我们对于蛇的样式需要加在蛇的子元素上,而蛇容器不必加样式和定位

HTML:

<html>
<head>
<title>贪吃蛇</title>
</head>
<body>
<div class="snake_pos
20000
tion">
<div class="snake_body">
<div class="snake_body_screen">
<!-- 设置蛇 -->
<div class="snake">
<div></div>
</div>
<!-- 设置食物 -->
<div class="food"></div>
</div>
<div class="snake_body_score_level">
<div class="snake_body_item">level:
<span class="level">0</span>
</div>
<div class="snake_body_item">grade:
<span class="score">0</span>
</div>
</div>
</div>
</div>
</body>

</html>

CSS(将主要用到的列了出来):

/* 定位总游戏盒子  */
.snake_postion{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
/* 游戏盒子  */
.snake_body{
width: 324px;
height: 400px;
background: #1e272e;
border-radius: 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 10px;
box-shadow: 0 0 15px #1e272e;
}
/* 屏幕 */
.snake_body_screen{
background: #485460;
height: 304px;
box-sizing: border-box;
border-radius: 6px;
border: 2px solid #808e9b;
position: relative;
}
/* 记分板 */
.snake_body_score_level{
border-radius: 6px;
text-align: center;
font-size: 20px;
color: #fff;
line-height: 50px;
display: flex;
}
/* 记分板各项 */
.snake_body_item{
width: 50%;
font-size: 14px;
text-shadow: 0 0 10px #222f3e;
}
/* 蛇身体 */
.snake > div{
width: 10px;
height: 10px;
background: #222f3e;
border: 1px solid #808e9b;
position: absolute;
border-radius: 2px;
}
/* 蛇头 */
.snake > div:nth-child(1){
width: 10px;
height: 10px;
background: #3c6382;
border: 1px solid #808e9b;
position: absolute;
border-radius: 2px;
left: 20px;
top: 20px;
}
/* 食物 */
.food{
width: 10px;
height: 10px;
background: #222f3e;
border: 1px solid #808e9b;
position: absolute;
left: 120px;
top: 100px;
border-radius: 2px;
}

各类的具体分析与实现

我们最好将各类分成各个模块,这样好维护。

因为从分析来看,食物类和计分板类是最简单的两个类,所以先将它们实现

Food类

食物类包含了获取和设置食物位置,随机改变食物位置

  • 实现步骤

      定义存放食物元素的变量
    1. 使用
      document.querySelector
      获取食物元素
    2. 使用
      offsetTop
      offsetLeft
      获取食物的位置
      get
      set
      设置食物的位置
    3. 因为我们屏幕的有效长宽是290px,每次移动10px,所以我们只需要取0-29的随机数,最后再乘以10就行了。使用
      Math.random
      Math.round
      实现随机取数
    4. 赋值给食物元素的样式
  • 具体代码

    // 定义食物类
    class Food{
    // 定义存储元素的变量
    private element: HTMLElement;
    
    constructor() {
    // 拿到元素
    this.element = document.querySelector(".food")!;
    }
    
    get X() {
    // 得到left值
    return this.element.offsetLeft;
    }
    
    get Y() {
    // 得到top值
    return this.element.offsetTop;
    }
    
    // 吃到一个事物改变位置
    change() {
    // 这里left和top需要分别拿,不然就只能走对角线了
    let left = Math.round(Math.random() * 29) * 10;
    let top = Math.round(Math.random() * 29) * 10;
    // 赋值给food实现随机改变位置
    this.element.style.left = left + 'px';
    this.element.style.top = top + 'px';
    }
    }
    
    export default Food;

    测试代码

    项目入口文件

    index.ts
    增加如下测试代码

    import Food from './modules/Food';
    
    const testFood = new Food();
    testFood.change();

    然后刷新多次页面查看食物随机改变的效果

Scoreboard类

包含了获取积分和等级,增加积分,增加等级的功能

  • 实现步骤

      我们需要定义四个变量,存放等级
      level
      和积分
      score
      ,等级显示元素和积分显示元素
    1. 如果还想自定义升级的规则和最大等级可以定义两个变量去控制
    2. 升级和积分增加都是先将现在的
      level
      score
      自增后往各自的元素的
      innerHTML
      添加即可
  • 具体代码

    // 定义记分牌
    class LevelScore{
    // 等级
    private level: number = 1;
    // 积分
    private score: number = 0;
    // 控制升级规则(每吃多少个升一级)
    private levelItem: number;
    // 最大等级
    private maxLevel: number;
    
    // 显示等级的元素
    private levelElement: HTMLElement;
    // 显示积分的元素
    private scoreElement: HTMLElement;
    
    // 给出初始值定义初始规则:吃10个食物升一级,最高等级10及
    constructor(leveItem: number = 10, maxLevel: number = 10) {
    this.levelItem = leveItem;
    this.maxLevel = maxLevel;
    this.levelElement = document.querySelector(".level")!;
    this.scoreElement = document.querySelector(".score")!;
    }
    
    // 增加积分
    addScore() {
    this.scoreElement.innerHTML = ++this.score + '';
    // 如果当前的积分和升级规则规定的个数取余为0,说明达到规定个数升级
    if (this.score % this.levelItem === 0) {
    this.levelUp();
    }
    }
    
    levelUp() {
    if (this.level < this.maxLevel) {
    this.levelElement.innerHTML = ++this.level + '';
    }
    }
    
    getlevel() {
    return this.level;
    }
    getScore() {
    return this.score;
    }
    }
    
    export default LevelScore;

测试代码

项目入口文件

index.ts
增加如下测试代码

import LevelScore from './modules/LevelScore'

const testLevelScore = new LevelScore();
setInterval(()=>{
testLevelScore.addScore();
},1000)

查看页面对于我们增加分数和增加等级规则的测试

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: