HTML+JS+websocket 實例泽艘,聯(lián)機“游戲王”對戰(zhàn)(六)- 卡片放置置蜀,戰(zhàn)場更新

目錄

HTML+JS+websocket 實例,聯(lián)機“游戲王”對戰(zhàn) 1
HTML+JS+websocket 實例悉盆,聯(lián)機“游戲王”對戰(zhàn) 2 - 聯(lián)機模式
HTML+JS+websocket 實例盯荤,聯(lián)機“游戲王”對戰(zhàn) 3 - 界面布局
HTML+JS+websocket 實例,聯(lián)機“游戲王”對戰(zhàn) 4 - 卡組系統(tǒng)
HTML+JS+websocket 實例焕盟,聯(lián)機“游戲王”對戰(zhàn) 5 - 卡片選中系統(tǒng)
HTML+JS+websocket 實例秋秤,聯(lián)機“游戲王”對戰(zhàn) 6 - 卡片放置,戰(zhàn)場更新
HTML+JS+websocket 實例脚翘,聯(lián)機“游戲王”對戰(zhàn) 7 - 墓地灼卢,副控制面板
HTML+JS+websocket 實例,聯(lián)機“游戲王”對戰(zhàn) 8 - 返回手卡来农,卡組
HTML+JS+websocket 實例鞋真,聯(lián)機“游戲王”對戰(zhàn) 9 - 實現(xiàn)簡單 websocket 通信
HTML+JS+websocket 實例,聯(lián)機“游戲王”對戰(zhàn) 10 - 搭建游戲服務端
HTML+JS+websocket 實例沃于,聯(lián)機“游戲王”對戰(zhàn) 11 - 客戶端消息的收發(fā)
HTML+JS+websocket 實例涩咖,聯(lián)機“游戲王”對戰(zhàn) 12 - 消息發(fā)送具體場景
HTML+JS+websocket 實例,聯(lián)機“游戲王”對戰(zhàn) 13 - 實機演示

功能按鍵的實現(xiàn)(一)

1. 卡片放置:

卡片的攻擊繁莹,防御檩互,背蓋防御召喚以及發(fā)動,覆蓋咨演,這些操作都可歸類為玩家向戰(zhàn)場上放置卡片闸昨,卡片放置函數(shù)可通過傳遞不同參數(shù)來分別執(zhí)行這些功能。

實現(xiàn)卡片放置主要有幾個步驟:

(1)選中手牌某一張卡片薄风,并記錄卡片信息:
這個操作由我們前面章節(jié)介紹的卡片選中系統(tǒng)來完成饵较,當我們選中某張卡片后會用一個全局對象記錄卡片的來源類型(手牌/場上),卡片序號遭赂,卡牌圖片 url 等信息供其他函數(shù)使用循诉。

(2)尋找場上的空卡槽:
確定怪獸/魔法陷阱區(qū)域的某個空卡槽,如果沒有空卡槽剩余則無法執(zhí)行召喚/發(fā)動/覆蓋嵌牺。

(3)將被選中的手牌刪除:
被選中的手牌被打到場上去了打洼,故需從手牌被刪除龄糊。

(4)更新戰(zhàn)場信息并更新戰(zhàn)場:
將被選中的卡片按要求加載至戰(zhàn)場上并記錄其狀態(tài)。

卡片放置函數(shù) placeCard:

參數(shù) 含義
placetype 放置類型募疮,包括 攻擊 / 防御 / 背蓋防御 / 發(fā)動 / 覆蓋
cardtype 卡片類型炫惩,包括 怪獸 / 魔法陷阱
尋找 怪獸/魔法陷阱 區(qū)域的空卡槽;

如果(卡槽未滿)阿浓;
    如果(被選中的卡片來源于手牌):
        記錄手牌id他嚷;
        通過手牌id獲取手牌卡槽對象;
        清除手牌卡槽的卡片芭毙;
        
        更新戰(zhàn)場數(shù)組fieldArrayPly1的內容筋蓖;
        更新戰(zhàn)場上的卡片;

        清空所有卡槽的選中狀態(tài)退敦;

/**
 * 我方從手牌向場上放置卡片粘咖,并發(fā)出放置指令 (攻擊,防御侈百,背蓋防御瓮下,發(fā)動,蓋卡)
 * @param {string} placetype - place type (attack/defence/back/on/off)
 * @param {string} cardtype - card type (monster/magic)
 */
function placeCard(placetype, cardtype) {

    var cardslot = findEmptySlot(cardtype) //尋找空的卡槽
    var cardsrc;

    if(cardslot == -1) {
        alert("卡槽已滿");
    } else {
        if (SelectedCard.type == 'hand') {  //放置卡片必須來源于手牌
            /*獲取被選中手卡信息 */
            var handslot = (SelectedCard.cardNo).toString();
            var handID = "p1-hand" + handslot;
            element = document.getElementById(handID);
            cardsrc = SelectedCard.cardSrc;
            element.src = "";  //手牌該卡消失

            /*更新戰(zhàn)場信息 */
            fieldArrayPly1.FieldCards[cardslot].imgsrc = cardsrc;
            fieldArrayPly1.FieldCards[cardslot].state = placetype;

            /*發(fā)出指令钝域,執(zhí)行更新戰(zhàn)場卡片的函數(shù) */
            var fieldID = "p1-field" + cardslot.toString();
            updateField(fieldID, placetype, cardsrc);

            /**
             * 放置后告知對手執(zhí)行戰(zhàn)場更新函數(shù);
             * 放置完成后記得告訴對手哪張手卡消失了;
             * 注意:我方戰(zhàn)場變化對對方來說是P2;
             */
            var updateID = "p2-field" + cardslot.toString();
            messageField(placetype, updateID, cardsrc);
            messageHand('reduce', handslot);

            /*清空所有選中狀態(tài) */
            cleanSelected();
        }
    }
}

在html中:

<button class="button" type="button" name="attkSummon" onclick="placeCard('attk', 'monster')">攻擊召喚</button>
<button class="button" type="button" name="defenSummon" onclick="placeCard('defen', 'monster')">守備召喚</button>
<button class="button" type="button" name="backSummon" onclick="placeCard('back', 'monster')">背蓋召喚</button>
<button class="button" type="button" name="launchCard" onclick="placeCard('on', 'magic')">發(fā)動(手卡)</button>
<button class="button" type="button" name="coverCard" onclick="placeCard('off', 'magic')">覆蓋(手卡)</button>

這些 button 都會調用 placeCard 函數(shù)讽坏,且根據(jù)不同的功能傳入不同的參數(shù)。

尋找空卡槽函數(shù) findEmptySlot

/**
 * 返回當前我方場上/手牌的空卡槽序號(怪獸卡槽與魔法陷阱卡槽也要區(qū)分開)
 * @param {string} slottype - type of wanted empty slot (monster/magic/hand) 
 */
function findEmptySlot(slottype) {
    var emptySlot = -1;

    if (slottype == 'monster') {  //放置怪獸卡搜索0-4卡槽
        for (var i=0; i<5; i++) {
            if (fieldArrayPly1.FieldCards[i].state == "null") {
                emptySlot = i;
                break;
            }
        }
    } else if (slottype == 'magic') {  //放置魔法陷阱卡搜索5-9卡槽
        for (var i=5; i<10; i++) {
            if (fieldArrayPly1.FieldCards[i].state == "null") {
                emptySlot = i;
                break;
            }
        }
    } else if (slottype == 'hand') {
        for (var i=0; i<8; i++) {
            var handID = 'p1-hand' + i.toString();
            element = document.getElementById(handID);
            if (element.src == emptysrc) {  //如果該卡槽為空
              emptySlot = i;
              break;
            }
        }
    }

    return emptySlot;
}

根據(jù)被選中卡片的類型去尋找相應區(qū)域的空卡槽例证,并返回卡槽序號路呜。


2. 更變卡片表示形式:

卡片表示形式的更變包括怪獸卡與魔法陷阱卡。

怪獸卡的形式變更順序:
攻擊 -> 防御 -> 背蓋 -> 攻擊 -> ...

魔法陷阱的形式更變順序:
覆蓋 -> 表側 -> 覆蓋 -> ...

更變形式函數(shù) changeState

參數(shù) 含義
cardtype 卡片類型织咧,包括 怪獸/魔法陷阱
如果(被選中的卡屬于場上 且 屬于我方玩家player1):
    獲取卡槽id胀葱;
    獲取卡槽中的卡片url以及當前狀態(tài)(即表示形式state);
    
    如果卡片類型是:
    怪獸:
        按 攻擊/防御/背蓋 的順序變更1次狀態(tài)并記錄烦感;
    魔法陷阱:
        按 表側/背蓋 的順序變更1次狀態(tài)并記錄巡社;
    
    更新戰(zhàn)場數(shù)組fieldArrayPly1中該卡槽的狀態(tài)(state);
    更新戰(zhàn)場上的卡片手趣;

/**
 * 更變卡片的表示形式
 * 更變順序為:攻擊 -> 防御 -> 背蓋 -> 攻擊, 蓋覆卡 -> 表側卡 -> 蓋覆卡
 * @param {string} cardtype - card type (monster/magic)
 */
function changeState(cardtype) {
    if (SelectedCard.type == 'field' && SelectedCard.player == 'player1') {  //必須是我方場上的卡方可更變表示形式
        var fieldID = "p1-field" + (SelectedCard.cardNo).toString();
        var cardsrc = fieldArrayPly1.FieldCards[SelectedCard.cardNo].imgsrc;
        var cardstate = fieldArrayPly1.FieldCards[SelectedCard.cardNo].state;

        switch (cardtype) {
            case 'monster':
                if (cardstate == 'attk') {
                    cardstate = "defen";
                } else if (cardstate == 'defen') {
                    cardstate = "back";
                } else if (cardstate == 'back') {
                    cardstate = "attk";
                }
                break;
            case 'magic':
                if (cardstate == 'off') {
                    cardstate = "on";
                } else {
                    cardstate = "off";
                }
                break;
            default:
                break;
        }

        fieldArrayPly1.FieldCards[SelectedCard.cardNo].state = cardstate;  //更新場上卡片狀態(tài)信息
        cardstate = "change-" + cardstate;  //為通過更變形式而導致的戰(zhàn)場更新操作添加一個標簽方便更新函數(shù)識別(因為更變形式不觸發(fā)音效)
        updateField(fieldID, cardstate, cardsrc);  //更新指定卡槽

        /**
         * 告知對手某一卡槽的表示形式發(fā)生變化肥荔,執(zhí)行戰(zhàn)場更新函數(shù)
         */
        var updateID = "p2-field" + (SelectedCard.cardNo).toString();
        messageField(cardstate, updateID, cardsrc);
    }
}

更變后的形式(state)會被戰(zhàn)場數(shù)組記錄并同時傳遞給戰(zhàn)場更新函數(shù) updateField 以更新所選卡槽的卡片樣式绿渣。


3. 戰(zhàn)場更新函數(shù):

戰(zhàn)場更新函數(shù) updateField 用于更改某一個卡槽的卡片樣式,讓玩家可以實際的看到操作帶來的變化燕耿,前面介紹的兩個函數(shù)均有在作用域的末尾調用此函數(shù)中符。

參數(shù) 含義
fieldID 需要更新的卡槽 id
cardstate 需要更新的卡片狀態(tài)
cardsrc 需要更新的卡牌圖片 url

updateField 的原理很簡單,我們在css中準備了幾種卡片狀態(tài)對應的卡槽樣式誉帅,根據(jù)參數(shù)的不同修改卡槽樣式即可(其實有些樣式是一樣的完全可以共用…)淀散。

.main-field .battle-field .card-field .item .card-attk {
  width: 65px;
  height: 94px;
  margin: 1px 40px;
}

.main-field .battle-field .card-field .item .card-defen {
  width: 65px;
  height: 94px;
  transform: rotate(90deg);
  margin: 1px 40px;
}

.main-field .battle-field .card-field .item .card-back {
  width: 65px;
  height: 94px;
  transform: rotate(90deg);
  margin: 1px 40px;
}

.main-field .battle-field .card-field .item .card-on {  /* 魔法陷阱翻開狀態(tài)*/
  width: 65px;
  height: 94px;
  margin: 1px 40px;
}

.main-field .battle-field .card-field .item .card-off {  /* 魔法陷阱覆蓋狀態(tài)*/
  width: 65px;
  height: 94px;
  margin: 1px 40px;
}
/**
 * 戰(zhàn)場狀態(tài)更新右莱,單獨更新某一個卡槽
 * @param {string} fieldID - field img container id 
 * @param {string} cardstate - state of card (attk/defen/back/on/off)
 * @param {string} cardsrc - card source url
 */
function updateField(fieldID, cardstate, cardsrc) { 
    var stateclass;
    element = document.getElementById(fieldID);

    /**
     * 如果是蓋卡或背蓋召喚直接顯示卡片背面
     * 檢查showCardInfo函數(shù)可知對于我方來說,即使卡片是背面圖片仍可以顯示卡片信息
     * 由于音效種類問題修改分類了多種情況
     */
    switch (cardstate) {
        case 'off':
        case 'back':
            element.src = CardBackSrc;
            stateclass = "card-" + cardstate;
            /*觸發(fā)背蓋或蓋卡音效 */
            var snd = new Audio("sound/activate.wav");
            snd.play();
            break;
        case 'on':  //正常發(fā)動卡片
            element.src = cardsrc;
            stateclass = "card-" + cardstate;
            /*觸發(fā)發(fā)動卡片音效 */
            var snd = new Audio("sound/activate.wav");
            snd.play();
            break;
        case 'change-off':  //通過更變形式覆蓋卡片
            element.src = CardBackSrc;
            stateclass = "card-" + cardstate.replace("change-", "");
            break;
        case 'change-back':  //通過更變形式背蓋召喚卡片
            element.src = CardBackSrc
            stateclass = "card-" + cardstate.replace("change-", "");
            break;
        case 'change-on':  //通過更變形式實現(xiàn)的打開蓋卡
            /*觸發(fā)打開蓋卡音效 */
            element.src = cardsrc;
            stateclass = "card-" + cardstate.replace("change-", "");
            var snd = new Audio("sound/open.wav");
            snd.play();
            break;
        case 'null':
            stateclass = "card";
            element.src = cardsrc;
            break;
        default:
            element.src = cardsrc;
            if (cardstate.search("change-") == -1) {  //正常召喚
                stateclass = "card-" + cardstate;
                /*觸發(fā)發(fā)召喚怪獸音效 */
                var snd = new Audio("sound/summon.wav");
                snd.play();
            } else {                                  //更變形式
                stateclass = "card-" + cardstate.replace("change-", "");
            }
            break;
    }

    element.setAttribute("class", stateclass);  //更新對應img容器的class
}

:這里由于添加音效的問題多出了3種狀態(tài)档插,change-off, change-back, change-on慢蜓,因為通過更變形式打開或背蓋卡片與直接從手牌發(fā)動或背蓋卡片的音效是不同的,故多加了幾個狀態(tài)區(qū)分一下郭膛。前文 changeState 函數(shù)中也有一段代碼是為了這里區(qū)分而在調用戰(zhàn)場更新前修改了狀態(tài)名稱:

fieldArrayPly1.FieldCards[SelectedCard.cardNo].state = cardstate;  //更新場上卡片狀態(tài)信息
cardstate = "change-" + cardstate;  //為通過更變形式而導致的戰(zhàn)場更新操作添加一個標簽方便更新函數(shù)識別(因為更變形式不觸發(fā)音效)
updateField(fieldID, cardstate, cardsrc);  //更新指定卡槽


最后來測試一下:

各種召喚:

summons.gif

發(fā)動/放置 魔法陷阱:

magics.gif

更變形式:

change_state.gif

下一章繼續(xù)介紹其他的功能按鍵晨抡。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市则剃,隨后出現(xiàn)的幾起案子耘柱,更是在濱河造成了極大的恐慌,老刑警劉巖棍现,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件调煎,死亡現(xiàn)場離奇詭異,居然都是意外死亡己肮,警方通過查閱死者的電腦和手機士袄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朴肺,“玉大人窖剑,你說我怎么就攤上這事「旮澹” “怎么了西土?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鞍盗。 經(jīng)常有香客問我需了,道長,這世上最難降的妖魔是什么般甲? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任肋乍,我火速辦了婚禮,結果婚禮上敷存,老公的妹妹穿的比我還像新娘墓造。我一直安慰自己,他們只是感情好锚烦,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布觅闽。 她就那樣靜靜地躺著,像睡著了一般涮俄。 火紅的嫁衣襯著肌膚如雪蛉拙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天彻亲,我揣著相機與錄音孕锄,去河邊找鬼吮廉。 笑死,一個胖子當著我的面吹牛畸肆,可吹牛的內容都是我干的宦芦。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼恼除,長吁一口氣:“原來是場噩夢啊……” “哼踪旷!你這毒婦竟也來了?” 一聲冷哼從身側響起豁辉,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤令野,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后徽级,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體气破,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年餐抢,在試婚紗的時候發(fā)現(xiàn)自己被綠了现使。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡旷痕,死狀恐怖碳锈,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情欺抗,我是刑警寧澤售碳,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站绞呈,受9級特大地震影響贸人,放射性物質發(fā)生泄漏。R本人自食惡果不足惜佃声,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一艺智、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧圾亏,春花似錦十拣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弄跌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尝苇,已是汗流浹背铛只。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工埠胖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淳玩。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓直撤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜕着。 傳聞我的和親對象是個殘疾皇子谋竖,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內容