🎮ArcadeLab

Minecraft RPG

by SparkShark50
664 lines29.0 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Minecraft RPG</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:system-ui, sans-serif}
body{background:#222;color:#fff;overflow:hidden;font-size:12px}
#home{width:100vw;height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:24px}
#home h1{font-size:26px}
.btn{padding:8px 14px;background:#3a3a3a;border:1px solid #888;border-radius:4px;color:#fff;cursor:pointer;font-size:12px}
.btn:hover{background:#505050}
#game{width:100vw;height:100vh;display:none;position:relative;padding:12px}
.top-left{position:absolute;top:12px;left:12px;line-height:1.5;font-size:12px}
.battle-area{position:absolute;top:45%;left:50%;transform:translate(-50%,-50%);text-align:center;width:90%}
.monster-name{font-size:20px;margin-bottom:6px}
.hp-row{margin:3px 0;font-size:12px}
.bar-wrap{width:260px;height:14px;background:#111;border:1px solid #777;margin:6px auto;position:relative;overflow:hidden;border-radius:2px}
.bar-cd{height:100%;background:#4488ff;width:0%;transition:none;}
.modal{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.75);display:none;align-items:center;justify-content:center}
.modal-box{background:#2b2b2b;padding:18px;border:1px solid #999;border-radius:6px;width:340px;max-height:70vh;overflow-y:auto;font-size:12px}
.modal-box h3{margin-bottom:10px;font-size:16px}
.item-line{padding:4px 0;border-bottom:1px solid #444;font-size:12px}
input{width:100%;padding:5px;margin:5px 0;background:#1a1a1a;border:1px solid #666;color:#fff;border-radius:3px;font-size:12px}
.inv-row{display:flex;gap:4px;flex-wrap:wrap;margin:6px 0}
.inv-slot{width:42px;height:42px;background:#181818;border:1px solid #555;display:flex;align-items:center;justify-content:center;font-size:11px;position:relative}
.offhand{width:56px;height:56px;background:#181818;border:2px solid #888;margin:6px auto;display:flex;align-items:center;justify-content:center;font-size:12px}
.quality-common{color:#eee}
.quality-good{color:#5f5}
.quality-rare{color:#5af}
.quality-legend{color:#fa0}
.tip{position:fixed;bottom:80px;left:50%;transform:translateX(-50%);background:#111;padding:6px 12px;border:1px solid #888;border-radius:4px;display:none;font-size:12px}
#battleTip{margin-top:8px;color:#ff7777;font-size:12px}
.bottom-bar{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);display:flex;gap:5px;flex-wrap:wrap;justify-content:center;width:95%}
#mineFull{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000;display:none;flex-direction:column;align-items:center;justify-content:center;gap:20px}
.mine-rock{font-size:70px;display:none;}
.langBtn{position:fixed;bottom:12px;left:12px;padding:6px 10px;background:#333;color:#fff;border:1px solid #777;border-radius:4px;cursor:pointer}
</style>
</head>
<body>
<div id="home">
<h1 id="homeTitle">Minecraft RPG</h1>
<div style="display:flex;gap:10px">
<button class="btn" onclick="startGame()" id="btnStart">开始游戏</button>
<button class="btn" onclick="openRuleModal()" id="btnRule">规则</button>
</div>
</div>

<div id="game">
<div class="top-left">
<div><span id="txtGoldLabel">金币:</span><span id="gold">0</span></div>
<div><span id="txtIronLabel">铁矿:</span><span id="iron">0</span></div>
<div><span id="txtCoalLabel">煤炭:</span><span id="coal">0</span></div>
<div><span id="txtGemLabel">宝石:</span><span id="gem">0</span></div>
<div><span id="txtStoneLabel">石头:</span><span id="stone">0</span></div>
<div><span id="txtKillLabel">击杀普通怪:</span><span id="killCount">0</span>/15</div>
<div><span id="txtPlayerHpLabel">玩家生命:</span><span id="playerHp">10</span>/<span id="playerMaxHp">40</span></div>
</div>

<div class="battle-area">
<div class="monster-name" id="monsterName">🧟 僵尸</div>
<div class="hp-row"><span id="txtMonsterHpLabel">怪物生命:</span><span id="monsterHp">20</span>/<span id="monsterMaxHp">60</span></div>
<div class="bar-wrap">
<div class="bar-cd" id="cdBar"></div>
</div>
<div id="txtAtkCd" style="font-size:12px">攻击冷却</div>
<button class="btn" onclick="attack()" id="btnAtk">攻击</button>
<div id="battleTip"></div>
</div>

<div class="bottom-bar">
<button class="btn" onclick="openMinePage()" id="btnMine">矿场</button>
<button class="btn" onclick="openBag()" id="btnBag">背包</button>
<button class="btn" onclick="openOffhand()" id="btnOff">副手</button>
<button class="btn" style="display:none" onclick="openCraft()" id="btnCraft">工作台</button>
<button class="btn" onclick="openSaveLoad()" id="btnSave">存档/读档</button>
<button class="btn" onclick="fullscreenToggle()" id="btnFull">全荧幕</button>
</div>
</div>

<div id="mineFull">
<div id="mineTitle">正在前往矿场</div>
<div id="mineCountText">5</div>
<div class="mine-rock" id="rockEl">🪨</div>
<div class="bar-wrap" style="width:220px">
<div class="bar-cd" id="mineCdBar"></div>
</div>
<button class="btn" id="mineActBtn" onclick="doMining()" style="display:none">开采</button>
<button class="btn" id="mineBackBtn" onclick="closeMinePage()" style="display:none">返回冒险</button>
</div>

<div class="modal" id="ruleModal">
<div class="modal-box">
<h3 id="ruleTitle">Minecraft RPG 新手规则</h3>
<div id="ruleContent"></div>
<br>
<button class="btn" onclick="closeModal('ruleModal')" id="btnRuleClose">关闭</button>
</div>
</div>

<div class="modal" id="craftModal">
<div class="modal-box">
<h3 id="craftTitle">工作台</h3>
<div class="item-line"><span id="craftStoneSwordTxt">石剑:石头×2</span> <button class="btn" onclick="craft('stoneSword')">合成</button></div>
<div class="item-line"><span id="craftIronSwordTxt">铁剑:铁矿×2</span> <button class="btn" onclick="craft('ironSword')">合成</button></div>
<div class="item-line"><span id="craftDiamondSwordTxt">钻石剑:宝石×3</span> <button class="btn" onclick="craft('diamondSword')">合成</button></div>
<div class="item-line"><span id="craftShieldTxt">铁盾牌:铁矿×3</span> <button class="btn" onclick="craft('shield')">合成</button></div>
<div class="item-line"><span id="craftBreadTxt">面包:石头×1</span> <button class="btn" onclick="craft('bread')">合成</button></div>
<br>
<button class="btn" onclick="closeModal('craftModal')" id="btnCraftClose">关闭</button>
</div>
</div>

<div class="modal" id="bagModal">
<div class="modal-box">
<h3><span id="bagTitle">背包</span> (<span id="bagCount">0</span>/20)</h3>
<div class="inv-row" id="bagList"></div>
<br>
<button class="btn" onclick="closeModal('bagModal')" id="btnBagClose">关闭</button>
</div>
</div>

<div class="modal" id="offhandModal">
<div class="modal-box">
<h3 id="offTitle">副手栏</h3>
<div class="offhand" id="offhandSlot">空</div>
<div id="offhandList"></div>
<br>
<button class="btn" onclick="closeModal('offhandModal')" id="btnOffClose">关闭</button>
</div>
</div>

<div class="modal" id="saveModal">
<div class="modal-box">
<h3 id="saveTitle">存档 / 读档</h3>
<div id="saveCodeLabel">存档代码:</div>
<input id="saveCodeRead" readonly>
<button class="btn" onclick="saveGame()" id="btnGenSave">生成存档</button>
<div id="loadCodeLabel" style="margin-top:6px">读取存档:</div>
<input id="saveCodeWrite" placeholder="粘贴存档代码">
<button class="btn" onclick="loadGame()" id="btnLoadSave">读取</button>
<br><br>
<button class="btn" onclick="closeModal('saveModal')" id="btnSaveClose">关闭</button>
</div>
</div>

<div class="modal" id="unlockCraftModal">
<div class="modal-box">
<h3 id="unlockTitle">提示</h3>
<p id="unlockMsg">已收集10份铁矿,可以解锁工作台,是否解锁?</p>
<button class="btn" onclick="unlockCraft()" id="btnUnlockYes">解锁</button>
<button class="btn" onclick="closeModal('unlockCraftModal')" id="btnUnlockNo">暂不解锁</button>
</div>
</div>

<div class="tip" id="tipBox"></div>
<button class="langBtn" id="langToggle" onclick="switchLang()">ENG</button>

<script>
let lang = "zh";
const texts = {
    zh:{
        homeTitle:"Minecraft RPG",
        start:"开始游戏",
        rule:"规则",
        gold:"金币:",iron:"铁矿:",coal:"煤炭:",gem:"宝石:",stone:"石头:",
        killTxt:"击杀普通怪:",playerHp:"玩家生命:",
        monsterHp:"怪物生命:",atkCd:"攻击冷却",attack:"攻击",
        mine:"矿场",bag:"背包",off:"副手",craft:"工作台",save:"存档/读档",full:"全荧幕",
        mineTitle:"正在前往矿场",mineDig:"开采",mineBack:"返回冒险",
        ruleModalTitle:"Minecraft RPG 新手规则",
        ruleContent:`【游戏目标】<br>
击败怪物、采集矿物、收集材料合成装备,击杀15只普通怪物就会出现首领,由弱到强依次挑战。<br><br>
【基础操作】<br>
1. 点击「开始游戏」进入冒险画面<br>
2. 攻击:按攻击按钮打怪物,有攻击冷却时间,冷却条满先可以再次攻击<br>
3. 矿场:点矿场按钮,会倒数5秒,倒数完先可以开采石头<br>
4. 开采有冷却,每次开采完要等冷却完先可以再掘<br><br>
【采矿机制】<br>
- 石头:机率最高,掘到会获得金币<br>
- 煤炭:机率中等,掘到直接获得煤炭资源<br>
- 铁矿:机率最低,掘到直接获得铁矿<br>
- 储够10个铁矿,会弹提示解锁工作台<br><br>
【背包与合成】<br>
1. 背包最多可以存放20件物品<br>
2. 工作台解锁之后,可以使用矿物合成武器、盾牌、面包<br>
3. 面包、腐肉系食物,点击背包入面嘅食物可以回复血量<br>
4. 铁盾牌可以放去副手栏,受到攻击时减少伤害<br><br>
【战斗机制】<br>
1. 打怪物有机率出现暴击,造成更高伤害<br>
2. 有机率闪避怪物攻击,完全唔受伤<br>
3. 击败僵尸会随机掉落1-2块腐肉,有机率额外掉落其他道具<br>
4. 击杀普通怪物会累计击杀数,击杀满15只就会召唤首领<br>
5. 首领击败之后会切换下一只更强首领<br><br>
【存档功能】<br>
1. 点击「存档/读档」可以生成存档代码,复制保存<br>
2. 读取存档就粘贴存档代码,可以恢复游戏进度`,
        close:"关闭",
        craftTitle:"工作台",
        swordStone:"石剑:石头×2",
        swordIron:"铁剑:铁矿×2",
        swordDiamond:"钻石剑:宝石×3",
        shield:"铁盾牌:铁矿×3",
        bread:"面包:石头×1",
        bagTitle:"背包",
        offTitle:"副手栏",
        saveTitle:"存档 / 读档",
        saveCode:"存档代码:",genSave:"生成存档",
        loadCode:"读取存档:",loadSave:"读取",
        unlockTitle:"提示",unlockMsg:"已收集10份铁矿,可以解锁工作台,是否解锁?",
        unlockYes:"解锁",unlockNo:"暂不解锁",
        tipCd:"冷却未结束",tipCd2:"冷却中",tipCrit:"暴击!",tipDodge:"闪避成功",tipLose:"你战败了,怪物重置",
        tipCraftUnlock:"工作台已解锁",tipMatShort:"材料不足",tipBagFull:"背包已满",
        tipBoss:"首领出现!",tipSaveOk:"存档已生成,请复制代码",
        tipLoadOk:"读取存档成功",tipLoadErr:"存档代码错误",
        tipFullErr:"浏览器唔支援全荧幕",
        empty:"空",
        equip:"装备 "
    },
    en:{
        homeTitle:"Minecraft RPG",
        start:"Start Game",
        rule:"Rules",
        gold:"Gold: ",iron:"Iron: ",coal:"Coal: ",gem:"Gem: ",stone:"Stone: ",
        killTxt:"Kills: ",playerHp:"Player HP: ",
        monsterHp:"Monster HP: ",atkCd:"Attack Cooldown",attack:"Attack",
        mine:"Mine",bag:"Bag",off:"Offhand",craft:"Workbench",save:"Save/Load",full:"Fullscreen",
        mineTitle:"Heading to Mine",mineDig:"Mine",mineBack:"Back to Adventure",
        ruleModalTitle:"Minecraft RPG Beginner Rules",
        ruleContent:`【Game Goal】<br>
Defeat monsters, mine resources, craft gears. Kill 15 normal monsters to spawn boss, bosses get stronger sequentially.<br><br>
【Controls】<br>
1. Click "Start Game" to adventure<br>
2. Attack: Click attack button, cooldown required before next hit<br>
3. Mine: Enter mine, wait 5s countdown to mine<br>
4. Mining also has cooldown.<br><br>
【Mining】<br>
- Stone: Most common, gain gold<br>
- Coal: Medium chance, get coal resource<br>
- Iron: Rare chance, get iron<br>
- Collect 10 iron to unlock workbench<br><br>
【Bag & Craft】<br>
1. Bag capacity:20 items<br>
2. Craft weapons, shield and bread in workbench<br>
3. Bread & rotten flesh restore HP<br>
4. Iron shield to offhand for damage reduction<br><br>
【Combat】<br>
1. Critical hit deals extra damage<br>
2. Chance to dodge incoming attack<br>
3. Zombies drop 1~2 rotten flesh randomly<br>
4. Every 15 kills summon boss<br>
5. Defeat boss to unlock next stronger boss<br><br>
【Save System】<br>
1. Generate save code and copy it<br>
2. Paste code to load your progress`,
        close:"Close",
        craftTitle:"Workbench",
        swordStone:"Stone Sword: Stone×2",
        swordIron:"Iron Sword: Iron×2",
        swordDiamond:"Diamond Sword: Gem×3",
        shield:"Iron Shield: Iron×3",
        bread:"Bread: Stone×1",
        bagTitle:"Bag",
        offTitle:"Offhand Slot",
        saveTitle:"Save / Load",
        saveCode:"Save Code:",genSave:"Generate Save",
        loadCode:"Load Code:",loadSave:"Load",
        unlockTitle:"Notice",unlockMsg:"10 Iron collected. Unlock Workbench?",
        unlockYes:"Unlock",unlockNo:"Later",
        tipCd:"Cooldown not over",tipCd2:"Cooldown",tipCrit:"Critical Hit!",tipDodge:"Dodge!",tipLose:"Defeated, monster reset",
        tipCraftUnlock:"Workbench Unlocked",tipMatShort:"Not enough materials",tipBagFull:"Bag Full",
        tipBoss:"Boss appeared! ",tipSaveOk:"Save generated, copy code",
        tipLoadOk:"Load success",tipLoadErr:"Invalid save code",
        tipFullErr:"Fullscreen unsupported",
        empty:"Empty",
        equip:"Equip "
    }
}

let game = {
    gold:0, iron:0, coal:0, gem:0, stone:0,
    playerHp:10, playerMaxHp:40,
    bag:[], bagMax:20, offhand:null,
    craftUnlocked:false,
    killCount:0, bossIndex:0,
    monster:{name:"🧟 Zombie", hp:20, maxHp:60, atk:6, type:"zombie"},
    cd:false, cdTime:800,
    critRate:0.15, dodgeRate:0.12
}
const bosses = [
    {name:"Zombie King",hp:120,maxHp:120,atk:8},
    {name:"Creeper Overlord",hp:180,maxHp:180,atk:12},
    {name:"Wither Knight",hp:280,maxHp:280,atk:15},
    {name:"Ender Guardian",hp:400,maxHp:400,atk:20}
]
const quality = {zh:["普通","优良","稀有","传奇"],en:["Common","Fine","Rare","Legendary"]};
const qualityClass = ["quality-common","quality-good","quality-rare","quality-legend"];

function switchLang(){
    lang = lang === "zh" ? "en" : "zh";
    document.getElementById("langToggle").innerText = lang === "zh" ? "ENG" : "中";
    applyLang();
}
function applyLang(){
    const t = texts[lang];
    document.getElementById("homeTitle").innerText = t.homeTitle;
    document.getElementById("btnStart").innerText = t.start;
    document.getElementById("btnRule").innerText = t.rule;

    document.getElementById("txtGoldLabel").innerText = t.gold;
    document.getElementById("txtIronLabel").innerText = t.iron;
    document.getElementById("txtCoalLabel").innerText = t.coal;
    document.getElementById("txtGemLabel").innerText = t.gem;
    document.getElementById("txtStoneLabel").innerText = t.stone;
    document.getElementById("txtKillLabel").innerText = t.killTxt;
    document.getElementById("txtPlayerHpLabel").innerText = t.playerHp;
    document.getElementById("txtMonsterHpLabel").innerText = t.monsterHp;
    document.getElementById("txtAtkCd").innerText = t.atkCd;
    document.getElementById("btnAtk").innerText = t.attack;

    document.getElementById("btnMine").innerText = t.mine;
    document.getElementById("btnBag").innerText = t.bag;
    document.getElementById("btnOff").innerText = t.off;
    document.getElementById("btnCraft").innerText = t.craft;
    document.getElementById("btnSave").innerText = t.save;
    document.getElementById("btnFull").innerText = t.full;

    document.getElementById("mineTitle").innerText = t.mineTitle;
    document.getElementById("mineActBtn").innerText = t.mineDig;
    document.getElementById("mineBackBtn").innerText = t.mineBack;

    document.getElementById("ruleTitle").innerText = t.ruleModalTitle;
    document.getElementById("ruleContent").innerHTML = t.ruleContent;
    document.getElementById("btnRuleClose").innerText = t.close;

    document.getElementById("craftTitle").innerText = t.craftTitle;
    document.getElementById("craftStoneSwordTxt").innerText = t.swordStone;
    document.getElementById("craftIronSwordTxt").innerText = t.swordIron;
    document.getElementById("craftDiamondSwordTxt").innerText = t.swordDiamond;
    document.getElementById("craftShieldTxt").innerText = t.shield;
    document.getElementById("craftBreadTxt").innerText = t.bread;
    document.getElementById("btnCraftClose").innerText = t.close;

    document.getElementById("bagTitle").innerText = t.bagTitle;
    document.getElementById("btnBagClose").innerText = t.close;
    document.getElementById("offTitle").innerText = t.offTitle;
    document.getElementById("btnOffClose").innerText = t.close;

    document.getElementById("saveTitle").innerText = t.saveTitle;
    document.getElementById("saveCodeLabel").innerText = t.saveCode;
    document.getElementById("btnGenSave").innerText = t.genSave;
    document.getElementById("loadCodeLabel").innerText = t.loadCode;
    document.getElementById("btnLoadSave").innerText = t.loadSave;
    document.getElementById("btnSaveClose").innerText = t.close;

    document.getElementById("unlockTitle").innerText = t.unlockTitle;
    document.getElementById("unlockMsg").innerText = t.unlockMsg;
    document.getElementById("btnUnlockYes").innerText = t.unlockYes;
    document.getElementById("btnUnlockNo").innerText = t.unlockNo;

    spawnNormalMonster();
    refreshUI();
}

function openRuleModal(){openModal("ruleModal")}
function startGame(){
    document.getElementById("home").style.display="none";
    document.getElementById("game").style.display="block";
    refreshUI();
}
function showTip(text){
    const t = document.getElementById("tipBox");
    t.innerText=text;
    t.style.display="block";
    setTimeout(()=>t.style.display="none",1600);
}
function closeModal(id){document.getElementById(id).style.display="none"}
function openModal(id){document.getElementById(id).style.display="flex"}
function openBag(){renderBag();openModal("bagModal")}
function openOffhand(){renderOffhand();openModal("offhandModal")}
function openSaveLoad(){openModal("saveModal")}
function openCraft(){openModal("craftModal")}

function fullscreenToggle(){
    if (!document.fullscreenElement) {
        document.documentElement.requestFullscreen().catch(e=>showTip(texts[lang].tipFullErr));
    } else {
        if(document.exitFullscreen) document.exitFullscreen();
    }
}

function openMinePage(){
    document.getElementById("mineFull").style.display="flex";
    document.getElementById("mineTitle").innerText=texts[lang].mineTitle;
    document.getElementById("mineCountText").innerText="5";
    document.getElementById("rockEl").style.display="none";
    document.getElementById("mineActBtn").style.display="none";
    document.getElementById("mineBackBtn").style.display="none";
    document.getElementById("mineCdBar").style.width="0%";
    let count = 5;
    const countTimer = setInterval(()=>{
        document.getElementById("mineCountText").innerText = count;
        count--;
        if(count < 0){
            clearInterval(countTimer);
            document.getElementById("mineTitle").innerText="";
            document.getElementById("rockEl").style.display="block";
            document.getElementById("mineActBtn").style.display="inline-block";
            document.getElementById("mineBackBtn").style.display="inline-block";
        }
    },1000);
}
function closeMinePage(){
    document.getElementById("mineFull").style.display="none";
}
function doMining(){
    if(game.cd){showTip(texts[lang].tipCd);return;}
    game.cd=true;
    const mineTotalTime = 500;
    let elapsed = 0;
    const mineTxt = document.getElementById("mineCountText");
    const mineBtn = document.getElementById("mineActBtn");
    const mineBar = document.getElementById("mineCdBar");
    const rock = document.getElementById("rockEl");
    mineBtn.disabled=true;
    const mineInterval = setInterval(()=>{
        elapsed += 50;
        const percent = (elapsed/mineTotalTime)*100;
        mineBar.style.width = percent + "%";
        const remainSec = ((mineTotalTime-elapsed)/1000).toFixed(1);
        mineTxt.innerText = remainSec;
        if(elapsed >= mineTotalTime){
            clearInterval(mineInterval);
            const r = Math.random();
            if(r < 0.08){
                game.iron++;
                rock.innerText = "🪨";
            }else if(r < 0.25){
                game.coal++;
                rock.innerText = "⬛";
            }else{
                game.gold += 2;
                rock.innerText = "🪨";
            }
            mineTxt.innerText="0";
            mineBar.style.width="100%";
            mineBtn.disabled=false;
            game.cd=false;
            mineBar.style.width="0%";
            refreshUI();
            checkIronUnlock();
        }
    },50)
}
function checkIronUnlock(){
    if(game.iron>=10 && !game.craftUnlocked) openModal("unlockCraftModal");
}
function unlockCraft(){
    game.craftUnlocked=true;
    document.getElementById("btnCraft").style.display="flex";
    closeModal("unlockCraftModal");
    showTip(texts[lang].tipCraftUnlock);
    refreshUI();
}
function craft(id){
    const qLang = quality[lang];
    if(id==="stoneSword"){
        if(game.stone<2){showTip(texts[lang].tipMatShort);return}
        if(game.bag.length>=game.bagMax){showTip(texts[lang].tipBagFull);return}
        game.stone -=2;
        const q = Math.floor(Math.random()*4);
        game.bag.push({name:lang==="zh"?"石剑":"Stone Sword",type:"weapon",dmg:9,quality:qLang[q],color:qualityClass[q]})
    }else if(id==="ironSword"){
        if(game.iron<2){showTip(texts[lang].tipMatShort);return}
        if(game.bag.length>=game.bagMax){showTip(texts[lang].tipBagFull);return}
        game.iron -=2;
        const q = Math.floor(Math.random()*4);
        game.bag.push({name:lang==="zh"?"铁剑":"Iron Sword",type:"weapon",dmg:12,quality:qLang[q],color:qualityClass[q]})
    }else if(id==="diamondSword"){
        if(game.gem<3){showTip(texts[lang].tipMatShort);return}
        if(game.bag.length>=game.bagMax){showTip(texts[lang].tipBagFull);return}
        game.gem -=3;
        const q = Math.floor(Math.random()*4);
        game.bag.push({name:lang==="zh"?"钻石剑":"Diamond Sword",type:"weapon",dmg:18,quality:qLang[q],color:qualityClass[q]})
    }else if(id==="shield"){
        if(game.iron<3){showTip(texts[lang].tipMatShort);return}
        if(game.bag.length>=game.bagMax){showTip(texts[lang].tipBagFull);return}
        game.iron -=3;
        game.bag.push({name:lang==="zh"?"铁盾牌":"Iron Shield",type:"shield",reduce:0.3})
    }else if(id==="bread"){
        if(game.stone<1){showTip(texts[lang].tipMatShort);return}
        if(game.bag.length>=game.bagMax){showTip(texts[lang].tipBagFull);return}
        game.stone -=1;
        game.bag.push({name:lang==="zh"?"面包":"Bread",type:"food",heal:15})
    }
    refreshUI();renderBag();
}
function renderBag(){
    const wrap = document.getElementById("bagList");
    wrap.innerHTML="";
    document.getElementById("bagCount").innerText=game.bag.length;
    game.bag.forEach((it,i)=>{
        const div = document.createElement("div");
        div.className="inv-slot "+(it.color||"");
        div.innerText=it.name;
        div.onclick=()=>useItem(i);
        wrap.appendChild(div);
    })
}
function renderOffhand(){
    document.getElementById("offhandSlot").innerText = game.offhand?.name??texts[lang].empty;
    const list = document.getElementById("offhandList");
    list.innerHTML="";
    game.bag.forEach((it,i)=>{
        if(it.type==="shield"){
            const btn = document.createElement("button");
            btn.className="btn";
            btn.innerText=texts[lang].equip+it.name;
            btn.onclick=()=>{
                game.offhand = it;
                game.bag.splice(i,1);
                renderOffhand();refreshUI();
            }
            list.appendChild(btn);
        }
    })
}
function useItem(idx){
    const it = game.bag[idx];
    if(it.type==="food"){
        game.playerHp = Math.min(game.playerHp + it.heal, game.playerMaxHp);
        game.bag.splice(idx,1);
    }
    refreshUI();renderBag();
}

function attack(){
    if(game.cd){showTip(texts[lang].tipCd2);return}
    game.cd=true;
    let elapsed=0;
    const bar = document.getElementById("cdBar");
    const interval = setInterval(()=>{
        elapsed += 50;
        const pct = (elapsed/game.cdTime)*100;
        bar.style.width = pct+"%";
        if(elapsed>=game.cdTime){
            clearInterval(interval);
            game.cd=false;
            bar.style.width="0%";
            refreshUI();
        }
    },50)
    let dmg = 8;
    if(Math.random() < game.critRate){dmg *=1.5;showTip(texts[lang].tipCrit)}
    game.monster.hp -= dmg;
    document.getElementById("battleTip").innerText = (lang==="zh"?"造成 ":"Hit ")+Math.round(dmg)+(lang==="zh"?" 点伤害":" damage");
    if(game.monster.hp <=0){killMonster()}else{monsterAttack()}
    refreshUI();
}

function monsterAttack(){
    if(Math.random() < game.dodgeRate){showTip(texts[lang].tipDodge);return}
    let md = game.monster.atk;
    if(game.offhand?.type==="shield") md = md*(1-game.offhand.reduce);
    game.playerHp -= md;
    if(game.playerHp <=0){
        game.playerHp=0;
        showTip(texts[lang].tipLose);
        spawnNormalMonster();
    }
    refreshUI();
}
function killMonster(){
    const m = game.monster;
    const meatName = lang==="zh"?"腐肉":"Rotten Flesh";
    if(m.name.includes("僵尸")||m.name.includes("Zombie")){
        const meat = {name:meatName,type:"food",heal:5};
        for(let i=0;i<Math.floor(Math.random()*2)+1;i++){
            if(game.bag.length<game.bagMax) game.bag.push(meat);
        }
    }
    if(m.name.includes("苦力怕")||m.name.includes("Creeper")){
        const gunPowder = lang==="zh"?"火药":"Gunpowder";
        if(game.bag.length<game.bagMax) game.bag.push({name:gunPowder});
    }
    if(!m.name.includes("王") && !m.name.includes("霸主") && !m.name.includes("骑士") && !m.name.includes("守卫")
    && !m.name.includes("King") && !m.name.includes("Overlord") && !m.name.includes("Knight") && !m.name.includes("Guardian")){
        game.killCount++;
        if(game.killCount>=15){
            spawnBoss();
            game.killCount=0;
        }else spawnNormalMonster();
    }else{
        game.bossIndex++;
        if(game.bossIndex >= bosses.length) game.bossIndex=0;
        spawnNormalMonster();
    }
    refreshUI();
}
function spawnNormalMonster(){
    const r=Math.random();
    if(r<0.4) game.monster={name:lang==="zh"?"🧟 僵尸":"🧟 Zombie",hp:60,maxHp:60,atk:6,type:"zombie"};
    else if(r<0.7) game.monster={name:lang==="zh"?"👶 小僵尸":"👶 Baby Zombie",hp:35,maxHp:35,atk:4,type:"babyZombie"};
    else game.monster={name:lang==="zh"?"💥 苦力怕":"💥 Creeper",hp:50,maxHp:50,atk:9,type:"creeper"};
}
function spawnBoss(){
    const b = bosses[game.bossIndex];
    game.monster = {...b, type:"boss"};
    showTip(texts[lang].tipBoss+b.name);
}
function saveGame(){
    const jsonStr = JSON.stringify(game);
    const utf8 = unescape(encodeURIComponent(jsonStr));
    const code = btoa(utf8);
    document.getElementById("saveCodeRead").value = code;
    showTip(texts[lang].tipSaveOk);
}
function loadGame(){
    const code = document.getElementById("saveCodeWrite").value.trim();
    try{
        const utf8 = atob(code);
        const jsonStr = decodeURIComponent(escape(utf8));
        game = JSON.parse(jsonStr);
        if(game.craftUnlocked) document.getElementById("btnCraft").style.display="flex";
        showTip(texts[lang].tipLoadOk);
        applyLang();
    }catch(e){
        showTip(texts[lang].tipLoadErr);
    }
}
function refreshUI(){
    document.getElementById("gold").innerText=game.gold;
    document.getElementById("iron").innerText=game.iron;
    document.getElementById("coal").innerText=game.coal;
    document.getElementById("gem").innerText=game.gem;
    document.getElementById("stone").innerText=game.stone;
    document.getElementById("killCount").innerText=game.killCount;
    document.getElementById("playerHp").innerText=game.playerHp;
    document.getElementById("playerMaxHp").innerText=game.playerMaxHp;
    document.getElementById("monsterName").innerText=game.monster.name;
    document.getElementById("monsterHp").innerText=game.monster.hp;
    document.getElementById("monsterMaxHp").innerText=game.monster.maxHp;
}
// 作弊码
document.addEventListener("keydown",(e)=>{
    window.codeInput = window.codeInput || "";
    window.codeInput += e.key;
    if(window.codeInput.includes("!!!gsf801005!!!")){
        game.craftUnlocked=true;
        game.gold +=999;
        game.iron +=999;
        game.coal +=999;
        game.gem +=999;
        game.stone +=999;
        document.getElementById("btnCraft").style.display="flex";
        showTip(lang==="zh"?"已解锁全部内容!":"Everything Unlocked!");
        window.codeInput="";
    }
    if(window.codeInput.length>30) window.codeInput="";
})
applyLang();
</script>
</body>
</html>

Game Source: Minecraft RPG

Creator: SparkShark50

Libraries: none

Complexity: complex (664 lines, 29.0 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: minecraft-rpg-sparkshark50-mvvt4dh4" to link back to the original. Then publish at arcadelab.ai/publish.