原生canvas的简单贪吃蛇

用原生canvas做个贪吃蛇

贪吃蛇设计的原理

通过观察贪吃蛇,发现可以通过把蛇身上最后一个元素,移动到头部位置来实现蠕动,新的位置通过当前的头部坐标和当前的方向判断。所以要实现很简单的。

用canvas如何实现

蛇的身体通过若干矩形绘制,所以要有个数组来存储矩形开始绘制的坐标和颜色等信息,监听按键来改变当前的方向。生成的果子也是随机的,不在蛇身上就可以了。
下面是实现后的贪吃蛇:在这里插入图片描述

粗暴地上代码(都有注释)

没有做碰撞检测,撞墙了或者吃到自己了也不会挂。可能跑到地图外去,就很难找回了( ̄▽ ̄)/
v-dragable是我自定义的指令,要去掉的。蛇身上的属性并没有做处理,理论上要重新赋一遍值。
当然如果有环形链表实现起来就要简单很多。之所以会有白色的轨迹是因为尾部被移开的元素被白色填充,看起来就像白色的轨迹,也是个特效吧(^_^)☆

<template>
    <div class='snake_cnt' :style="{'width':width||'480px'}" v-dragable>
        <div class='head clear-float'>snake<span class='el-icon-close icon' @click="close"></span></div>
        <div class="main">
            <canvas ref="mainCav" :height="cavHeight" :width="cavWidth"></canvas>
        </div>
        <div>分数:{{score}}</div>
        <div>
            <el-button size="small" @click="startGame">开始</el-button>
            <el-button size="small" @click="pauseGame">停止</el-button>
        </div>
    </div>
</template>
<script>
export default {
    name:'greedy-snake',
    comments:{
        
    },
    props: ['width'],
    data() {
        return {
            cavWidth:720,
            cavHeight:200,
            scale:5,//比例
            snake:[{x:0,y:0,color:"green"},{x:5,y:0,color:"green"}],//蛇的组成数组
            score:0,//得分
            speed:200,//蛇移动的间隔ms
            ctx:null,
            direction:"right",
            handleMove:null,//定时器句柄
            food:[],//理论来说只有一个食物,需要多个要改代码
        }
    },mounted() {
        this.ctx=this.$refs.mainCav.getContext("2d");
        console.log(this.ctx);
    },methods: {
        close(){
            this.$emit("execTrans",{fnc:"closeDialog",param:['showSnake']})
        },startGame(){//开始游戏
            let that=this;
            this.drawSnake();
            this.initFood();
            document.addEventListener("keydown",function(event){
                console.log(event);
                if([37,38,39,40].indexOf(event.keyCode)!=-1 && that.handleMove){//有效按键,并且游戏运行按键事件触发
                    that.direction=["left","up","right","down"][event.keyCode-37];console.log(that.direction)
                    that.drawSnake();
                }
            });
        },drawSnake(){
           let that=this;clearInterval(this.handleMove);
           this.handleMove=setInterval(()=>{
                that.ctx.save();
                let ele={...[...that.snake].pop()};
                if(that.direction=="up"){
                    ele.y-=that.scale;
                }
                if(that.direction=="down"){
                    ele.y+=that.scale;
                }
                if(that.direction=="right"){
                    ele.x+=that.scale;
                }
                if(that.direction=="left"){
                    ele.x-=that.scale;
                }
                that.snake.push(ele);//头部,通过原头部和方向判断新头部的位置
                let oldele=that.snake.shift();
                if(that.food.some((item)=>item.x==ele.x&&item.y==ele.y)){//吃到食物了没有 
                    that.snake.unshift({
                        x:oldele.x,
                        y:oldele.y,
                        color:"green"
                    });//后面插入一个元素
                    that.score+=10;//吃掉加10分
                    that.initFood();//吃掉后新增食物
                }
                //边界限制未设置
                that.ctx.fillStyle="white";
                that.ctx.fillRect(oldele.x,oldele.y,5,5);console.log(that.snake,oldele);
                that.ctx.restore();
                that.snake.forEach(item => {
                    that.ctx.save();
                    that.ctx.fillStyle=item.color;
                    // that.ctx.translate(item.x,item.y);
                    that.ctx.fillRect(item.x,item.y,5,5);
                    that.ctx.restore();
                });
            },that.speed);
        },pauseGame(){
            clearInterval(this.handleMove);
        },initFood(){//初始化食物
            let pos={},that=this;
            function getPos(){
                pos.x=Math.ceil((Math.random()*that.cavWidth)/5)*5;
                pos.y=Math.ceil((Math.random()*that.cavHeight)/5)*5;
                that.snake.some((item)=>item.x==pos.x&&item.y==pos.y) && getPos();
            }
            getPos();//获取随机的坐标,但不能在蛇身上
            this.ctx.save();
            that.ctx.fillStyle="red";
            that.ctx.fillRect(pos.x,pos.y,5,5);
            that.ctx.restore();//绘制小红点食物
            that.food.push(pos);
        }
    },
}

还是工作太闲了,别被老板发现才好 (=´ω`=)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值