HTML+JS+websocket 实例,联机“游戏王”对战(七)- 墓地,副控制面板

目录

HTML+JS+websocket 实例,联机“游戏王”对战 1
HTML+JS+websocket 实例,联机“游戏王”对战 2 - 联机模式
HTML+JS+websocket 实例,联机“游戏王”对战 3 - 界面布局
HTML+JS+websocket 实例,联机“游戏王”对战 4 - 卡组系统
HTML+JS+websocket 实例,联机“游戏王”对战 5 - 卡片选中系统
HTML+JS+websocket 实例,联机“游戏王”对战 6 - 卡片放置,战场更新
HTML+JS+websocket 实例,联机“游戏王”对战 7 - 墓地,副控制面板
HTML+JS+websocket 实例,联机“游戏王”对战 8 - 返回手卡,卡组
HTML+JS+websocket 实例,联机“游戏王”对战 9 - 实现简单 websocket 通信
HTML+JS+websocket 实例,联机“游戏王”对战 10 - 搭建游戏服务端
HTML+JS+websocket 实例,联机“游戏王”对战 11 - 客户端消息的收发
HTML+JS+websocket 实例,联机“游戏王”对战 12 - 消息发送具体场景
HTML+JS+websocket 实例,联机“游戏王”对战 13 - 实机演示

功能按键的实现(二)

文接上回,继续介绍功能按键。

1. 墓地与送去墓地:

先来实现下墓地系统。和卡组系统几乎一样,一个字符串数组,存储卡片url:

var P1Tomb = [];  //我方墓地(卡片src)

当有新卡片送入墓地时,把它的图片路径 PUSH 进去,若需拿出卡片则用 splic() 将其从墓地剔出。

执行送去墓地的操作前,我们仍然需要先选中一张卡片,全局对象 SelectedCard 会像缓存一样帮我们记录选中卡片的相关信息。

为了简化函数,送去墓地函数 sendtoTomb 只允许操作我方卡片,不能直接将对方卡牌送去墓地。同时只能直接操作场上与手牌的卡片,牌组中的卡片需要加入手牌后再送入墓地。

获取选中卡片url;
获取选中卡槽序号;

如果(选中卡片属于我方玩家player1):
    如果(卡片来源于手牌):
        根据卡槽序号获取手牌卡槽id;
        将选中手牌卡槽清空;
        将选中卡片url PUSH 到墓地P1Tomb中;

    如果(卡片来源于场上):
        根据卡槽序号获取场上卡槽id;
        将该卡的记录从战场数组fieldArrayPly1中清除;
        将选中卡片从卡槽清空;
        将选中卡片url PUSH 到墓地P1Tomb中;

清空所有被选中的状态;

/**
 * 将我方的卡片(场上/手牌)送去墓地
 */
function sendtoTomb() {
    var cardsrc = SelectedCard.cardSrc;
    var cardNo = SelectedCard.cardNo;
    var fieldID; 
    
    if (SelectedCard.player == 'player1') {
        /*若卡片来源于手牌 */
        if (SelectedCard.type == 'hand') {
            var handID = "p1-hand" + cardNo.toString();
            element = document.getElementById(handID);
            element.src = "";  //手牌该卡消失
            P1Tomb.push(cardsrc);  //将选中卡片的src存入墓地数组

            /**
             * 告知对方更新我方手牌数及墓地
             */
            messageHand("reduce", cardNo);
            messageTomb("add", "player2", "null", cardsrc);  //向墓地添加卡片不需要cardNo

        /*若卡片来源于场上 */
        } else if (SelectedCard.type == 'field') {
            fieldID = "p1-field" + cardNo.toString();
            fieldArrayPly1.FieldCards[cardNo].imgsrc = "null";  //场上该卡的记录清空
            fieldArrayPly1.FieldCards[cardNo].state = "null";
            P1Tomb.push(cardsrc);  //将选中卡片的src存入墓地数组
            updateField(fieldID, "null", "");  //更新战场

            /**
             * 告知对方更新我方战场及墓地
             */
            var updateID = "p2-field" + cardNo.toString();
            messageField("null", updateID, "");
            messageTomb("add", "player2", "null", cardsrc);
        } else {
            alert("请先将卡片拿到手牌再放入墓地");  //防止直接从卡组或墓地中选卡放回墓地
        }

        /*清空所有选中状态 */
        cleanSelected();

        sf_buttons('p1tomb');  //刷新副面板显示
    }
}

清除手牌的卡时我们直接获取 html 对象并置空它的src属性,清除战场卡槽时我们就直接用已有的函数 updateField 吧。

最后一行代码刷新副面板其实就是在副面板里显示刚被送入墓地的卡片(见演示gif),具体放到后面来说。

演示效果:


send_tomb.gif

2. 副控制面板:

介绍“回到手牌”与“回到卡组”这两个功能前有必要先介绍一下副控制面板了。

当我们操作“回到手牌”时,除了从场地上返回手牌,也有可能是从卡组或者墓地中取回卡片。场上的卡片是玩家直接可见并且可选的,而卡组或墓地一般存放在后台,不会一直展示给玩家。副控制面板就是在玩家需要时,将卡组或者墓地中的卡片全部加载列举出来,供玩家选择操作。

game_ui_subfield.png

这个显示区域是动态元素,每次点击按钮后都需要重新加载内容,所以在html里这一块的容器是留空的(id是select-area):

<div class="card-selection">
   <div id="select-area" class="selection-area"></div>
   <div class="button-area">
     <button class="button" type="button" onclick="sf_buttons('deck')">从牌组中选择(刷新列表)</button>
     <button class="button" type="button" onclick="sf_buttons('p1tomb')">从我方墓地选择(刷新列表)</button>
     <button class="button" type="button" onclick="sf_buttons('p2tomb')">从对方墓地选择(刷新列表)</button>
     <button class="button" type="button" onclick="shuffleDeck()">洗牌</button>
   </div>
 </div>

为了避免一些 bug 和参数方面的混淆,我给副控制面板的卡片显示,卡片选中等功能重新写了一套函数(希望以后能设计更好的架构合并相似功能而不是重构)。

在玩家操作时,我们准备了一个全局对象来记录玩家的选择,因为其他函数需要用到这些信息:

var sf_Card = {
    type: "null",  //卡的来源类型(我方卡组,我方墓地,对方墓地)
    player: "null",  //记录副面板显示卡片的玩家类型
    size: 0  //记录副面板显示卡片的数量
};

动态面板上的主要功能按键分为三种,“从(我方)牌组中选择”,“从我方墓地中选择”,“从对方墓地中选择”。这里为了避免一些问题没有设置 “从对方牌组中选择” 这个功能,需要获取对方卡牌可由对方取出后放置场上再由我方加入手卡,实战中这个功能也并不常用。

三个功能按键都对应同一个函数 sf_buttons,参数只有一个,不同按键传入不同参数值来执行对应功能。主要是根据玩家的选择在显示区域动态创建数个img标签并逐一加载卡组/墓地中的卡片图片。每个img标签的 onmouseover 属性设置显示卡片信息的函数 sf_showInfo,onclick 属性设置选中函数 sf_selecteCard

获取副面板显示区域对象;
清空副面板的全部内容;

创建一个空的临时卡组数组cardset;

如果玩家需要显示的卡片来源于:
    我方卡组:
        拷贝当前我方卡组至cardset;
        sf_Card记录其他相关信息;
    我方墓地:
        拷贝当前我方墓地至cardset;
        sf_Card记录其他相关信息;
    对方墓地:
        拷贝当前对方墓地至cardset;
        sf_Card记录其他相关信息;

遍历cardset中所有卡片url:
    在显示区域创建子元素cardImg,类型是img;
    按循环顺序设置子元素id,这个id序号其实也正好对应卡片在卡组/墓地中的位置;
    设置class,onmouseover,onclick属性;
    设置cardImg的src属性为cardset中的图片rul,加载图片;
    将子元素cardImg添加至父容器selectArea;

/**
 * 选择副面板显示的内容(我方卡组/我方墓地/对方卡组)
 * @param {string} type - button type (P1 deck/P1 tomb/ P2 deck)
 */
function sf_buttons(type) {
    var selectArea = document.getElementById("select-area");
    selectArea.innerHTML = "";  //清空副面板显示框

    var cardset = [];

    switch (type) {
        case "deck":
            cardset = P1Deck;
            sf_Card.player = "player1";
            sf_Card.type = "deck";
            break;
        case "p1tomb":
            cardset = P1Tomb;
            sf_Card.player = "player1";
            sf_Card.type = "p1tomb";
            break;
        case "p2tomb":
            cardset = P2Tomb;
            sf_Card.player = "player2";
            sf_Card.type = "p2tomb";
            break;
        default: break;
    }

    /*副面板显示需显示的内容(我方卡组/墓地/对方墓地的全部卡片) */
    sf_Card.size = cardset.length;
    for (i=0; i<sf_Card.size; i++) {
        var cardImg = document.createElement("img");
        cardImg.id = "sf-card" + i.toString();
        cardImg.setAttribute("class", "card");
        cardImg.setAttribute("onmouseover", "sf_showInfo(this.src)");
        cardImg.setAttribute("onclick", "sf_selectCard(this.id, this.src)");
        cardImg.src = cardset[i];
        selectArea.appendChild(cardImg);
    }
}

再贴下onmouseover设置的显示函数 sf_showInfo

/**
 * 显示副面板中被鼠标指到的卡片
 * @param {string} cardsrc - card img source 
 */
function sf_showInfo(cardsrc) {
    if (cardsrc != emptysrc) {
        element = document.getElementById('card-info');
        element.src = cardsrc;
    }
}

然后是onclick设置的选中函数 sf_selectCard

/**
 * 在副面板中选中卡片
 * @param {int} id - selection field img container id 
 * @param {string} cardsrc - selected card img source
 */
function sf_selectCard(id, cardsrc) {
    if (cardsrc != emptysrc) {
        var CardSrc = "image" + cardsrc.split('image')[1];
        cleanSelected();  //选择卡片之前首先清空场上已选中的卡片样式再更新
        element = document.getElementById(id);
        element.setAttribute("class", "card-selected");

        SelectedCard.player = sf_Card.player;
        SelectedCard.type = sf_Card.type;  //我方卡组/我方墓地/对方墓地
        SelectedCard.cardNo = parseInt(id.replace("sf-card", ""));  //用replace去掉id中的英文字符来获取数字字符
        SelectedCard.cardSrc = CardSrc;  //直接从img容器获取src
    }
}

这个函数主要是更改下副控制面板中的卡片样式,卡片相关信息还是要存到大的全局对象 SelectedCard 中的。

最后演示下效果:


select_from_deck.gif

“从我方墓地选择” 与 “从对方墓地选择” 的效果与此相似。另外前文 sendtoTomb 函数中最后调用了副面板显示其实也是重新使副面板加载墓地内容,这样玩家可以看到刚刚向墓地丢了什么卡:

sf_buttons('p1tomb');  //刷新副面板显示

下一章应该能把功能按键全讲完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容