TypeScript 第十一天,贪吃蛇TS项目实例

4 阅读2分钟

不废话,我们这里直接上代码了。请看下面:

Food.ts

这个是食物类,代码如下:

class Food{
    element:HTMLElement;

    constructor(){
        this.element = document.getElementById('food')!;
    }

    get X(){
        return this.element.offsetLeft;
    }

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

    change(){
       this.element.style.left = Math.round(Math.random()*29)*10 + 'px';
       this.element.style.top = Math.round(Math.random()*29)*10 + 'px'; 
    }
}

export default Food;

GameControl.ts

控制器类,代码如下:

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

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,10);
      this.init();
   }

   init(){
      document.addEventListener('keydown',this.keydownHandler.bind(this));
      this.run();
   }

//    创建键盘事件
   keydownHandler(event:KeyboardEvent){
      // 检查event.key是否合法
    //   if(this.direction === 'ArrowRight' && event.key === 'ArrowLeft'){
    //      return; 
    //   }
      this.direction = event.key; 
   }

   run(){
     let X = this.snake.X; 
     let Y = this.snake.Y;
     switch(this.direction){
        case 'ArrowUp':
        case 'Up':
           Y -= 10;
           break;
        case 'ArrowDown':
        case 'Down':
           Y += 10;
           break;
        case 'ArrowLeft':
        case 'Left':
           X -= 10;
           break;
        case 'ArrowRight':
        case 'Right':
           X += 10;
           break;
     } 
     this.checkEat(X,Y);
     try{
         this.snake.X = X;
         this.snake.Y = Y;
     }catch (e){
      //   alert(e.message+'Game Over');
      // console.log();
        alert(e.message+'Game Over');
        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.snake.addBody();
      }
   }

}

export default GameControl;

ScorePanel.ts

这个里面记分牌的类,代码如下

// 定义表示记分牌的类
class ScorePanel{
    // 记录分数和等级
    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.scoreEle.innerHTML = ++this.score + '';
        if(this.score % this.upScore === 0){
            this.levelUp();
        }
    }

    levelUp(){
        if(this.level < this.maxLevel){
            this.levelEle.innerHTML = ++this.level + '';
        }
        return this.level;
    }
}

export default ScorePanel;

Snake.ts

蛇的类,代码如下:

class Snake{
    // 蛇的元素
    head:HTMLElement;
    bodies:HTMLCollection;
    element:HTMLElement;
    constructor(){
        this.element = document.getElementById('sink')!;
        this.head = document.querySelector('#sink > div') as HTMLElement;
        this.bodies = this.element.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] && (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';
        this.checkHeadBody();
    }

    set Y(value:number){
        if(this.Y === value) return;
        if(value < 0 || value > 290){
            throw new Error('蛇撞墙了 !'); 
        }
        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';
        this.checkHeadBody();
    }

    // 蛇增加身体
    addBody(){
        // 创建一个div
        let div = document.createElement('div');
        this.element.insertAdjacentElement('beforeend',div);
    }

    moveBody(){ 
        // 遍历所有的身体,让每一个身体都去移动到下一个身体位置
        // 遍历的顺序,是 backwards
        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.top = Y + 'px';
            (this.bodies[i] as HTMLElement).style.left = X + 'px';
        }
    }

    checkHeadBody(){
        for (let i = 1; i < this.bodies.length; i++) {
            let bd = this.bodies[i] as HTMLElement;
            if(bd.offsetLeft === this.X && bd.offsetTop === this.Y){
                throw new Error('撞到自己了!');
            }
        }
    }
}

export default Snake;

感谢大家观看,这一篇水了,哈哈哈有机会再好好改改。我们下次见