zoukankan      html  css  js  c++  java
  • 原生JavaScript实现的贪吃蛇

    github代码地址:https://github.com/McRayFE/snake

    涉及到的知识点:

    • 键盘事件
    • setInterval()定时器
    • javascript中数组的使用
    • 碰撞的检测
    • offsetLeft,offsetWidth,offsetTop,offsetHeight

    实现的思路

    • 让小蛇动起来
    • 让食物随机生成
    • 检测碰撞
    • 让身体跟随

    HTML主体代码

    <div class="container">
           <!--小蛇移动的操场-->
           <div id="playground">
               <!--小蛇-->
               <div id="snake"></div>
               <!--食物-->
               <div id="food"></div>
           </div>
           <!--记录得分-->
           <div id="menu">
              <div>得分<span id="score"></span></div>
           </div>
       </div>
    

    一个小蛇移动的操场playground,里面包含了小蛇snake和食物food,还有一个记录得分的menu

    CSS代码

    *{
        padding:0;
        margin:0;
    }
    .container{
        600px;
        height:500px;
        margin:0 auto;
    }
    #playground{
        450px;
        height:100%;
        background-color:pink;
        float:left;
        position:relative;
    }
    #menu{
        150px;
        height:100%;
        background-color:blue;
        float:left;
    }
    #snake{
        20px;
        height:20px;
        background-color:red;
        position:absolute;
        left:0;
        top:0;
    }
    #food{
        20px;
        height:20px;
        background-color:yellow;
        position:absolute;
    }
    .body{
        20px;
        height:20px;
        background-color:green;
        position:absolute;;
        top:0;
        left:0;
    }
    #score{
        font-size:30px;
        font-weight:bold;
        color:black;
    }
    #menu div{
        font-size:20px;
        font-weight:bold;
        margin-left:20px;
    }
    

    此时界面的效果如下:

    snake1.PNG

    获取元素和定义全局变量

        var snake = document.getElementById("snake");
        var food = document.getElementById("food");
        var playground = document.getElementById("playground");
        var score = document.getElementById('score');
        /*设置全局变量*/
        var timer;
        var srr = [];//存放蛇的位置的数组
        var num = 0;//数组的长度
        var snakeBody;//每次吃调一个食物,增加的身体
        var timer1 = setInterval(eat,10);//设置一个碰撞的时间器
    

    让小蛇动起来

    监听键盘事件,判断上下左右键的ASCII码值来执行不同方向的移动函数,其中每移动1px,就要将小蛇的位置存入到arr[]数组中,因为后面实现身体跟随的时候,是根据数组里面的位置来动态变化的。

    document.onkeydown = function(e){
            var evt = window.evnet || e;
            switch(evt.keyCode){
                case 37://左
                    clearInterval(timer);
                    timer = window.setInterval(runLeft,10);//向左移动的时间器
                  function runLeft(){
                    if(snake.offsetLeft > 0){
                        snake.style.left = snake.offsetLeft - 1 + 'px';
                        snake.style.top = snake.offsetTop + 'px';
                        srr.push([snake.offsetLeft,snake.offsetTop]);//每移动1px,就将位置存进数组中
                        num++;//相应的数组长度加1
                    }else{
                        clearInterval(timer);
                        console.log("failed!");
                    }
                   }
                    break;
                case 38://上
                    clearInterval(timer);
                    timer = window.setInterval(runTop,10);
                    function runTop(){
                        if(snake.offsetTop > 0){
                            snake.style.top = snake.offsetTop - 1 + 'px';
                            snake.style.left = snake.offsetLeft + 'px';
                            srr.push([snake.offsetLeft,snake.offsetTop]);
                            num++;
                        } else{
                            clearInterval(timer);
                            console.log("failed!");
                        }
                    }
                    break;
                case 39://右
                    clearInterval(timer);
                    timer = window.setInterval(runRight,10);
                    function runRight(){
                        if(snake.offsetLeft < 430){
                            snake.style.left = snake.offsetLeft + 1 + 'px';
                            snake.style.top = snake.offsetTop + 'px';
                            srr.push([snake.offsetLeft,snake.offsetTop]);
                            num++;
                        } else{
                            clearInterval(timer);
                            console.log("falied!");
                        }
                    }
                    break;
                case 40://下
                    clearInterval(timer);
                    timer = window.setInterval(runBottom,10);
                    function runBottom(){
                        if(snake.offsetTop < 480) {
                            snake.style.top = snake.offsetTop + 1 + 'px';
                            snake.style.left = snake.offsetLeft + 'px';
                            srr.push([snake.offsetLeft,snake.offsetTop]);
                            num++;
                        }else{
                            clearInterval(timer);
                            console.log("falied!");
                        }
                    }
                    break;
            }
        }
    

    让食物随机产生

    运用了Math类里面的random方法实现食物的随机产生,代码如下,配合碰撞检测使用

    function pos(){
        food.style.left = parseInt(Math.random()*430) + 'px';
        food.style.top = parseInt(Math.random()*480) + 'px';
    }
    

    碰撞检测

    小蛇和食物不碰撞有四种可能,图中黄色是食物,红色是小蛇:
    第一种情况:

    第二种情况:

    碰撞2.PNG

    第三种情况:

    碰撞3.PNG

    第三种情况

    碰撞4.PNG

    除了以上四种情况以外的都是碰撞的情况,所以代码如下

    /*检测碰撞函数*/
    function eat(){
        snakeCrashFood(snake,food);
        function snakeCrashFood(obj1,obj2){
            var obj1Left = obj1.offsetLeft;
            var obj1Width = obj1.offsetWidth + obj1.offsetLeft;
            var obj1Top = obj1.offsetTop;
            var obj1Height = obj1.offsetHeight + obj1.offsetTop;
            var obj2Left = obj2.offsetLeft;
            var obj2Width = obj2.offsetWidth + obj2.offsetLeft;
            var obj2Top = obj2.offsetTop;
            var obj2Height = obj2.offsetHeight + obj2.offsetTop;
            if(!((obj1Width<obj2Left)||(obj2Width<obj1Left)||(obj1Height<obj2Top)||(obj2Height<obj1Top))){
                snakeBody = document.createElement("div");
                snakeBody.setAttribute("class","body");
                playground.appendChild(snakeBody);//添加一节新的身体
                pos();//让食物重新随机出现
                setInterval(follow,10);//动态地改变新的身体的位置
            }
        }
    }
    

    让身体跟随

    在讲让小蛇动起来的那一节的时候,已经提到过了,小蛇每移动1px,都会将此时的位置存入到位置数组中,这个位置数组就是在这一节里面起作用的,能让身体动态地跟随,看下面的图片

    移动.PNG

    红色的头节点移动了40px,此时arr[]数组的长度就为40,那么第二节身体的位置刚好就是arr[20]的位置,第三节的位置就是arr[40]的位置,依次加等20。。。实现的代码如下

    /*身体跟随函数*/
    function follow(){
        /*获得增加的身体的数组*/
        var bodyNum = document.getElementsByClassName("body");
        score.innerHTML = bodyNum.length;
        var place = 0;
        /*数组每移动1px,新的身体的位置就是相对于前一个身体的第20个数组的位置,后面依次加等*/
        for(var i=0;i<bodyNum.length;i++){
            place += 20;
            bodyNum[i].style.left = srr[num-place][0] + 'px';
            bodyNum[i].style.top = srr[num-place][1] + 'px';
        }
    }
    
  • 相关阅读:
    洛谷P2894 [USACO08FEB]酒店Hotel
    codevs 3981 动态最大子段和
    舞蹈家怀特先生(线型)
    IOS8 通知中心(Notification Center)新特性
    WWDC2014 IOS8 APP Extensions
    IOS8 TouchID使用介绍
    IOS8 UIAlertController 弹框
    Unable to run Kiwi tests on iOS8 device
    registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later
    iOS开发---- 开发错误汇总及解决方法
  • 原文地址:https://www.cnblogs.com/mcray/p/6773163.html
Copyright © 2011-2022 走看看