使用前端原生 js,貪吃蛇小遊戲

來源:互聯網
上載者:User

標籤:mil   charset   time   ret   rip   背景色   遊戲   運動   設定   

好久好久,真的是好久好久沒來寫過了,因為最近有點小忙。不過即使是忙,也也還是寫了兩個小遊戲,其中一個就是這個,貪吃蛇啦。

算是一個小練手了,這個是在有點太簡單了,只是第一次寫這種小遊戲,還是零零星星花了三五天時間,下面就是這個小遊戲的gif小動畫,比較簡單,對比過網上其他用來寫出來練手的貪吃蛇作品,這個在顏值還是功能上,都還是不錯的,霍霍。

這裡講解一下功能:

  1. 空格控制開始和暫停。
  2. 方向鍵控制移動方向。
  3. Q 鍵加速,再按一次恢複常規速度(在加速狀態時,按下或者方向鍵,或者吃到了白色小食物,速度自動回復正常)。

這次我研究了 github,一個用來管理代碼版本的國外網站,不過使用它不需要FQ,它的一個功能,就是可以用來展示網站,比如我就把貪吃蛇放在裡 github 中,可以點擊後面的連結訪問,也就是可以直接玩耍:點擊這裡開啟貪吃蛇

想描述一下技術要點。。。發現有點小忘了,不過一個痛點還是記得的,當蛇的身子比較長後,容易和自己挨住,會連成一塊,看上去很不方便,所以我在中間添加了這條縫隙,如所示,為添加前和添加後的效果:

這條縫隙的添加還是比較麻煩的,我的思路是,給組成蛇身的每個 li 元素小塊,都設定個 1px 的border背景色邊框,接著每一個 li 的後面跟一個寬度為 2px,高度和 li 等高的 span 標籤,背景顏色和li相同,再通過css設定好位置,正好可以補上蛇身中兩個正常相連的 li 小塊之間,那個 2px 的縫隙,為什麼是 2px 呢?因為前一個 li 和後一個 li,各都有 1px 的 border。

原始碼也放在下面吧,免得以後啥時候我改了 github 配置,上面那個連結不能使用了。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>貪吃蛇</title>    <style>        * {            padding: 0;            margin: 0;        }        body {            background-color: #090e20;        }        .big {            width: 1000px;            height: 600px;            border: 1px dashed #fff;            margin: 30px auto 0;            position: relative;        }        p {            margin-bottom: 10px;        }        .right span {            position: absolute;            width: 20px;            height: 20px;            background-color: #fff;            border-radius: 30%;        }        ul li {            list-style: none;            position: absolute;            width: 20px;            height: 20px;            background-color: #b5cad5;            box-sizing: border-box;            border: 1px solid #090e20;        }        ul li b {            display:block;            z-index: 100;            width: 2px;            height: 18px;            background-color: #b5cad5;            position: absolute;            top: 0;            left: 8px;            transform-origin: 11px 9px;            transform: translate(-10px,0) rotate(0deg);        }        ul li:first-child b {            width: 4px;            transform: translate(-12px,0) rotate(0deg);        }        ul li:last-child b {            background-color: transparent;        }        ul li:nth-child(1) {            border-radius: 0 50% 50% 0;            /*transform:scale(2,2);*/        }        ul li:nth-child(1):before {            content: ‘‘;            display: block;            background-color: #090e20;            width: 2px;            height: 2px;            position: absolute;            bottom: 5px;            right: 10px;            z-index: 2;        }        ul li:nth-child(1):after {            content: ‘‘;            display: block;            background-color: #090e20;            width: 2px;            height: 2px;            position: absolute;            top: 5px;            right: 10px;        }        .explain {            float: left;            box-sizing: border-box;            border-right: 1px dashed #fff;            height: 100%;            width: 260px;            color: #fff;        }        .explain em {            color: #b3c6ff;            font-style: normal;        }        ol li {            margin-left: 25px;        }        .right {            width: 740px;            float: right;            height: 100%;            position: relative;            box-sizing: border-box;        }    </style></head><body><div class="big">    <div class="explain">        <p>點擊<em>空格</em>開始或暫停</p>        <p>可通過<em>WASD</em>或者<em>方向鍵</em>控制方向</p>        <p>可通過<em>斷行符號鍵</em>或者<em>Q</em>加速</p>        <p>當改變方向,或者吃到小球,速度自動回復正常</p>        <br>        <p>以下為每局吃掉的小球個數</p>        <ol></ol>    </div>    <div class="right">        <span></span>        <ul>        </ul>    </div></div></body><script>    window.onload = function () {        //擷取元素節點        var big = document.querySelector(".big");        var span = document.querySelector("span");        var ul = document.querySelector("ul");        var ol = document.querySelector("ol");        var ol_lis; //預留的ol中的li標籤        var lis;//預留的ul中的li標籤,即貪吃蛇的身子        var times;//速度,初始為150        var arrall;//二維數組,每一項為一個數組,其中儲存每個li的x軸y軸座標和方向        var timer;//蛇運動時的定時器        var timers;//數組,蛇吃到小球,小球白點順著身子流動的定時器,之所以是數組,是因為可能上一個小球白點還沒到尾部,蛇又吃了一個        var index;//數組,和times綁定的        var direction; //現在蛇運動的方向        var flag; //判斷是否按下了方向鍵        var num;//用來記憶最初始有幾個li,計數吃掉幾個小球時減去        var stars = false;//判斷是否遊戲中true或者false        var spanX;//儲存食物小球的座標        var spanY;        star();        //初始化函數        function star() {            times = 200;            arrall = [];            timers = [];            index = [];            ul.innerHTML = "<li></li><li></li><li></li><li></li>";            lis = document.querySelectorAll("ul li");            num = lis.length;            //給每一個li定位,且記錄到arrall中            for (var i = lis.length - 1; i >= 0; i--) {                var arr = [0, 20 * i, "right"];                arrall[arrall.length] = arr;                lis[i].style.top = 0;                lis[i].style.left = 20 * (lis.length - 1 - i) + "px";                var b = document.createElement(‘b‘);                lis[i].appendChild(b);            }            //給arrall多造一個子項目,用來為吃到小點後新增的身子賦值;            arrall[arrall.length] = [0, 20 * lis.length - 1, "right"];            spanPosition();//產生span小球事物            timer = null;            direction = ‘right‘;            flag = null;        }        //產生小白球函數        function spanPosition() {            var temp;            do {                temp = false;                spanX = Math.floor(Math.random() * 36) * 20;                spanY = Math.floor(Math.random() * 29) * 20;                //for迴圈來保證小白球不會出現在蛇身體的內部                for (var i = 0; i < lis.length; i++) {                    if (spanX == arrall[i][1] &&                        spanY == arrall[i][0]) {                        temp = true;                        break;                    }                }            } while (temp);            span.style.left = spanX + "px";            span.style.top = spanY + "px";            span.style.display = "block";        }        //按下鍵盤按鍵        document.onkeydown = function (e) {        //如果是紅的,則屏蔽所有按鍵            if (lis[0].style.backgroundColor === "red") return;            //如果是空格鍵            if (e.keyCode == 32) {                if (timer) {                    clearInterval(timer);                    timer = null;                    flag = true;                } else {                    timer = setInterval(move, times);                    flag = false;                    //如果遊戲沒有運行,也就是初次啟動,而不是暫停後的啟動                    if (!stars) {                    //如果是失敗了,蛇頭為紅色,此時也屏蔽空格                        var li = document.createElement(‘li‘);                        li.innerHTML = "吃掉小球數量為:" + (arrall.length - 1 - num) + "枚!";                        ol.appendChild(li);                        ol_lis = document.querySelectorAll("ol li");                        stars = true;                    }                }                return;            }            //如果遊戲沒有開始開,則其他按鍵失效            if (!stars) return;            //如果是斷行符號或者Q            if (e.keyCode == 13 || e.keyCode == 81) {                if (timer) {                    clearInterval(timer);                    if (times == "50") times = 200;                    else times = 50;                    timer = setInterval(move, times);                } else {                    if (times == "50") times = 200;                    else times = 50;                }                return;            }            if (flag) return;            if (e.keyCode == 38 || e.keyCode == 87) {                if (direction == "bottom" || direction == "top") {                    return;                }                flag = ‘top‘;            } else if (e.keyCode == 37 || e.keyCode == 65) {                if (direction == "right" || direction == "left") {                    return;                }                flag = ‘left‘;            } else if (e.keyCode == 39 || e.keyCode == 68) {                if (direction == "left" || direction == "right") {                    return;                }                flag = ‘right‘;            } else if (e.keyCode == 40 || e.keyCode == 83) {                if (direction == "top" || direction == "bottom") {                    return;                }                flag = ‘bottom‘;            } else {                returnValue = false;                return;            }            times = 200;            clearInterval(timer);            move();        }        //移動函數        function move() {            //如果安了方向鍵,那麼為direction賦flag的值            if (flag) {                direction = flag;            }            //用for迴圈依次移動每一個li            for (var i = arrall.length - 1; i >= 0; i--) {                if (i == arrall.length - 1) {                    var arrs = [];                    arrs[0] = arrall[i - 1][0];                    arrs[1] = arrall[i - 1][1];                    arrs[2] = arrall[i - 1][2];                    arrall[i] = arrs;                } else {                    //如果是第一個li,把它的方向資訊及時更新                    if (i == 0) {                        arrall[i][2] = direction;                    } else {                        //如果不是,把li移動的方向設定為前一個的                        arrall[i][2] = arrall[i - 1][2];                    }                    //根據方向來更新位置                    switch (arrall[i][2]) {                        case "top" :                            arrall[i][0] -= 20;                            lis[i].style.top = arrall[i][0] + "px";                            lis[i].querySelector(‘b‘).style.transform = "translate(-10px,0) rotate(270deg)";                            break;                        case "right" :                            arrall[i][1] += 20;                            lis[i].style.left = arrall[i][1] + "px";                            lis[i].querySelector(‘b‘).style.transform = "translate(-10px,0) rotate(0deg)";                            break;                        case "bottom" :                            arrall[i][0] += 20;                            lis[i].style.top = arrall[i][0] + "px";                            lis[i].querySelector(‘b‘).style.transform = "translate(-10px,0) rotate(90deg)";                            break;                        case "left" :                            arrall[i][1] -= 20;                            lis[i].style.left = arrall[i][1] + "px";                            lis[i].querySelector(‘b‘).style.transform = "translate(-10px,0) rotate(180deg)";                            break;                    }                }            }            lis[0].querySelector(‘b‘).style.transform= "translate(-12px,0) rotate(0deg)";            //再判斷是不是按下了方向鍵,用來轉動蛇頭            if (flag) {                if (flag == "bottom") {                    lis[0].style.transform = "rotate(90deg)";                } else if (flag == "right") {                    lis[0].style.transform = "rotate(0deg)";                } else if (flag == "left") {                    lis[0].style.transform = "rotate(180deg)";                } else if (flag == "top") {                    lis[0].style.transform = "rotate(270deg)";                }                flag = null;                timer = setInterval(move, times);            }            //判斷是否吃掉了小球            if (arrall[0][0] == spanY && arrall[0][1] == spanX) {                clearInterval(timer);                times = 200;                timer = setInterval(move, times);                //新產生一枚小球點                span.style.display = "none";                spanPosition();                //下面兩個是啟動產生小白點的函數定時器                index[index.length] = 1;                timers[timers.length] = setInterval(dingshi,20,timers.length);            }            //判斷有沒有碰到牆壁或自己            for (var i = 1; i < lis.length; i++) {                if (arrall[0][0] == arrall[i][0] &&                    arrall[0][1] == arrall[i][1] ||                    arrall[0][0] < 0 ||                    arrall[0][0] == 600 ||                    arrall[0][1] < 0 ||                    arrall[0][1] == 740) {                    clearInterval(timer);                    lis[0].style.zIndex = lis.length;                    lis[0].style.backgroundColor = "red";                    stars = false;                    var tempTimer = setTimeout(function(){                        lis[0].style.backgroundColor = "#b5cad5";                        star();                    },1000);                    break;                }            }        }        //吃掉小球,出現順著蛇身子移動的白點的函數        function dingshi(temp){            lis[index[temp]].style.backgroundColor = "#b5cad5";            if (index[temp] == lis.length-1) {                clearInterval(timers[temp]);                //新產生的li的數組,其位置和方向資訊等於之前的最後一個li                var arr = [arrall[arrall.length - 1][0], arrall[arrall.length - 1][1], arrall[arrall.length - 1][2]];                arrall[arrall.length] = arr;                //建立新的li元素,並且用另一個函數,給這個li賦值位置和方向資訊                var li = document.createElement("li");                var b = document.createElement(‘b‘);                li.appendChild(b);                ul.appendChild(li);                lis = document.querySelectorAll("ul li");                lis[lis.length - 1].style.top = arr[0] + "px";                lis[lis.length - 1].style.left = arr[1] + "px";                ol_lis[ol_lis.length - 1].innerHTML = "吃掉小球數量為:" + (arrall.length - 1 - num) + "枚!";                return ;            };            lis[index[temp]+1].style.backgroundColor = "#fff";            index[temp]++;        }    }</script></html>

  

使用前端原生 js,貪吃蛇小遊戲

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.