前端遊戲之原生js-猴子喫水果

偶然想到曾經在無智能手機時代,玩過的一款遊戲,遊戲名忘了,只記得內容,遊戲內容是一個猴子在樹木之間跳躍,喫水果,躲炸彈,防蟲子,其他的記不太清,大致是這樣的玩法,似乎是某款諾基亞上的遊戲。。。。。。-_-!!。。。。。。由於執念太強,所以試着用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的,不過算是滿足了下回憶吧。。。有空會繼續升級這個遊戲,畢竟還沒有把向上爬的金龜子加入,,,
那個有感興趣的大佬們,可以寫寫,寫個更好的,希望最終作品能夠分享給我,謝謝了。。。
注:上述代碼解釋有誤的,幫我指出,謝謝。當然如果上述代碼有不理解的也可以聯繫我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章