【TypeScript】贪吃蛇小游戏

效果预览

【TypeScript】贪吃蛇小游戏_第1张图片

项目结构

【TypeScript】贪吃蛇小游戏_第2张图片
共有Food,GameControl,ScorePanel,Snake四个类

食物类

//食物类
class Food {
  //食物所对应的元素
  element: HTMLElement;
  constructor() {
    this.element = document.getElementById('food');
  }

  //获取食物位置的方法
  get X() {
    return this.element.offsetLeft;
  }
  get Y() {
    return this.element.offsetTop;
  }

  //食物位置的修改
  change() {
    //生成随机位置
    //0~290的随机数,一格是10px
    //Math.round(Math.random() * 29) * 10
    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;

记分牌类

记分牌只需要控制自己的分数增长和等级提高

/**
 * 记分牌
 */

 class ScorePanel {
  //分数和等级
  score = 0;
  level = 1;
  scoreEle: HTMLElement;
  leveEle: HTMLElement;

  //等级限制
  maxLevel: number;

  //多少分升级
  upLevel: number;

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

  //分数增加方法
  addScore() {
    this.scoreEle.innerHTML = ++this.score + '';

    //每10分升1级
    if(this.score % this.upLevel == 0) {
      this.addLevel();
    }
  }

  //等级提升
  addLevel() {
    if(this.level < 10) {
      this.leveEle.innerHTML = ++this.level + '';
    }
  }
}

export default ScorePanel;

蛇类

蛇类最主要的是身体如何根据蛇头来改变位置
这里是对蛇身体除了蛇头进行遍历,将前一个div的位置赋值给后一个div的位置

/**
 * snake
 */

class Snake {
  //蛇头
  head: HTMLElement;

  //蛇身体
  bodies: HTMLCollection;

  //蛇的容器
  element: HTMLElement;

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

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

  //给蛇头坐标赋值
  set X(value: number) {
    if (this.X === value) {
      return;
    }
    if (value < 0 || value > 290) {
      throw new Error("游戏结束");
    }
    if (
      this.bodies[1] &&
      value === (this.bodies[1] as HTMLElement).offsetLeft
    ) {
      if (value > this.X) {
        value = this.X - 10;
      } else {
        value = this.X + 10;
      }
    }
    this.bodyMove();
    this.head.style.left = `${value}px`;
    this.checkHead();
  }
  set Y(value: number) {
    if (this.Y === value) {
      return;
    }
    if (value < 0 || value > 290) {
      throw new Error("游戏结束");
    }
    if (this.bodies[1] && value === (this.bodies[1] as HTMLElement).offsetTop) {
      if (value > this.Y) {
        value = this.Y - 10;
      } else {
        value = this.Y + 10;
      }
    }
    this.bodyMove();
    this.head.style.top = `${value}px`;
    this.checkHead();
  }

  //蛇的身体增加
  addBody() {
    this.element.insertAdjacentHTML("beforeend", "
"
); } bodyMove() { //遍历到除了蛇头意外的div for (let i = this.bodies.length - 1; i > 0; i--) { //获取前一个div的位置 let preX = (this.bodies[i - 1] as HTMLElement).offsetLeft; let preY = (this.bodies[i - 1] as HTMLElement).offsetTop; //将前一个的位置赋值给当前div的位置 (this.bodies[i] as HTMLElement).style.left = `${preX}px`; (this.bodies[i] as HTMLElement).style.top = `${preY}px`; } } //检查蛇头有没有撞到自己 checkHead() { for(let i = 1; i < this.bodies.length; i++) { let bd = (this.bodies[i] as HTMLElement); if(this.X === bd.offsetLeft && this.Y === bd.offsetTop) { throw new Error("蛇撞到自己的身体了"); } } } } export default Snake;

整个游戏控制类

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

//游戏控制器
class GameControl {
  //蛇
  snake: Snake;
  food: Food;
  scorePanel: ScorePanel;

  //存储蛇的移动方向
  direction: string;

  //记录游戏是否结束
  isLive: boolean = true;

  constructor() {
    this.snake = new Snake();
    this.food = new Food();
    this.scorePanel = new ScorePanel(10, 2);

    this.init();
  }

  //初始化
  init() {
    document.addEventListener("keydown", this.keyDownHandler.bind(this));
    this.run();
  }

  keyDownHandler(event: KeyboardEvent) {
    //判断按键是否合法
    this.direction = event.key;
  }

  //让蛇移动的方法
  run() {
    let X = this.snake.X;
    let Y = this.snake.Y;

    switch (this.direction) {
      case "ArrowUp":
        Y -= 10;
        break;
      case "ArrowDown":
        Y += 10;
        break;
      case "ArrowLeft":
        X -= 10;
        break;
      case "ArrowRight":
        X += 10;
        break;
    }
    //检查蛇是否吃到食物
    this.checkEat(X, Y);

    try {
      this.snake.X = X;
      this.snake.Y = Y;
    } catch (err) {
      alert(err);
      this.isLive = false;
    }
    this.isLive &&
      setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 50);
  }

  checkEat(x: number, y: number) {
    if (x === this.food.X && y === this.food.Y) {
      this.food.change();
      this.scorePanel.addScore();
      this.snake.addBody();
    }
  }
}

export default GameControl;

完整项目代码

https://gitee.com/tao-yuhan/type-script-snake.git

你可能感兴趣的:(TypeScript,ts,typescript)