使用Ts编写一个贪吃蛇小游戏(完结版)

ts编写贪吃蛇内部逻辑

这个小游戏主要包括积分面板,食物,蛇,还有我们的游戏控制器这四个部分,分为四个类来写。
创建一个食物的类(详解在代码注释):

// 定义一个食物的类
class Food{
    // 属性
    element:HTMLElement;
    constructor(){
        this.element=document.getElementById("food")!;
    }

    // 定义获取食物的x轴坐标
    get X(){
        return this.element.offsetLeft;
    }
    // 定义获取食物的y轴坐标
    get Y(){
        return this.element.offsetTop;
    }

    // 定义food位置的方法
    change(){
        // 定义food出现位置随机的数
        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;
    // 等级限制的变量
    levelLimit:number;
    // 多少分时升级的变量
    upSocre:number;
    // score元素标签
    scoreSpan:HTMLElement;
    // level元素标签
    levelSpan:HTMLElement;
    constructor(levelLimit:number,upSocre:number){
        this.scoreSpan = document.getElementById("score")!;
        this.levelSpan = document.getElementById("level")!;
        this.levelLimit = levelLimit;
        this.upSocre = upSocre;
    }
    
    // 增加分数方法
    addScore(){
        this.scoreSpan.innerHTML = ++this.score + "";
        if(this.score % this.upSocre === 0){
            this.addLevel();
        }
    }
    // 增加等级的方法
    addLevel(){
        if(this.level < this.levelLimit){
            this.levelSpan.innerHTML = ++this.level + "";
        }
    }
}
// 向外暴露我们的积分面板类
export default ScorePanel;

创建一个我们的主角蛇类:

class Snake{
    // 表示蛇头的元素
    head:HTMLElement;
    // 表示蛇的身体(包括蛇头)
    bodies:HTMLCollection;
    // 获取蛇的容器
    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:number){
        // 判断蛇是否在移动的范围内
        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 = this.X - 10;
            }else{
                value = this.X + 10;
            }
        }
        this.removeBody();
        this.head.style.left = value + "px"; 

    }
    set Y(value:number){
        // 判断蛇是否在移动的范围内
        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 = this.Y - 10;
            }else{
                value = this.Y + 10;
            }
        }
        // 调用身体移动的方法
        this.removeBody();
        this.head.style.top = value + "px"; 
        this.checkHeadBody();
    }
    // 蛇增加身体的方法
    addBody(){
        // 向element中添加div
        this.element.insertAdjacentHTML("beforeend","<div></div>");
    }
    // 蛇身体移动的方法
    removeBody(){
        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-1; i++){
            let bd = this.bodies[i] as HTMLElement;
            if(this.X === bd.offsetLeft && this.Y === bd.offsetTop){
                throw new Error("蛇吃到自己的身体了");
            }
        }
    }
}
// 向外暴露我们的蛇类
export default Snake;

创建我们的游戏控制器类,这个类控制我们的游戏开始或者结束:

import Snake from "./Snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";
// 游戏的控制器,控制其他的所有类
class GameControl {
    // 定义三个属性
    snake: Snake;
    food: Food;
    scorePanel: ScorePanel;
    // 定义获取键盘按键的字符串
    direction: String = '';

    // 判斷蛇是否去世
    isField:boolean = true;
    constructor() {
        this.snake = new Snake();
        this.food = new Food();
        this.scorePanel = new ScorePanel(10, 2);
        this.init();
    }
    // 游戏开始的初始化方法
    init() {
        // 绑定键盘事件
        // .bind() 创建一个新函数,使this指向我们的GameControl这个对象
        document.addEventListener("keydown", this.keydownHandler.bind(this));
        this.run();
    }
    // 创建一个键盘按下的响应函数
    keydownHandler(event: KeyboardEvent) {
        // 修改direction属性
        this.direction = event.key
    }
    // 创建蛇动的方法
    // ArrowUp Up  ArrowRight Right ArrowLeft Left ArrowDown Down 
    run() {
        let X = this.snake.X;
        let Y = this.snake.Y;
        switch (this.direction) {
            case 'ArrowUp':
            case 'Up':
                Y -= 10;
                break;
            case 'ArrowRight':
            case 'Right':
                X += 10;
                break;
            case 'ArrowLeft':
            case 'Left':
                X -= 10;
                break;
            case 'ArrowDown':
            case 'Down':
                Y += 10;
                break
        }
        try{
            this.snake.X = X;
            this.snake.Y = Y;
        }catch(e){
            // 提示蛇已经撞墙
            alert("Game Over!");
            // 停止移动
            this.isField = false;
        }
        
        // 调用蛇吃到食物的方法
        this.checkEat(X,Y);
        // 蛇等级的提升移动速度的改变
        this.isField && setTimeout(this.run.bind(this),300-(this.scorePanel.level-1)*30);
    }
	//当吃到食物,发生的系列游戏行为
    checkEat(X:number,Y:number){
        if(this.food.X === X && this.food.Y === Y){
        	// 食物位置的改变
            this.food.change();
            // 积分等级的改变
            this.scorePanel.addScore();
            // 蛇长度的改变
            this.snake.addBody();
        }
    }
}
// 向外暴露我们的GameControl类
export default GameControl;

这样我们的蛇的基本逻辑就已经实现了,我们只需要启动我们的GameControl这个类,整个游戏就可以运行起来了。
创建一个主index.ts文件,引入我们的GameControl类,创建GameControl的实例对象:

import './style/style.less';
import GameControl from "./model/GameControl"
// 创建实例对象启动游戏
const ga = new GameControl();

效果:
在这里插入图片描述
这里打开我们的网页,按方向键就能开始游戏了,吃到食物后左上角有个小问题,也不是太清楚,这里为什么会闪一下,还是有待完善的地方,但是总体上还是能运行下去。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值