Day36 - 「登愣登愣,登愣登登登」~ 隐挑战 Day12 ─ 果然我的青春写扣喜剧搞错了。完

重复是学习之母。继续写是完赛之母。
https://ithelp.ithome.com.tw/upload/images/20201012/20129873MJX4opV9lx.png

继续写是完赛之母XDDDDDDDDDDD
这会不会太符合我现况XDDDDDDDDDDDDDD

但真的不能再打扰铁人赛的各位大大们了(?),
其实是团员抱怨他们一直收到通知,
(好啦他们没抱怨,只是跟我提一下 XD)
而且我也不想拖着这个隐挑战一直结束不了orz
今天做了一些修改,
但我也不想没整理 code 就把成果赶着寄出去,
(因为 code 真的很乱QQ)
所以今天是我最後一篇隐挑战文了,
但我对自己承诺这礼拜一定会把它寄出去!

正片开始

本日课题:昨天提到要改的地方进行修正

1. 战斗成功&战斗失败合成一个函数,html 元素也合成一个
html 的部份,我将昨天写成两个部份:war_fail、war_success 的战斗结果显示,
合成一个 war_result。

<div class="war_result"></div>

CSS也将共同的部份改到 .war_result,
再将战斗成功、失败不同的 CSS 拆开来。

.war_result{
    position: absolute;
    z-index: 2;

    display: none;
    flex-direction: column;
    align-items: center;

    &.war_success{
        left: 300px;
        top: 120px;

        .message{
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            margin-bottom: 10px;
        }
        .message1{
            width: 546px;
            height: 118px;
            background-image: url("../img/success1.png");
        }
        .message2{
            width: 664px;
            height: 115px;
            background-image: url("../img/success2.png");
        }
    }
    &.war_fail{
        width: 100%;
        height: 100%;
        background-color: rgba(125, 20, 17, 0.5);
        padding-top: 100px;
        .message{
            color: #c2b6a5;
            font-size: 44px;
            font-family: "新细明体";
            text-shadow: 4px 5px 2px #000000; // 文字阴影效果 (X偏移 Y偏移 Blur 颜色)
            margin-bottom: 10px;
            letter-spacing: 5px; // 文字间距
        }
    }
}

JavaScript 的话,主要就是加上 warStatus 的变数,
战斗胜利就将值设为 WIN,
战斗失败就将值设为 FAIL,
然後 finishWar 函数再判断 warStatus 的值,
来载入不同的 BGM 跟 innerHTML。

let warStatus = "ONGOING";
const warResultElement = document.querySelector(".war_result");

function roleActionExecute(){
        ... 前略 ...
        // 如果怪的血量 <= 0,表示怪被消灭了,後续动作不用执行
        if ( roleStatus[2].HealthPoint[0] <=0 ){
            console.log("战斗胜利");
            warStatus = "WIN";
            window.removeEventListener("keydown", optionSelect);
            window.removeEventListener("keydown", skillSelect);
            setTimeout(finishWar, 3000); // 延迟3秒才显示战斗成功
        } 
    
}

function bloodClassReset(){
    if ( currentActor < 2 ){
        monsterBloodMinusElement.textContent = "";
        monsterBloodMinusElement.setAttribute("class",originClass);
        currentActor ++;
    } else{
        girlStatusElement.childNodes[0].setAttribute("class",originClass);
        if ( roleStatus[0].HealthPoint[0] <=0 && roleStatus[1].HealthPoint[0] <=0 ){ 
            console.log("角色全灭");
            warStatus = "FAIL";
            setTimeout(finishWar, 1500); // 延迟1.5秒才显示战斗失败
        } 
        ... 後略 ...
    }
}

function finishWar(){
    let originClass = warResultElement.getAttribute("class");
    switch(warStatus){
        case "WIN": 
            console.log("战斗胜利");
            musicElement.pause();
            setTimeout(function(){ 
                musicElement.loop = false;
                musicElement.src = "bgm/victory.mp3";
                musicElement.play();
            }, 500);
            warResultElement.innerHTML = `
            <div class="message message1"></div>
            <div class="message message2"></div>`;
            warResultElement.style = "display:flex";
            warResultElement.setAttribute("class",`${originClass} war_success animate__animated animate__pulse`);
            break;
        case "FAIL": 
            console.log("角色全灭");
            musicElement.pause();
            setTimeout(function(){ 
                musicElement.loop = false;
                musicElement.src = "bgm/fail.mp3";
                musicElement.play();
            }, 500);
            warResultElement.innerHTML = `
            <div class="message message1">
                胜败乃兵家常事也
            </div>
            <div class="message message2">
                大侠请重新来过吧
            </div>`;
            warResultElement.style = "display:flex";
            warResultElement.setAttribute("class",`${originClass} war_fail`);
            break;
        default:
            console.log("default");
            break;
    }
    // 要将战斗选单及角色状态隐藏
    warMenuElement.style = "display:none";
    roleStatusElement.style = "display:none";
    monsterBloodElement.style = "display:none";
}

2. 攻击量要随机
产生x~y中间的随机数字这边参考了 2018 铁人赛大大的文章→ 用Math.random()取得某区间内的随机乱数
所以新增了一个产生随机数字的函数:

function getRandom(min,max){
    return Math.floor(Math.random()*(max-min+1))+min;
}

然後在攻击的法术的地方代入 getRandom 函数来产生随机的攻击量:

function roleActionExecute(){
    ... 前略 ....
    if ( currentActor < 2 ){
        let attackQty;
        switch(roleStatus[currentActor].Action.OptionSelection){
            case "attack": // 动作为攻击
                attackQty = getRandom(roleStatus[currentActor].AttackPower-5,roleStatus[currentActor].AttackPower+5);
                attackQty -= roleStatus[2].DefensePower;
                break;
            case "skill": // 动作为招式
                let skillSelection = roleStatus[currentActor].Action.SkillSelection;
                attackQty = roleStatus[currentActor].Moves[skillSelection].Cost;
                attackQty *= getRandom(roleStatus[currentActor].MagicAttackPower-5,roleStatus[currentActor].MagicAttackPower+5)*0.5;
                attackQty -= roleStatus[2].DefensePower;
                // 法力消耗
                roleStatus[currentActor].MagicPoint[0] -= roleStatus[currentActor].Moves[skillSelection].Cost;
                break;
            ... 後略 ...
        }
        ... 後略 ...
    }
}

还有怪攻击的地方也改成攻击量随机:

else{
    console.log("轮到怪");
    let attackQty = getRandom(roleStatus[currentActor].AttackPower-5,roleStatus[currentActor].AttackPower+5);
    attackQty -= roleStatus[1].DefensePower;
    roleStatus[1].HealthPoint[0] -= attackQty;
    ... 後略 ...
}

让我们来看看效果吧!

  • 李逍遥攻击 -23
    https://ithelp.ithome.com.tw/upload/images/20201012/201298735DIsadYwCK.png
  • 赵灵儿攻击 -11
    https://ithelp.ithome.com.tw/upload/images/20201012/20129873wfy481kJHk.png
  • 怪攻击 -26
    https://ithelp.ithome.com.tw/upload/images/20201012/20129873bkoSirpa6s.png
  • 战斗成功
    https://ithelp.ithome.com.tw/upload/images/20201012/201298733IqFHWc2Ap.png

隐挑战打完收工!
ヽ(✿゚▽゚)ノ




隐挑战暨铁人赛完结心得(其实这才是本日正文?)

这次是真的要结束这 36 天的铁人赛了,
其实去年就有写这个隐挑战,
去年都硬写,因此 code 很多地方重复性很高,
今年有解决重复性很高的问题,
比起来今年真的进步了,觉得满意!

当然还有很多地方可以改的,
例如:怪要随机攻击李逍遥或赵灵儿、
(今天原本打算改的,但发现除了随机选择对象後,还要其对应的角色状态再进行扣血,
最麻烦的是要找到该对应的 html 元素再加上动画,
有点麻烦,就没改了orz)
两个角色如果有一个角色血量归 0,则应该要反灰不能进行攻击、
法力若小於招式消耗法力不能选择......等等,
其实有很多眉角可以精进orz

然後深深感觉到写游戏真的不容易XD
(我知道我写的只是很鸡毛蒜皮的一小部份而已orz)

铁人赛结束後,
问我有没有维持写程序手感的计划?
有哦!
这几天开始在研究 Next.js
然後发现 Next.js 是采用 React 的框架,
React 又牵扯到 JSX 的写法,
发现小的突然多了好多要学的东西啊!!!!!!
https://www.moedict.tw/%E5%AD%B8%E6%B5%B7%E7%84%A1%E6%B6%AF%E5%8B%A4%E6%98%AF%E5%B2%B8.png
是的,学海无涯,
小的要从这个坑跳往另一片海了XD
也许明年的铁人赛我就可以写 30 天学会 Next.js 的题目也说不定呢XD

有些感言其实第 30 天的文章写过了,
但这边还是写一下,
感谢团长之前的揪团,
虽然看到你第 30 天的文章才发现原来你中间也都想放弃XD
只是碍於我跟另外一位团员是自我挑战仔,
所以你才想说好吧不要放弃(?)

感谢团员一起度过这 30 天,
如果没有看到你们如此勤勉在拼铁人赛文章,
小的应该中途可能就会放弃了吧orz

感谢曾经不小心误入这个系列文的大大们,
还有感谢现在还在拼铁人赛的大大们,
我脱出了你们加油啊XD(被巴)

最後,感谢我自己,
谢谢你 36 天前挑了这个题目,
虽然中途很多次都很想巴 36 天前的自己,
但是我撑过来了!
而且 36 天以後我写程序的手感真的从 0 分变成了 60 分!!!!!
也因为这样才有机会去研究 Next.js,
虽然现在还是处於雾煞煞的状态,
期望之後的我就可以变得上手了!

那麽,
这一次是认真要跟大家说再见了,
30天找回写程序手感计划!!! 本系列文章到此告一段落,
感谢各位的爱戴(?),
各位 2021 见!!!!!
https://ithelp.ithome.com.tw/upload/images/20201012/20129873Gp9v8Wf3PE.png
希望明年真的还有机会再来参加铁人赛:)

[舍不得说再见(?)的後记]

然後这个系列文是真的有产出复习写程序手感程序的!
我在第 30 天的文章有写到,
有兴趣的可以右转至此→ Day30 - 「登愣登愣,登愣登登登」~ 隐挑战 Day6 暨铁人赛完赛心得
虽然不希望现在写程序手感不见,
但万一有一天又不见的话,
希望自己可以再次参考这次系列文产出的 SOP,
再找回一次手感:D


<<:  DAY27-ASP.NET网页切换导向及状态管理

>>:  多国语系魔术

SSL凭证检测工具-SSL Lab

昨天讲完XSS的评估小工具後 接着是测试最最常见SSL凭证的漏洞 我们可以利用线上工具SSL Lab...

【情蒐阶段】确认自己的目标、熟悉职缺市场

今天早上泡了杯 wushwush,打开我的 Leetcode, 啊又是一个觉得智力不足的 momen...

Day -6 条件式

python 条件式 if,注意 python run code 是 依据 code 排版 ,前後顺...

找LeetCode上简单的题目来撑过30天啦(DAY12)

题号:15 标题:3Sum 难度:Medium Given an integer array num...

[Day10] 如何实现图片填色功能 (完结)

#733 - Flood Fill 连结: https://leetcode.com/proble...