H5 canvas实现贪吃蛇小游戏

所属分类: 网页制作 / html5 阅读数: 319
收藏 0 赞 0 分享

本文介绍了H5 canvas实现贪吃蛇小游戏,分享给大家,具体如下:

实现效果如下

实现思路:

ps:这个只是思路,详细可看代码注释

一、先把蛇画出来

  1. 定义一下蛇的结构,用一个数组保存一堆矩形,包含蛇头(红)和蛇身(灰)。
  2. 画蛇(初始状态)

二、蛇能动(重点)

  1. 蛇移动方式:自始至终都只有蛇头在动
    1. 画一个灰色的方块,位置与蛇头重叠
    2. 将这个方块插到数组中蛇头后面一个的位置arrar.splice(0,1,rect)
    3. 砍去末尾的方块array.pop()
    4. 将蛇头向设定方向移动一格
  2. 需要一个保存方向的变量(direction)
  3. 根据方向进行移动,一次移动一个格
  4. 根据按键改方向

三、随机投放食物

  1. 需要随机食物的位置
  2. 需要判断食物在不在蛇身上。

四、吃食物

  1. 判断食物是否与蛇头重叠
  2. 数组加一个元素(少删除一个元素就是加一个元素)
  3. 生成新的食物

五、gameover

  1. 撞墙判定
  2. 装自己判定
     
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        #canvas{
            box-shadow: 0 5px 40px black;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="800" height="500"></canvas>
</body>
<script>
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');

    //构造对象方块
    function Rect (x,y,w,h,color) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.color = color;
    }
    //画方块的方法
    Rect.prototype.draw = function () {
        context.beginPath();
        context.fillStyle = this.color;
        context.rect(this.x,this.y,this.w,this.h);
        context.fill();
        context.stroke();
    }

    //构造对象蛇
    function Snake () {

        //定义一个空数组存放组成整蛇的方块对象
        var snakeArray = [];

        //画出4个方块,设置成灰色
        for (var i = 0; i < 4; i++) {
            var rect = new Rect(i*20,0,20,20,"gray");
            //之所以用splice(往前加)而不是用push(往后加),是为了让蛇头出现在数组第一个位置
            snakeArray.splice(0,0,rect);     
        }

        //把数组第一个作为蛇头,蛇头设成红色
        var head = snakeArray[0];
        head.color = "red";

        //此处将两个后面常用的东西定为属性,方便后面调用
        this.head = snakeArray[0];  //蛇头
        this.snakeArray = snakeArray;  //整蛇数组

        //给定初始位置向右(同keyCode右箭头)
        this.direction = 39;
    }
    //画蛇的方法
    Snake.prototype.draw = function () {
        for (var i = 0; i < this.snakeArray.length; i++) {
            this.snakeArray[i].draw();
        } 
    }
    //蛇移动的方法
    Snake.prototype.move = function () {

        //此处是核心部分,蛇的 移动方式
        //1、画一个灰色的方块,位置与蛇头重叠
        //2、将这个方块插到数组中蛇头后面一个的位置
        //3、砍去末尾的方块
        //4、将蛇头向设定方向移动一格
        var rect = new Rect(this.head.x,this.head.y,this.head.w,this.head.h,"gray");
        this.snakeArray.splice(1,0,rect);

        //判断是否吃到食物,isEat判定函数写在最后了
        //吃到则食物重新给位置,不砍去最后一节,即蛇变长
        //没吃到则末尾砍掉一节,即蛇长度不变
        if (isEat()){
            food = new getRandomFood();
        }else{
            this.snakeArray.pop();
        }

        //设置蛇头的运动方向,37 左,38 上,39 右,40 下
        switch (this.direction) {
            case 37:
                this.head.x -= this.head.w
                break;
            case 38:
                this.head.y -= this.head.h
                break;
            case 39:
                this.head.x += this.head.w
                break;
            case 40:
                this.head.y += this.head.h
                break;
            default:    
                break;
        }

        // gameover判定
        // 撞墙
        if (this.head.x > canvas.width || this.head.x < 0 || this.head.y > canvas.height || this.head.y < 0){
            clearInterval(timer);
        }

        // 撞自己,循环从1开始,避开蛇头与蛇头比较的情况
        for (var i = 1; i < this.snakeArray.length; i++) {
            if (this.snakeArray[i].x == this.head.x && this.snakeArray[i].y == this.head.y){
                clearInterval(timer);
            }
        }
    }

    //画出初始的蛇
    var snake = new Snake()
    snake.draw();

    //画出初始的食物
    var food = new getRandomFood()

    //定时器
    var timer = setInterval(function () {
        context.clearRect(0,0,canvas.width,canvas.height);
        food.draw();
        snake.move();
        snake.draw();
    }, 100)

    //键盘事件,其中的if判定是为了让蛇不能直接掉头
    document.onkeydown = function (e) {
        var ev = e||window.event;
        switch(ev.keyCode){
            case 37:{
                if (snake.direction !== 39){
                    snake.direction = 37;
                }
                break;
            }
            case 38:{
                if (snake.direction !== 40){
                    snake.direction = 38;
                }
                break;
            }
            case 39:{
                if (snake.direction !== 37){
                    snake.direction = 39;
                }
                break;
            }
            case 40:{
                if (snake.direction !== 38){
                    snake.direction = 40;
                }
                break;
            }    
        }
        ev.preventDefault();
    }

    //随机函数,获得[min,max]范围的值
    function getNumberInRange (min,max) {
        var range = max-min; 
        var r = Math.random();
        return Math.round(r*range+min)
    }

    //构建食物对象
    function getRandomFood () {

        //判定食物是否出现在蛇身上,如果是重合,则重新生成一遍
        var isOnSnake = true;

        //设置食物出现的随机位置
        while(isOnSnake){
            //执行后先将判定条件设置为false,如果判定不重合,则不会再执行下列语句
            isOnSnake = false;
            var indexX = getNumberInRange(0,canvas.width/20-1);
            var indexY = getNumberInRange(0,canvas.height/20-1);
            var rect = new Rect(indexX*20, indexY*20, 20, 20, "green");
            for (var i = 0; i < snake.snakeArray.length; i++) {
                if(snake.snakeArray[i].x == rect.x && snake.snakeArray[i].y == rect.y){
                    //如果判定重合,将其设置为true,使随机数重给
                    isOnSnake = true;
                    break;
                }
            }
        }
        //返回rect,使得实例化对象food有draw的方法
        return rect;
    }

    //判定吃到食物,即蛇头坐标与食物坐标重合
    function isEat () {
        if (snake.head.x == food.x && snake.head.y == food.y){
            return true;
        } else {
            return false;
        }
    }

</script>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

突袭HTML5之Javascript API扩展5—其他扩展(应用缓存/服务端消息/桌面通知)

前面已经总结了主要的API扩展(应用缓存/服务端消息/桌面通知),下面的几个只有在特定的场合才能发挥它的潜质,无一例外,IE均不支持,桌面通知目前只有Chrome支持,感兴趣的朋友可以了解下,或许对你有所帮助
收藏 0 赞 0 分享

HTML5之HTML元素扩展(上)—新增加的元素及使用概述

HTML5中加入了全新的结构型元素,例如页眉header,页脚footer,导航nav,内容article,章节section等除了这种整个页面的结构型元素,html5也加入了块级别的语义元素,感兴趣的朋友可以了解下,或许对你有所帮助
收藏 0 赞 0 分享

HTML5之HTML元素扩展(下)—增强的Form表单元素值得关注

在HTML5增强的元素中,最值得关注的就是表单元素;在HTML5中,表单已经做了重大的修整,一些以前需要通过JavaScript编码实现的功能现在无需编码就可轻松实现,感兴趣的朋友可以详细了解下,或许对你有所帮助
收藏 0 赞 0 分享

HTML5之WebGL 3D概述(上)—WebGL原生开发开启网页3D渲染新时代

WebGL开启了网页3D渲染的新时代,它允许在canvas中直接渲染3D的内容,而不借助任何插件,看到此处是不是感觉特别惊讶啊,WebGL有一个很好的中文教程,就是下面使用参考中的第一个链接,所以这里不再班门弄斧,后面的内容只是简单的总结一下学习的内容,感兴趣的朋友可以了
收藏 0 赞 0 分享

HTML5之WebGL 3D概述(下)—借助类库开发及框架介绍

前面我们看到了使用原生的WebGL API开发是多么的累,只因如此大量的WebGL框架被开发出来,这些框架不同程度的封装了创建3D场景的各种要素你可以快速创建需要的3D场景,感兴趣的朋友可以了解下,或许本文对你有所帮助
收藏 0 赞 0 分享

HTML中fieldset标签概述及使用方法

之前HTML没有好好学,导致以前看到控件组样式感觉很新奇,fieldset> 标签将表单内容的一部分打包,生成一组相关表单的字段,接下来对HTML中fieldset标签的使用进行详细解读,感兴趣的朋友可以了解下,或许对你有所帮助
收藏 0 赞 0 分享

HTML5中微数据概述及在搜索引擎中的使用举例

HTML5微数据规范是标记内容的一种方式,用于描述特定的信息类型,例如评论、人物信息或活动。微数据使用 HTML 标记(常为 span>或 div)中的简单属性为项和属性指定简要的描述性名称
收藏 0 赞 0 分享

html5新增的属性和废除的属性简要概述

HTML5中,在新增加和废除很多元素的同时,也增加和废除了很多属性比如表单相关的属性/链接相关属性是新增的而HTML4中一些属性就被废除掉了,感兴趣的你可以了解下,或许对你学习html5有所帮助
收藏 0 赞 0 分享

html5的新增的标签和废除的标签简要概述

HTML5中在新增加和废除很多标签的同时,也增加和废除了很多标签比如新增的结构标签:section元素/video元素等等,感兴趣的朋友可以了解下,希望本文的知识点对你有所帮助
收藏 0 赞 0 分享

html5配合css3实现带提示文字的输入框(摆脱js)

webkit特有的一个css,可以控制里面的文字样式,配合css3的动画效果和伪类,我们就可以很容易做出一个带动画的输入框,在系统登录、搜索等位置很适合,感兴趣的你可以参考下本文或许可以帮助到你
收藏 0 赞 0 分享
查看更多