H5 canvas实现贪吃蛇小游戏


Posted in HTML / CSS onJuly 28, 2017

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

实现效果如下

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>

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

HTML / CSS 相关文章推荐
CSS3 三维变形实现立体方块特效源码
Dec 15 HTML / CSS
详解CSS3开启硬件加速的使用和坑
Aug 21 HTML / CSS
button在IE6/7下的黑边去除方案
Dec 24 HTML / CSS
关于css中margin的值和垂直外边距重叠问题
Oct 27 HTML / CSS
HTML5手机端弹出遮罩菜单特效代码
Jan 27 HTML / CSS
HTML5 canvas 瀑布流文字效果的示例代码
Jan 31 HTML / CSS
详解如何解决canvas图片getImageData,toDataURL跨域问题
Sep 17 HTML / CSS
一文彻底解决HTML5页面中长按保存图片功能
Jun 10 HTML / CSS
解决HTML5中滚动到底部的事件问题
Aug 22 HTML / CSS
网站性能延迟加载图像的五种技巧(小结)
Aug 13 HTML / CSS
Web前端:CSS最强总结 附详细代码
Mar 31 HTML / CSS
div与span之间的区别与使用介绍
Dec 06 HTML / CSS
LocalStorage记住用户和密码功能
Jul 24 #HTML / CSS
基于HTML5实现类似微信手机摇一摇功能(计算摇动次数)
Jul 24 #HTML / CSS
H5调用相机拍照并压缩图片的实例代码
Jul 20 #HTML / CSS
h5实现获取用户地理定位的实例代码
Jul 17 #HTML / CSS
HTML5 表单验证失败的提示语问题
Jul 13 #HTML / CSS
HTML5地理定位_动力节点Java学院整理
Jul 12 #HTML / CSS
HTML5中input[type='date']自定义样式与日历校验功能的实现代码
Jul 11 #HTML / CSS
You might like
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
Thinkphp5框架实现获取数据库数据到视图的方法
2019/08/14 PHP
javascript知识点收藏
2007/02/22 Javascript
表头固定(利用jquery实现原理介绍)
2012/11/08 Javascript
js操作label给label赋值及取label的值示例
2013/11/07 Javascript
多个jquery.datatable共存,checkbox全选异常的快速解决方法
2013/12/10 Javascript
js获取url中&quot;?&quot;后面的字串方法
2014/05/15 Javascript
jQuery实现自定义事件的方法
2015/04/17 Javascript
jquery实现点击展开列表同时隐藏其他列表
2015/08/10 Javascript
js验证真实姓名与身份证号是否匹配
2015/10/13 Javascript
js判断空对象的实例(超简单)
2016/07/26 Javascript
js获取当前时间(昨天、今天、明天)
2016/11/23 Javascript
ionic中列表项增加和删除的实现方法
2017/01/22 Javascript
微信小程序实现image组件图片自适应宽度比例显示的方法
2018/01/16 Javascript
关于jquery layui弹出层的使用方法
2018/04/21 jQuery
快速解决brew安装特定版本flow的问题
2018/05/17 Javascript
Vue 中axios配置实例详解
2018/07/27 Javascript
详解vue 兼容IE报错解决方案
2018/12/29 Javascript
vue将后台数据时间戳转换成日期格式
2019/07/31 Javascript
python对离散变量的one-hot编码方法
2018/07/11 Python
Python 数据库操作 SQLAlchemy的示例代码
2019/02/18 Python
Django网络框架之创建虚拟开发环境操作示例
2019/06/06 Python
wxpython自定义下拉列表框过程图解
2020/02/14 Python
jupyter note 实现将数据保存为word
2020/04/14 Python
Python优秀开源项目Rich源码解析的流程分析
2020/07/06 Python
Python猫眼电影最近上映的电影票房信息
2020/09/18 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
JINS眼镜官方网站:日本最大的眼镜邮购
2016/10/14 全球购物
海信商城:海信电视、科龙空调、容声冰箱官方专卖
2017/02/07 全球购物
学生宿舍管理制度
2014/01/30 职场文书
学习十八届三中全会精神实施方案
2014/02/17 职场文书
小学优秀教育工作者事迹材料
2014/05/09 职场文书
生活小常识广播稿
2015/08/19 职场文书
《槐乡的孩子》教学反思
2016/02/20 职场文书
Django+Celery实现定时任务的示例
2021/06/23 Python
MySQL深分页问题解决思路
2022/12/24 MySQL