前端游戏之原生js-猴子吃水果

6 篇文章 0 订阅
6 篇文章 0 订阅

偶然想到曾经在无智能手机时代,玩过的一款游戏,游戏名忘了,只记得内容,游戏内容是一个猴子在树木之间跳跃,吃水果,躲炸弹,防虫子,其他的记不太清,大致是这样的玩法,似乎是某款诺基亚上的游戏。。。。。。-_-!!。。。。。。由于执念太强,所以试着用html和原生js写下,倒是写出了个半吊子,唔----算是有个小样子吧。。。先看下游戏展示图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来是html代码:


<div class="startGame">                                     <!-- 游戏开始大页面 -->
    <img src="img/start.png" alt="" id="startGame">            <!-- 加入游戏开始按钮,这里用图片代替 -->
</div>

<div class="wrapper" id="wrapper">               <!-- 游戏开始后进入的主页面的大页面 -->
    <div class="backgroundTree">                 <!-- 在大页面里装入背景—三棵树 -->
        <div class="tree1"></div>                         <!-- 这里的树用图片表示,在css中写入,下面的树相同 -->
        <div class="tree2"></div>
        <div class="tree3"></div>
    </div>
    <div class="move" id="move">              <!-- 在大页面中加入动态因子(猴子,水果,炸弹),由于是动态的,所以在js里生成显示,不再这里直接显示 -->
        <!-- <div class="monkey" id="monkey"></div> -->           <!--注: 这是在执行js后,会自动生成的三个节点 -->
        <!-- <div class="fruits" id="fruits"></div> -->
         <!--  <div class="boom" id="boom"></div> -->
    </div>
    <div class="scoreBox" id="scoreBox">           <!-- 显示分数的大页面 -->
        <div class="score">计分:<p id="score">0</p>            <!-- 动态计入分数,在js里写入变化的分数值 -->
        </div>
    </div>
</div>
<div class="gameOver" id="gameOver">            <!-- 当游戏失败后,显示的游戏结束大页面 -->
    <div class="over" id="over">         <!-- 在大页面中的游戏结束弹出框,这里用图片表示(在css里写入图片) -->
        <div class="close" id="close"></div>        <!-- 在游戏结束框里加入关闭按钮,这里也用图片表示(css加入图片) -->
        <div class="scoreOver"><p id="scoreOver"></p></div>      <!-- 在游戏结束框中加入最后的计分 -->
    </div>
</div>

接下来css代码:

*{                            /* 写代码的习惯,先将所有默认的margin和padding都清0 */
    margin: 0;
    padding: 0;

}

.startGame{              /* 设置游戏开始的大页面 */
    width: 100%;            /* 100%的宽度 */
    height: 609px;         /* 根据自己的电脑浏览器显示大小设置的高度 */
    position: absolute;       /* 设置绝对定位 */
    top: 0;
    left: 0;
    z-index: 1000;         /* 显示在其他页面的最前面 */
}

.startGame img{             /* 在大页面中显示的游戏开始按钮 */
    width: 300px;       /* 根据图片设置宽高 */
    height: 100px;
    position: absolute;       /* 设置绝对定位,从这里到下面的margin:auto的设置表示该内容基于父级定位到正中心位置 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

.wrapper{           /* 游戏开始后的主界面的大界面 */
    width: 100%;         /* 和上述一样是设置宽高和绝对定位 */
    height: 609px;
    position: absolute;
    top: 0;
    left: 0;
}

.backgroundTree{           /* 在大界面中显示树的页面 */
    width: 100%;            /* 这里的值和上述设置的一样,原因往上看,这里不解释了 */
    height: 609px;
    position: absolute;
    top: 0;
    left: 0;
    background-image: url('img/bg1.jpg');       /* 加入背景图片,记得要和你的树看起来和谐一点哦 */
    background-size: 100% 100%;         /* 100%平铺图片 */
}

.tree1{                        /* 在背景图片中加入树的图片 */
    width: 25%;          /* 设置树的宽高,宽占背景图片的25% */
    height: 609px;   
    background-image: url('img/tree.png');             /* 加入树的图片 */
    background-size: 100% 100%;                   /* 平铺 */
    position: absolute;                         /* 绝对定位 */
    top: 0;
    left: 5%;                                       /* 位置距离左边5% */
}

.tree2{              /* 加入第二个树的图片 */
    width: 25%;                /* 和上述一样 */
    height: 609px;
    background-image: url('img/tree.png');
    background-size: 100% 100%;
    position: absolute;
    top: 0;
    left: 37.5%;                        /* 位置距离左边37.5% */
}

.tree3{                  /* 加入第三个树的图片 */
    width: 25%;
    height: 609px;
    background-image: url('img/tree.png');
    background-size: 100% 100%;
    position: absolute;
    top: 0;
    left: 70%;               /* 位置距离左边70% */
}


.move{                    /* 设置动态因子的大页面 */
    width: 100%;          
    height: 520px;           /* 设置你希望的游戏活动区域大小 */
    position: absolute;
    top: 60px;                     /* 设置位置距离上边60px */
    left: 0;
   display: none;            /* 刚开始时为不显示,触发js(即点击游戏开始按钮后)后更改为显示 */
}

.monkey{          /* 设置猴子的大小和初始位置 */
    width: 100px;
    height: 100px;
    background-image: url('img/monkey.png');           /* 加入猴子图片 */
    background-size: 100% 100%;
    position: absolute;          /* 设置基于父级的绝对定位,距上80px,距左150px */
    top: 80px;
    left: 150px;
}

.fruits{                              /* 设置水果的大小,至于位置在js里规定 */
    width: 150px;
    height: 50px;
    background-image: url('img/fruits.png');           /* 水果图片 */
    background-size: 100% 100%;
 
}

.boom{           /* 设置炸弹的大小 ,和上述一样解释*/
    width: 150px;
    height: 50px;
    background-image: url('img/zd.png');
    background-size: 100% 100%;
    display: block;        /* 设置显示为block */
}

.scoreBox{                /* 在大页面上的分数显示盒子 */
    width: 100%;
    height: 30px;
    position: absolute;
    top: 0;
    left: 0;
   
}

.score{                /* 在分数盒子里显示分数的大小和位置 */
    width: 80px;
    height: 30px;
    line-height: 30px;                     /* 垂直居中显示 */
    text-align: center;
    color: #222;                             /* 字体为黑色 */
    font-size: 18px;                         /* 字体大小 */
    font-weight: bolder;           /* 字体加粗 */
    position: absolute;           /* 在盒子里居中显示 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    float: left;                 /* 向左浮动 */

}
.score p{              /* 动态分数值 */
    float: right;           /* 向右浮动,使数字和汉字在同一行 */
}

.gameOver{                    /* 游戏结束大页面 */
    width: 100%;
    height: 609px;
    z-index: 10000;         /* 显示在所有其他页面的最前面 */
    position: absolute;
    top: 0;
    left: 0;
    display: none;          /* 刚开始时不显示,直到js里的相关事件被触发 */
}

.over{                  /* 在游戏结束大页面中显示游戏结束图片框 */
    width: 320px;             /* 图片大小自己按需求写 */
    height: 180px;
    position: absolute;          /* 在大页面中居中显示 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    background-image: url('img/gameOver.png');         /* 加入游戏结束的图片 */
    background-size: 100% 100%;
  
}

.close{               /* 在游戏结束框里加入关闭按钮 */
    width: 30px;        /* 大小自己按需设置 */
    height: 30px;
    background-image: url('img/shanchu.png');       /* 加入关闭按钮的图片 */
    background-size: 100% 100%;
    position: absolute;              /* 设置图片位置为基于父级的绝对定位 */
    top: 18px;                            /* 距上边18px */
    right: 18px;                           /* 距右边18px */
    cursor: pointer;                    /* 当鼠标移到图片,原鼠标指示变成小手图片 */
}

.scoreOver{                   /* 设置游戏结束图片上所显示的最终分数 */
    width: 80px;                /* 分数显示的范围宽高 */
    height: 30px;
    position: absolute;            /* 依据图片设置分数显示位置 */
    top: 118px;
    left: 170px;
    font-size: 20px;                /* 分数大小 */
    font-weight: bolder;          /* 分数字体加粗 */
    color: #000;                    /* 分数字体颜色白色 */
}

接下是js代码:

var startGame = document.getElementById('startGame');        //获取在html中的id = ‘startGame’的节点
var move = document.getElementById('move');           //以下同上解释
var score = document.getElementById('score');
var over = document.getElementById('over');
var gameOver = document.getElementById('gameOver');
var close = document.getElementById('close');
var scoreOver = document.getElementById('scoreOver');
var scoreBox = document.getElementById('score');
var boom = document.getElementsByClassName('boom');

var k = true;                   //设置锁
var number = [150,210,593,653,1036,1096];                 
var key = 1;
var speed1 = 100;
var speed2 = 80;
var timerf;
var timerb;

begin();                //执行函数begin()
function begin(){                       //游戏开始的默认值设置
    this.monkey_top = 80;              //    设置this.monkey_top为(假)猴子位置的高度
    this.monkey_left = 150;          //设置猴子位置的左边距离
    this.score = 0;                   //设置初始的分数为0
    monkey = document.createElement("div");         //创建一个(真)猴子(div)
    monkey.setAttribute('id','monkey');               //给猴子一个id = 'monkey'
    monkey.classList.add('monkey');            //给猴子一个class = “monkey”,用在css设置里
    move.appendChild(monkey);            //把猴子插入move节点下,成为move节点下的子节点,注:这的move是上述从var move里获取的id=“move”的节点
    bindEvent();                //触发bindEvent()函数
}

function bindEvent(){                  //用来装所有按键鼠标事件
    startGame.onclick = function(){            //当点击游戏开始按钮时触发该事件(注:startGame也是从上述的var startGame里得到的id节点,以下类似的不再说明)
        startGame.style.display = 'none';          // id=‘startGame’的节点display为none时,表示不显示该节点内容以及其下的子节点
        move.style.display = 'block';           //表示move节点包括其子节点都显示
        food();              //触发food()函数
        bomb();             //触发bom()函数
    }
    document.onkeydown = function(e){            //键盘事件,用来控制猴子的移动事件
        var code = e.keyCode;     //用code获取你所按的按键的代表的值
        setDerict(code);                 //将code的值返给setDerict()函数,触发该函数
    }

    close.onclick = function(){               //游戏结束后出现在游戏结束框右上方的叉叉按钮的点击事件
        gameOver.style.display = 'none';             //游戏结束框消失
        k = true;                  //钥匙k为true
        reStart();                 //触发重新开始游戏的函数,即reStart()
    }
}

function reStart(){                //游戏重新开始函数
    this.monkey_top = 80;              //与上述的begin()一样,重新设置初始值
    this.monkey_left = 150;
    this.score = 0;
    scoreBox.innerHTML = this.score;         //将游戏主界面的分数清0
    monkey = document.createElement("div");          //创建一个新的猴子
    monkey.setAttribute('id','monkey');
    monkey.classList.add('monkey');
    move.appendChild(monkey);
    key = 1;                  //钥匙key初始值为1
    bindEvent();                //重新触发bindEvent等一系列函数
    food();
    bomb();
  
}


function setDerict(code){           //猴子移动方向的控制
    switch(code){              //获取到code的值
        case 37:          //表示按键的方向键左
        if(key == 2||key == 4||key == 6){              //当key为2,4,6时引发的事件,注:这里的key的用意是:由于一颗树木分左右,而两颗树间又有距离,所有的树左右距离一样,所有的树与树间隔也一样,但左右和间隔的距离不一样,所以这里将其猴子的跳跃分成树1左,树1右,树间,树2左,树2右,树间…,不难找到规律,猴子从左到右为奇数,从右到树间为偶数,因此需要一个key来计入数字
            monkey.style.left = this.monkey_left - 60 + 'px';         //当key为偶数时,猴子的右距离为原始值右距离减60(这个60是树的左右直径)
            this.monkey_left = parseInt(getComputedStyle(monkey).left);    //此时的原始值要同步改变为当前的猴子位置的右距
            monkey.style.backgroundImage = 'url("img/monkey.png")';      //加入猴子面朝左的图片
            key --;        //key减1,变奇数
        }else if(key == 3 || key == 5){          //key为奇数时执行,注这里没有1,是因为这个按键是向左的,而猴子刚开始为的位置就在最左边,所以key为1时不能操作向左的按键
            monkey.style.left = this.monkey_left - 383 + 'px';          //猴子右距-383,这里的383是两颗树之间的距离
            this.monkey_left = parseInt(getComputedStyle(monkey).left);       //同上
            monkey.style.backgroundImage = 'url("img/monkey2.png")';         //面朝右的猴子图片
            key --;          //key减1,变偶数
        }else{         //因为树只有三颗,所以可设置的范围也就在1-5之间,所以当key为其他数值时,不触发事件
            ;
        }
        break;
        case 38:            //上
            monkey.style.top = parseInt(getComputedStyle(monkey).top) - 10 + 'px';        //控制猴子向上运动时的移动距离,为当前距离-10
            this.monkey_top = parseInt(getComputedStyle(monkey).top);    //实时获得更改后的猴子上距离
        break;
        case 39:           //右
            if(key == 1||key == 3||key == 5){          //这里的解释和上述37的一样,不再不说明,注:这里有1是由于该按键向右,因此可以操作
                monkey.style.left = this.monkey_left + 60 + 'px';
                this.monkey_left = parseInt(getComputedStyle(monkey).left);
                monkey.style.backgroundImage = 'url("img/monkey2.png")';
                key ++;        //变偶数
            }else if(key == 2 || key == 4){          //与上述一样,不多解释了
                monkey.style.left = this.monkey_left + 383 + 'px';
                this.monkey_left = parseInt(getComputedStyle(monkey).left);
                monkey.style.backgroundImage = 'url("img/monkey.png")';
                key ++;
            }else{
                ;
            }
        break;
        case 40:            //下  
            monkey.style.top = parseInt(getComputedStyle(monkey).top) + 10 + 'px';      //同上含义
            this.monkey_top = parseInt(getComputedStyle(monkey).top);
        break;
        default:
        break;
    }
}

function food(){           //设置水果函数
        var f = Math.floor(Math.random()*6);          先用f来获取一个0-6的一个随机数
        var monkey_l1 = parseInt(getComputedStyle(monkey).left);    //为下述过程方便,因此将猴子的位置赋给新变量
        var monkey_t1 = parseInt(getComputedStyle(monkey).top);
        var fruits = document.createElement('div');       //做一个水果(div)
        fruits.style.position = 'absolute';            //水果设置绝对定位
        fruits.style.left = number[f] + 'px';           //水果的右距为数组number里的第随机f个数,number[]数组的具体数值在开头设置了
        fruits.style.top = 0 + 'px';           //水果的初始上距离为0
        move.appendChild(fruits);        //在move下加入水果节点,是水果节点成为move下的子节点
        fruits.setAttribute('id','fruits');       //为水果节点加入id = ‘fruits’
        fruits.classList.add('fruits');         //加入class = ‘fruits’

        timerf = setInterval(function(){              //设置每隔speed1分钟执行一次的事件
            var monkey_l1 = parseInt(getComputedStyle(monkey).left);      //这里同上述的猴子里的一样意思,不再多解释
            var monkey_t1 = parseInt(getComputedStyle(monkey).top);
            var f_l = parseInt(getComputedStyle(fruits).left);        //这里也是为方便,将水果的左距离赋给f_l
            var f_t = parseInt(getComputedStyle(fruits).top);     //同
            fruits.style.top = f_t + 10 + 'px';        //水果的上距离+10
            if(f_t > 450){               //根据游戏界面设置数值,这里的450是我界面上的底部距离
                fruits.remove();     //当水果到达450以后,水果消失(删除节点)
                food();             //上个水果消失,下个水果出现
            }else if((monkey_l1 == f_l)&&((monkey_t1 == f_t)||(monkey_t1 == f_t + 30)||(monkey_t1 == f_t - 50))){          //前面为图方便就用在这里,这里表示的是当猴子吃到水果时,执行的事件,而猴子要吃到水果的要求就是,猴子的位置要和水果的位置一样,就表示吃到了,因为我的猴子设置的是100的宽高,而水果是50,所以这里我把猴子分成了三段,以便猴子吃水果的时候能够正常点显示(什么是正常显示,,,嗯,,就是水果碰到猴子头或者猴子身体或者猴子尾巴时,都表示吃到水果,都能得分)
                    this.score += 1;          //吃到水果得分+1
                    scoreBox.innerHTML = this.score;      //更新给界面上的分数
                    fruits.remove();          //吃到水果后,水果自然要消失
                    food();               //吃完,就要生成下个水果的出现,以便游戏继续
                    bomb();           //为了增加游戏难度,所以当猴子吃到一个水果后,就要同步增加一个炸弹
 
            }else{           //其他情况不执行事件
                ;
            }
        },speed1);
    
}

function bomb(){               //设置炸弹
    var b = Math.floor(Math.random()*6);          //与上述水果一致,其目的是为了随机出现在树的顶端六个位置
    var zd = document.createElement('div');        //创建一个炸弹
    zd.style.position = 'absolute';             //设置绝对定位
    zd.style.left = number[b] + 'px';             //取到随机位置
    zd.style.top = 0 + 'px';                //与上述一致,不多解释
    move.appendChild(zd);
    zd.setAttribute('id','zd');
    zd.classList.add('boom');

    timerb = setInterval(function(){           //设置每隔speed2执行一次事件
        var monkey_l = parseInt(getComputedStyle(monkey).left);         //与上述水果一致不多解释
        var monkey_t = parseInt(getComputedStyle(monkey).top);         
        var b_t =parseInt(getComputedStyle(zd).top);
        var b_l =parseInt(getComputedStyle(zd).left);
        zd.style.display = 'block';          //设置display = ‘block’
        zd.style.top = b_t + 10 + 'px';       //设置上距离+10
        if(b_t > 450){          /同上述解释
            if(k == true){            //这里设置的k,在下面解释
                zd.remove();      //炸弹消失
                bomb();          //重新生成炸弹
            }else{            //在这里解释下k的作用,因为游戏的难度是靠不断增加的炸弹为障碍,所以就出现了个问题,由于这里的zd.move()只能删除当前的炸弹(1个),不能删除所有的炸弹,因此对于重新开始游戏就麻烦了,炸弹会重失败时的个数开始显示,也就是游戏不能再从简单的开始玩,所以这里为设置所有炸弹都消失,而添加了这步操作
                for(var l = 0;l<document.getElementsByClassName('boom').length;l++){          //for循环的是当前html里显示的所有class为boom的节点,该节点表示的就是炸弹
                    var long = document.getElementsByClassName('boom')[l];     //获取每个boom节点
                    long.remove();          //循环删除每个boom节点
                }
            }
            
        }else if((monkey_l == b_l) && ((monkey_t == b_t) || (monkey_t == b_t - 50) ||( monkey_t == b_l + 30))){               //这里的含义同上述的水果,只是将水果替换为炸弹,也就是猴子吃到炸弹时引发的事件
            scoreOver.innerHTML = this.score;       //游戏结束最终得分
            gameOver.style.display = 'block';           //显示游戏结束界面
            k = false;             //这里控制所有正在掉落的炸弹,使它不会再触发上述的事件,而转触发删除节点事件
            fruits.remove();         //游戏结束所以水果也需要消失
            monkey.remove();        //猴子消失
            zd.remove();           //这个碰到的炸弹也消失
          
        }else{;}
        if((monkey_l == b_l) && ((monkey_t == b_t) || (monkey_t == b_t - 50))){       //不用怀疑,这里也和上面的一致,是猴子碰到炸弹触发事件,而作用也是为了双重保险删除所有炸弹节点,,,,,不知道这步是不是多余了。。。。等会试试
            for(var l = 0;l<document.getElementsByClassName('boom').length;l++){
                var long = document.getElementsByClassName('boom')[l];
                long.remove();
            }
        }
    },speed2);
}

好了,现在所有的代码都写完了,这游戏有个小缺点,就是当游戏失败后,你需要等界面上的所有炸弹都掉落完毕,再重新开始,才能从简单的开始(即刚开始只掉落一个炸弹)。。。。
总算是完成了记忆中的那个游戏,有点小激动,咳咳。。。虽然是挺low的,不过算是满足了下回忆吧。。。有空会继续升级这个游戏,毕竟还没有把向上爬的金龟子加入,,,
那个有感兴趣的大佬们,可以写写,写个更好的,希望最终作品能够分享给我,谢谢了。。。
注:上述代码解释有误的,帮我指出,谢谢。当然如果上述代码有不理解的也可以联系我

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值