jQuery 射擊遊戲/復古雷電 遊戲 簡易教學

Posted by

教學用jQuery撰寫簡單的射擊遊戲/復古雷電遊戲,因為是簡易版,供新手學習因此遊戲場景元素很多都會簡化不做,重點放在最主要的碰撞部份。

例如子彈碰到敵人、玩家飛機碰到敵人怎麼偵測的,以及如何使用jQuery撰寫。只要碰撞部份能學會,其他的較花俏的東西如”生命、金幣”哪些都好搞定,待未來教學進階版時撰寫,此次重點放在”碰撞偵測”部份。

在jquery部份都會有中文註解,供方便理解學習。

jquery-shooting-game-raiden-easy

作者遊戲範例:jQuery雷電

步驟一:

先部置好遊戲場景,例如遊戲場景要多大,背景要什麼顏色,這些都可以在CSS設定,但我們先將html寫進去。


<div class="gameBase"></div> <!--遊戲場景-->
<div class="gamePad"> <!--螢幕按鈕-->
<div class="up">上</div>
<div class="down">下</div>
<div class="left">左</div>
<div class="right">右</div>
</div>

<div class="message" style="margin: 0 auto; font-size: 50px;"></div>

———-

步驟二:
為遊戲場景添加樣式,這邊用到css部份,可以自由修改成自己喜歡的。

* {
    box-sizing: border-box;
}
.gameBase {
    margin: 0 auto;
    position: relative;
    width: 100%;
    max-width: 500px;
    height: 400px;
    background: #ddd;
    overflow: hidden;
}

.gamePad {
    margin: 0 auto;
    position: relative;
    width: 100%;
    max-width: 500px;
    height: auto;
    background: #ddd;
    overflow: hidden;
    text-align: center;
}

.gamePad>div {
    display: inline-block;
    width: 24%;
    font: bold 30px/2em "微軟正黑體";
    text-align: center;
    color: #fff;
}

.gamePad>div:nth-child(1) {
    background: #f8d42d;
}

.gamePad>div:nth-child(2) {
    background: #f82d58;
}

.gamePad>div:nth-child(3) {
    background: #2d74f8;
}

.gamePad>div:nth-child(4) {
    background: #2df8ae;
}

———-

步驟三:
添加玩家飛機、敵人飛機、子彈樣式,為了讓各位可以方便直接使用此程式碼,因此都使用svg繪圖,不使用圖片,可以直接複製貼上使用。但是未來各位是可以自由替換成圖片的。所有的素材都統一放在class為material的div內

<div class="material" style="opacity: 0;">

        <div class="aircraft" style="width: 50px;"> <!--玩家飛機樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 322 349" style="enable-background:new 0 0 322 349;" xml:space="preserve">
                <g>
                    <path style="fill:#2E3EB7;" d="M188,137.607v-26.916c0-3.21,0.017-15.289-7.462-23.572V36.5C180.538,30.725,168.996,0,161,0
        s-19.538,30.725-19.538,36.5v50.618c-7.479,8.283-7.462,20.363-7.462,23.572v26.916c0,0-134,103.168-134,108.393v15
        c0,6.6,5.4,12,12,12l122-30v51.57c0,0-56,43.775-56,45.503v4.96c0,2.182,2.535,3.968,5.634,3.968l65.732-13
        c0.999,0,1.937-0.188,2.753-0.512c2.785,0.33,5.773,0.512,8.881,0.512s6.096-0.182,8.881-0.512
        c0.816,0.325,1.754,0.512,2.753,0.512l65.732,13c3.099,0,5.634-1.786,5.634-3.968v-4.96c0-1.728-56-45.503-56-45.503V243l122,30
        c6.6,0,12-5.4,12-12v-15C322,240.775,188,137.607,188,137.607z" />
                </g>
            </svg>
        </div>
        <div class="enemy" style="width: 50px;"> <!--敵人飛機樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 322 349" style="enable-background:new 0 0 322 349;" xml:space="preserve">
                <g>
                    <path style="fill:#B53030;" d="M188,211.393v26.916c0,3.21,0.017,15.289-7.462,23.572V312.5c0,5.775-11.542,36.5-19.538,36.5
        s-19.538-30.725-19.538-36.5v-50.618c-7.479-8.283-7.462-20.363-7.462-23.572v-26.916c0,0-134-103.168-134-108.393V88
        c0-6.6,5.4-12,12-12l122,30V54.43c0,0-56-43.775-56-45.503v-4.96C78,1.786,80.535,0,83.634,0l65.732,13
        c0.999,0,1.937,0.188,2.753,0.512C154.904,13.182,157.891,13,161,13s6.096,0.182,8.881,0.512c0.816-0.325,1.754-0.512,2.753-0.512
        l65.732-13C241.465,0,244,1.786,244,3.968v4.96c0,1.728-56,45.503-56,45.503V106l122-30c6.6,0,12,5.4,12,12v15
        C322,108.225,188,211.393,188,211.393z" />
                </g>
            </svg>
        </div>
        <div class="bullet" style="width: 10px;"> <!--子彈樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 7 31" style="enable-background:new 0 0 7 31;" xml:space="preserve">
                <path style="fill:#FFCC3E;" d="M3.833,31L0,3.5C0,1.567,1.567,0,3.5,0h0C5.433,0,7,1.567,7,3.5L3.833,31z" />
                <circle style="fill:#FFFFFF;" cx="3.5" cy="3.5" r="2.5" />
            </svg>
        </div>


    </div>

———-

步驟四:
用javascript將一些遊戲元件先定義好,這是芋圓寫程式一貫的方式,只要是遊戲元素都先定義在最上頭,未來要維護方便好找。都有中文註解,方便閱讀。

var gameStage = $(".gameBase"); /*將遊戲場景放入變數,供未來方便使用*/
        var material = { /*用一個陣列,放入所有的遊戲素材,未來只要有此陣列開頭的就表示是素材,方便辨識*/
            aircraft: $(".aircraft").prop("outerHTML"), /*存入玩家飛機樣式,供未來方便使用*/
            aircraftHeight: $(".aircraft").height(), /*存入玩家飛機樣式高,供未來方便使用*/
            enemy: $(".enemy").prop("outerHTML"), /*存入敵人飛機樣式,供未來方便使用*/
            enemytHeight: $(".aircraft").height(), /*存入敵人飛機樣式高,供未來方便使用*/
            bullet: $(".bullet").prop("outerHTML") /*存入子彈樣式,供未來方便使用*/
        };

———-

步驟五:
將html寫好的玩家飛機樣式存入變數,並定義相關css後放入遊戲場景,內有中文註解

 var aircraft = $("<div>"); /*定義變數aircraft是一個div*/
        aircraft.append(material.aircraft) /*aircraft的div放入玩家飛機樣式*/
        aircraft.addClass("impactArc"); /*此div增加impactArc的class,供之後碰撞偵測使用*/
        aircraft.css({ /*增加此div要放入遊戲場景的位置*/
            "position": "absolute",
            "left": gameStage.width() / 2 - 25,
            "top": gameStage.height() - material.aircraftHeight
        });
        $(".gameBase").append(aircraft); /*場景放入玩家aircraft*/

———-

步驟六:
將html寫好的敵人飛機樣式存入變數,並定義相關css後,因為要重複使用所以寫成函式,內有中文註解。

function inputEnemy() { /*放入敵人的函式,因為要重複放入敵人,因此寫成函式*/
            var enemy = $("<div>"); /*定義變數enemy 是一個div*/
            enemy.append(material.enemy) /*enemy的div放入敵人飛機樣式*/
            enemy.addClass("impact"); /*此div增加impact的class,供之後碰撞偵測使用*/
            enemy.css({ /*增加此div要放入遊戲場景的位置*/
                "position": "absolute",
                "left": Math.floor(Math.random() * gameStage.width()), /*敵人飛機左右位置由場景大小亂數產生*/
                "top": -material.enemytHeight /*高度放置在場景高度以上*/
            })
            $(".gameBase").append(enemy) /*場景放入敵人*/
            enemy.stop().animate({ top: gameStage.height() + material.enemytHeight }, 3000, function() { enemy.remove(); }); /*敵人移動方式,會往場景底端位置移動,移出場景後刪除自己釋放效能*/
        }

        var startInputEnemy = setInterval(inputEnemy, 1000);/*每一秒重新放入敵人一次*/

———-

步驟七:
將html寫好的子彈樣式存入變數,並定義相關css後,因為要重複使用所以寫成函式,內有中文註解。

function fireBullet() { /*發射子彈的函式,因為要重複發射子彈,因此寫成函式*/
            var bullet = $("<div>"); /*定義子彈是一個div*/
            bullet.append(material.bullet) /*bullet的div放入子彈樣式*/
            bullet.addClass("impactArc");  /*此div增加impactArc的class,供之後碰撞偵測使用*/            
            bullet.css({ /*增加此div要放入遊戲場景的位置*/
                "position": "absolute",
                "left": aircraft.position().left + (aircraft.width() / 2) - 6, 
                /*因為子彈要有飛機發射出來的感覺,因此要抓取玩家飛機位置做定位*/
                "top": aircraft.position().top - material.aircraftHeight
                /*因為子彈要有飛機發射出來的感覺,因此要抓取玩家飛機位置做定位*/
            })
            $(".gameBase").append(bullet); /*遊戲場景放入子彈*/
            bullet.stop().animate({ top: 0 }, 3000, function() { bullet.remove(); });
            /*子彈移動方式,會往場景上方位置移動,移出場景後刪除自己釋放效能*/
        }

———-

步驟八:
這邊步驟八會是會難也是最重點的,碰撞偵測,只會懂得碰撞偵測原理,要寫什麼遊戲都很簡單了,作者芋圓也用此程式碼寫過RPG遊戲,步驟八要詳細閱讀呀!內有中文註解。
重點提示:碰撞偵測,就是取出兩個要偵測是否有互相重疊的元素之上、下、左、右位置,看是否有互相重疊到,只要有重疊,就是碰到囉,因此程式內會不斷的取出移動中的敵人與子彈各個位置並做大小於運算。

 var playerDir = new Array; /*定義一個陣列存放玩家飛機位置*/
        var boxDir = new Array; /*定義一個陣列存放敵人位置*/

        function impactTest() { /*碰撞偵測函式*/

            $.each($(".impact"), function() { /*每一個敵機div都執行以下*/
                boxDir[0] = $(this).position().top; /*敵機高存入boxDir變數0*/
                boxDir[1] = $(this).position().left; /*敵機左存入boxDir變數1*/
                boxDir[2] = $(this).position().top + $(this).height(); /*敵機下存入boxDir變數2*/
                boxDir[3] = $(this).position().left + $(this).width(); /*敵機右存入boxDir變數3*/

                for (i = 0; i < $(".impactArc").length; i++) { /*玩家飛機跟子彈,執行以下*/
                    playerDir[0] = $(".impactArc").eq(i).position().top; /*敵機高存入playerDir變數0*/
                    playerDir[1] = $(".impactArc").eq(i).position().left; /*敵機高存入playerDir變數0*/
                    playerDir[2] = $(".impactArc").eq(i).position().top + $(".impactArc").height(); 
                    /*敵機高存入playerDir變數2*/
                    playerDir[3] = $(".impactArc").eq(i).position().left + $(".impactArc").width(); 
                    /*敵機高存入playerDir變數3*/

                    if (playerDir[3] > boxDir[1] && playerDir[1] < boxDir[1] || playerDir[1] > boxDir[1] && playerDir[3] < boxDir[3] || playerDir[1] < boxDir[3] && playerDir[3] > boxDir[3]) { 
                    /*偵測敵人是否有跟玩家做子彈左右重疊*/

                        if (playerDir[0] < boxDir[2] && playerDir[2] > boxDir[2] || playerDir[0] < boxDir[0] && playerDir[2] > boxDir[0] || playerDir[0] < boxDir[2] && playerDir[2] > boxDir[0]) {
                         /*偵測敵人是否有跟玩家做子彈上下重疊*/      
                         /*有的話執行以下*/       


                            if ($(".impactArc").eq(i).children("div").hasClass("bullet")) {
                                $(this).remove();/*如果是子彈重疊,表是敵機被打中,移除敵機自己*/
                                $(".message").text("擊中"); /*在訊息欄顯示擊中*/
                            } else if ($(".impactArc").eq(i).children("div").hasClass("aircraft")) {
                                /*如果是跟玩家重疊,表示玩家被撞到*/
                                $(".message").text("相撞");/*在訊息欄顯示相撞*/
                            };
                        }
                    }
                }

            }); //$.each
        }

———-

步驟九:
撰寫飛機移動函式,藉由修改玩家飛機css做出操作玩家飛機效果。由switch去判斷呼覺此函式傳來的dir是什麼做執行,內有中文註解。

var aircraftStep = 5; /*定義玩家一次能飛多遠px*/


        function moveDir(dir) { /*玩家移動函式*/
            switch (dir) {  /*由dir判斷選擇執行哪段動作*/
                case "left": /*如果dir是left則往左*/
                    if (aircraft.position().left - aircraftStep > 0) {
                        /*如果飛機左邊像素減掉一次移動距離小於0,則可往左*/
                        aircraft.css({
                            "left": aircraft.position().left - aircraftStep
                        });
                    };
                    break;
                case "right":/*如果dir是right則往右*/
                    if (aircraft.position().left + aircraft.width() + aircraftStep < gameStage.width()) {
                        /*如果飛機右邊像素加上一次移動在加上飛機寬,沒有超出遊戲畫面,則可往右*/
                        aircraft.css({
                            "left": aircraft.position().left + aircraftStep
                        });
                    };
                    break;
                case "up":/*如果dir是up則往上*/
                    if (aircraft.position().top - aircraftStep > 0) {
                        /*如果飛機減掉一次移動距離,還未超出遊戲場景上方則可移動*/
                        aircraft.css({
                            "top": aircraft.position().top - aircraftStep
                        });
                    };
                    break;
                case "down":/*如果dir是down則往下*/
                    if (aircraft.position().top + aircraft.height() + aircraftStep < gameStage.height()) {
                        /*如果飛機加上一次移動距離再加上飛機高,還未超出遊戲場景下方則可移動*/
                        aircraft.css({
                            "top": aircraft.position().top + aircraftStep
                        });
                    };
                    break;
                default:

            }
        }

———-

步驟十:
撰寫操作方式,只要玩家按了鍵盤上上下左右鍵,或者網頁上的上下左右,就呼叫操做飛機移動的函式。

function keyDownHandler(e) {
            switch (e.keyCode) { /*依據玩家按哪個鍵,執行相對應函式帶入*/
                case 37:
                     moveDir("left");
                    break;
                case 39:
                     moveDir("right");
                    break;
                case 38:
                     moveDir("up");
                    break;
                case 40:
                     moveDir("down");
                    break;
                default:

            };           
        };
        document.addEventListener("keydown", keyDownHandler, false);/*如果玩家有按鍵盤則執行keyDownHandler*/


        
        $(".gamePad > div").click(function (){            
            switch ($(this).attr("class")) { /*依據玩家按哪個按鈕,執行相對應函式帶入*/
                case "left":
                     moveDir("left");
                    break;
                case "right":
                     moveDir("right");
                    break;
                case "up":
                     moveDir("up");
                    break;
                case "down":
                     moveDir("down");
                    break;
                default:

            }
            
        })

———-

步驟十一:
最後只要重複執行子彈射擊跟碰撞偵測函式,此遊戲就完成囉。

var impactTestTime = setInterval(function() { /*每500毫秒發射子彈一次,並且運算碰撞程式*/
            impactTest();
            fireBullet();
        }, 500);

———-

最後附上所有的語法,只要全部複製貼到空白html,就可以成功執行嚕,有RWD功能喔。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-tw" lang="zh-tw">

<head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <title>玩轉芋圓旅遊手札-程式教學</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<style type="text/css">
* {
    box-sizing: border-box;
}
.gameBase {
    margin: 0 auto;
    position: relative;
    width: 100%;
    max-width: 500px;
    height: 400px;
    background: #ddd;
    overflow: hidden;
}

.gamePad {
    margin: 0 auto;
    position: relative;
    width: 100%;
    max-width: 500px;
    height: auto;
    background: #ddd;
    overflow: hidden;
    text-align: center;
}

.gamePad>div {
    display: inline-block;
    width: 24%;
    font: bold 30px/2em "微軟正黑體";
    text-align: center;
    color: #fff;
}

.gamePad>div:nth-child(1) {
    background: #f8d42d;
}

.gamePad>div:nth-child(2) {
    background: #f82d58;
}

.gamePad>div:nth-child(3) {
    background: #2d74f8;
}

.gamePad>div:nth-child(4) {
    background: #2df8ae;
}
</style>

<body>
    <div class="gameBase"></div> <!--遊戲場景-->
    <div class="gamePad"> <!--螢幕按鈕-->
        <div class="up">上</div>
        <div class="down">下</div>
        <div class="left">左</div>
        <div class="right">右</div>
    </div>

    <div class="message" style="margin: 0 auto; font-size: 50px;"></div>

    <div class="material" style="opacity: 0;">

        <div class="aircraft" style="width: 50px;"> <!--玩家飛機樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 322 349" style="enable-background:new 0 0 322 349;" xml:space="preserve">
                <g>
                    <path style="fill:#2E3EB7;" d="M188,137.607v-26.916c0-3.21,0.017-15.289-7.462-23.572V36.5C180.538,30.725,168.996,0,161,0
        s-19.538,30.725-19.538,36.5v50.618c-7.479,8.283-7.462,20.363-7.462,23.572v26.916c0,0-134,103.168-134,108.393v15
        c0,6.6,5.4,12,12,12l122-30v51.57c0,0-56,43.775-56,45.503v4.96c0,2.182,2.535,3.968,5.634,3.968l65.732-13
        c0.999,0,1.937-0.188,2.753-0.512c2.785,0.33,5.773,0.512,8.881,0.512s6.096-0.182,8.881-0.512
        c0.816,0.325,1.754,0.512,2.753,0.512l65.732,13c3.099,0,5.634-1.786,5.634-3.968v-4.96c0-1.728-56-45.503-56-45.503V243l122,30
        c6.6,0,12-5.4,12-12v-15C322,240.775,188,137.607,188,137.607z" />
                </g>
            </svg>
        </div>
        <div class="enemy" style="width: 50px;"> <!--敵人飛機樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 322 349" style="enable-background:new 0 0 322 349;" xml:space="preserve">
                <g>
                    <path style="fill:#B53030;" d="M188,211.393v26.916c0,3.21,0.017,15.289-7.462,23.572V312.5c0,5.775-11.542,36.5-19.538,36.5
        s-19.538-30.725-19.538-36.5v-50.618c-7.479-8.283-7.462-20.363-7.462-23.572v-26.916c0,0-134-103.168-134-108.393V88
        c0-6.6,5.4-12,12-12l122,30V54.43c0,0-56-43.775-56-45.503v-4.96C78,1.786,80.535,0,83.634,0l65.732,13
        c0.999,0,1.937,0.188,2.753,0.512C154.904,13.182,157.891,13,161,13s6.096,0.182,8.881,0.512c0.816-0.325,1.754-0.512,2.753-0.512
        l65.732-13C241.465,0,244,1.786,244,3.968v4.96c0,1.728-56,45.503-56,45.503V106l122-30c6.6,0,12,5.4,12,12v15
        C322,108.225,188,211.393,188,211.393z" />
                </g>
            </svg>
        </div>
        <div class="bullet" style="width: 10px;"> <!--子彈樣式-->
            <svg version="1.1" id="&#x5716;&#x5C64;_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 7 31" style="enable-background:new 0 0 7 31;" xml:space="preserve">
                <path style="fill:#FFCC3E;" d="M3.833,31L0,3.5C0,1.567,1.567,0,3.5,0h0C5.433,0,7,1.567,7,3.5L3.833,31z" />
                <circle style="fill:#FFFFFF;" cx="3.5" cy="3.5" r="2.5" />
            </svg>
        </div>


    </div>
    <script type="text/javascript">
    $(function() {
        var gameStage = $(".gameBase"); /*將遊戲場景放入變數,供未來方便使用*/
        var material = { /*用一個陣列,放入所有的遊戲素材,未來只要有此陣列開頭的就表示是素材,方便辨識*/
            aircraft: $(".aircraft").prop("outerHTML"), /*存入玩家飛機樣式,供未來方便使用*/
            aircraftHeight: $(".aircraft").height(), /*存入玩家飛機樣式高,供未來方便使用*/
            enemy: $(".enemy").prop("outerHTML"), /*存入敵人飛機樣式,供未來方便使用*/
            enemytHeight: $(".aircraft").height(), /*存入敵人飛機樣式高,供未來方便使用*/
            bullet: $(".bullet").prop("outerHTML") /*存入子彈樣式,供未來方便使用*/
        };

        var aircraft = $("<div>"); /*定義變數aircraft是一個div*/
        aircraft.append(material.aircraft) /*aircraft的div放入玩家飛機樣式*/
        aircraft.addClass("impactArc"); /*此div增加impactArc的class,供之後碰撞偵測使用*/
        aircraft.css({ /*增加此div要放入遊戲場景的位置*/
            "position": "absolute",
            "left": gameStage.width() / 2 - 25,
            "top": gameStage.height() - material.aircraftHeight
        });
        $(".gameBase").append(aircraft); /*場景放入玩家aircraft*/



        function inputEnemy() { /*放入敵人的函式,因為要重複放入敵人,因此寫成函式*/
            var enemy = $("<div>"); /*定義變數enemy 是一個div*/
            enemy.append(material.enemy) /*enemy的div放入敵人飛機樣式*/
            enemy.addClass("impact"); /*此div增加impact的class,供之後碰撞偵測使用*/
            enemy.css({ /*增加此div要放入遊戲場景的位置*/
                "position": "absolute",
                "left": Math.floor(Math.random() * gameStage.width()), /*敵人飛機左右位置由場景大小亂數產生*/
                "top": -material.enemytHeight /*高度放置在場景高度以上*/
            })
            $(".gameBase").append(enemy) /*場景放入敵人*/
            enemy.stop().animate({ top: gameStage.height() + material.enemytHeight }, 3000, function() { enemy.remove(); }); /*敵人移動方式,會往場景底端位置移動,移出場景後刪除自己釋放效能*/
        }

        var startInputEnemy = setInterval(inputEnemy, 1000);/*每一秒重新放入敵人一次*/

        function fireBullet() { /*發射子彈的函式,因為要重複發射子彈,因此寫成函式*/
            var bullet = $("<div>"); /*定義子彈是一個div*/
            bullet.append(material.bullet) /*bullet的div放入子彈樣式*/
            bullet.addClass("impactArc");  /*此div增加impactArc的class,供之後碰撞偵測使用*/            
            bullet.css({ /*增加此div要放入遊戲場景的位置*/
                "position": "absolute",
                "left": aircraft.position().left + (aircraft.width() / 2) - 6, 
                /*因為子彈要有飛機發射出來的感覺,因此要抓取玩家飛機位置做定位*/
                "top": aircraft.position().top - material.aircraftHeight
                /*因為子彈要有飛機發射出來的感覺,因此要抓取玩家飛機位置做定位*/
            })
            $(".gameBase").append(bullet); /*遊戲場景放入子彈*/
            bullet.stop().animate({ top: 0 }, 3000, function() { bullet.remove(); });
            /*子彈移動方式,會往場景上方位置移動,移出場景後刪除自己釋放效能*/
        }



        var playerDir = new Array; /*定義一個陣列存放玩家飛機位置*/
        var boxDir = new Array; /*定義一個陣列存放敵人位置*/

        function impactTest() { /*碰撞偵測函式*/

            $.each($(".impact"), function() { /*每一個敵機div都執行以下*/
                boxDir[0] = $(this).position().top; /*敵機高存入boxDir變數0*/
                boxDir[1] = $(this).position().left; /*敵機左存入boxDir變數1*/
                boxDir[2] = $(this).position().top + $(this).height(); /*敵機下存入boxDir變數2*/
                boxDir[3] = $(this).position().left + $(this).width(); /*敵機右存入boxDir變數3*/

                for (i = 0; i < $(".impactArc").length; i++) { /*玩家飛機跟子彈,執行以下*/
                    playerDir[0] = $(".impactArc").eq(i).position().top; /*敵機高存入playerDir變數0*/
                    playerDir[1] = $(".impactArc").eq(i).position().left; /*敵機高存入playerDir變數0*/
                    playerDir[2] = $(".impactArc").eq(i).position().top + $(".impactArc").height(); 
                    /*敵機高存入playerDir變數2*/
                    playerDir[3] = $(".impactArc").eq(i).position().left + $(".impactArc").width(); 
                    /*敵機高存入playerDir變數3*/

                    if (playerDir[3] > boxDir[1] && playerDir[1] < boxDir[1] || playerDir[1] > boxDir[1] && playerDir[3] < boxDir[3] || playerDir[1] < boxDir[3] && playerDir[3] > boxDir[3]) { 
                    /*偵測敵人是否有跟玩家做子彈左右重疊*/

                        if (playerDir[0] < boxDir[2] && playerDir[2] > boxDir[2] || playerDir[0] < boxDir[0] && playerDir[2] > boxDir[0] || playerDir[0] < boxDir[2] && playerDir[2] > boxDir[0]) {
                         /*偵測敵人是否有跟玩家做子彈上下重疊*/      
                         /*有的話執行以下*/       


                            if ($(".impactArc").eq(i).children("div").hasClass("bullet")) {
                                $(this).remove();/*如果是子彈重疊,表是敵機被打中,移除敵機自己*/
                                $(".message").text("擊中"); /*在訊息欄顯示擊中*/
                            } else if ($(".impactArc").eq(i).children("div").hasClass("aircraft")) {
                                /*如果是跟玩家重疊,表示玩家被撞到*/
                                $(".message").text("相撞");/*在訊息欄顯示相撞*/
                            };
                        }
                    }
                }

            }); //$.each
        }


        var aircraftStep = 5; /*定義玩家一次能飛多遠px*/


        function moveDir(dir) { /*玩家移動函式*/
            switch (dir) {  /*由dir判斷選擇執行哪段動作*/
                case "left": /*如果dir是left則往左*/
                    if (aircraft.position().left - aircraftStep > 0) {
                        /*如果飛機左邊像素減掉一次移動距離小於0,則可往左*/
                        aircraft.css({
                            "left": aircraft.position().left - aircraftStep
                        });
                    };
                    break;
                case "right":/*如果dir是right則往右*/
                    if (aircraft.position().left + aircraft.width() + aircraftStep < gameStage.width()) {
                        /*如果飛機右邊像素加上一次移動在加上飛機寬,沒有超出遊戲畫面,則可往右*/
                        aircraft.css({
                            "left": aircraft.position().left + aircraftStep
                        });
                    };
                    break;
                case "up":/*如果dir是up則往上*/
                    if (aircraft.position().top - aircraftStep > 0) {
                        /*如果飛機減掉一次移動距離,還未超出遊戲場景上方則可移動*/
                        aircraft.css({
                            "top": aircraft.position().top - aircraftStep
                        });
                    };
                    break;
                case "down":/*如果dir是down則往下*/
                    if (aircraft.position().top + aircraft.height() + aircraftStep < gameStage.height()) {
                        /*如果飛機加上一次移動距離再加上飛機高,還未超出遊戲場景下方則可移動*/
                        aircraft.css({
                            "top": aircraft.position().top + aircraftStep
                        });
                    };
                    break;
                default:

            }
        }



        function keyDownHandler(e) {
            switch (e.keyCode) { /*依據玩家按哪個鍵,執行相對應函式帶入*/
                case 37:
                     moveDir("left");
                    break;
                case 39:
                     moveDir("right");
                    break;
                case 38:
                     moveDir("up");
                    break;
                case 40:
                     moveDir("down");
                    break;
                default:

            };           
        };
        document.addEventListener("keydown", keyDownHandler, false);/*如果玩家有按鍵盤則執行keyDownHandler*/


        
        $(".gamePad > div").click(function (){            
            switch ($(this).attr("class")) { /*依據玩家按哪個按鈕,執行相對應函式帶入*/
                case "left":
                     moveDir("left");
                    break;
                case "right":
                     moveDir("right");
                    break;
                case "up":
                     moveDir("up");
                    break;
                case "down":
                     moveDir("down");
                    break;
                default:

            }
            
        })
        


        

        var impactTestTime = setInterval(function() { /*每500毫秒發射子彈一次,並且運算碰撞程式*/
            impactTest();
            fireBullet();
        }, 500);


    })
    </script>
</body>

</html>

 
作者芋圓是位喜歡寫程式的視覺設計師,因此可以用視覺人的邏輯去教學javascrip和jQuery、CSS如果有任何想學的又或者是疑問,都可以留言,芋圓樂意分享與教學。

作者網站:https://huangmaster.com/
遊戲範例:點我

有任何疑問可以留言告知,或是E-Mail給芋圓
nickhuang1121@gmail.com

看更多 芋圓語法教室 教學示範文章

 

 


搜尋便宜機票
搜尋

發表迴響