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的Border-radius轻松制作圆角
Dec 24 HTML / CSS
CSS3网格的三个新特性详解
Apr 04 HTML / CSS
基于HTML5 Canvas 实现弹出框效果
Jun 05 HTML / CSS
教你如何一步一步用Canvas写一个贪吃蛇
Oct 22 HTML / CSS
HTML5之多线程(Web Worker)
Jan 02 HTML / CSS
HTML 5 标签、属性、事件及浏览器兼容性速查表 附打包下载
Oct 20 HTML / CSS
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
Feb 28 HTML / CSS
HTML5各种头部meta标签的功能(推荐)
Mar 13 HTML / CSS
使用Html5多媒体实现微信语音功能
Jul 26 HTML / CSS
从QQtabBar看css命名规范BEM的详细介绍
Aug 07 HTML / CSS
MIME类型中application/xml与text/xml的区别介绍
Jan 18 HTML / CSS
使用CSS定位HTML元素的实现方法
Jul 07 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
关于js与php互相传值的介绍
2013/06/25 PHP
Ajax和PHP正则表达式验证表单及验证码
2016/09/24 PHP
Laravel框架控制器的middleware中间件用法分析
2019/09/30 PHP
Laravel5.5 数据库迁移:创建表与修改表示例
2019/10/23 PHP
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
js写的评论分页(还不错)
2013/12/23 Javascript
JavaScript中setUTCMilliseconds()方法的使用详解
2015/06/12 Javascript
js实现浮动在网页右侧的简洁QQ在线客服代码
2015/09/04 Javascript
10个很棒的jQuery代码片段
2015/09/24 Javascript
Bootstrap开发实战之响应式轮播图
2016/06/02 Javascript
Angularjs 创建可复用组件实例代码
2016/10/09 Javascript
jQuery基于事件控制实现点击显示内容下拉效果
2017/03/07 Javascript
jQuery轻松实现无缝轮播效果
2017/03/22 jQuery
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
2017/04/25 Javascript
jquery仿京东商品放大浏览页面
2017/06/06 jQuery
Mongoose实现虚拟字段查询的方法详解
2017/08/15 Javascript
解决Vue中 父子传值 数据丢失问题
2019/08/27 Javascript
Python简单连接MongoDB数据库的方法
2016/03/15 Python
python用户管理系统的实例讲解
2017/12/23 Python
python基于ID3思想的决策树
2018/01/03 Python
python实现dijkstra最短路由算法
2019/01/17 Python
浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器
2019/03/11 Python
Python下简易的单例模式详解
2019/04/08 Python
python实现月食效果实例代码
2019/06/18 Python
Ranorex通过Python将报告发送到邮箱的方法
2020/01/12 Python
pytorch dataloader 取batch_size时候出现bug的解决方式
2020/02/20 Python
Python进程间通信multiprocess代码实例
2020/03/18 Python
UNIX文件类型
2013/08/29 面试题
公司请假条范文
2014/04/11 职场文书
高中教师考核方案
2014/05/18 职场文书
月度优秀员工获奖感言
2014/08/16 职场文书
应聘教师自荐信
2015/03/26 职场文书
2015年库房管理工作总结
2015/10/14 职场文书
2019垃圾分类宣传口号汇总
2019/08/16 职场文书
如何vue使用el-table遍历循环表头和表体数据
2022/04/26 Vue.js
一次SQL查询优化原理分析(900W+数据从17s到300ms)
2022/06/10 SQL Server