Minecraft RPG
by SparkShark50489 lines19.0 KB
<!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:320px;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;}
</style>
</head>
<body>
<div id="home">
<h1>Minecraft RPG</h1>
<button class="btn" onclick="startGame()">开始游戏</button>
</div>
<div id="game">
<div class="top-left">
<div>金币:<span id="gold">0</span></div>
<div>铁矿:<span id="iron">0</span></div>
<div>煤炭:<span id="coal">0</span></div>
<div>宝石:<span id="gem">0</span></div>
<div>石头:<span id="stone">0</span></div>
<div>击杀普通怪:<span id="killCount">0</span>/15</div>
<div>玩家生命:<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="monsterHp">20</span>/<span id="monsterMaxHp">60</span></div>
<div class="bar-wrap">
<div class="bar-cd" id="cdBar"></div>
</div>
<div style="font-size:12px">攻击冷却</div>
<button class="btn" onclick="attack()">攻击</button>
<div id="battleTip"></div>
</div>
<div class="bottom-bar">
<button class="btn" onclick="openMinePage()">矿场</button>
<button class="btn" onclick="openBag()">背包</button>
<button class="btn" onclick="openOffhand()">副手</button>
<button class="btn" id="craftBtn" style="display:none" onclick="openCraft()">工作台</button>
<button class="btn" onclick="openSaveLoad()">存档/读档</button>
<button class="btn" onclick="fullscreenToggle()">全荧幕</button>
<button class="btn" onclick="closeUI()">关闭UI</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="craftModal">
<div class="modal-box">
<h3>工作台</h3>
<div class="item-line">石剑:石头×2 <button class="btn" onclick="craft('stoneSword')">合成</button></div>
<div class="item-line">铁剑:铁矿×2 <button class="btn" onclick="craft('ironSword')">合成</button></div>
<div class="item-line">钻石剑:宝石×3 <button class="btn" onclick="craft('diamondSword')">合成</button></div>
<div class="item-line">铁盾牌:铁矿×3 <button class="btn" onclick="craft('shield')">合成</button></div>
<div class="item-line">面包:石头×1 <button class="btn" onclick="craft('bread')">合成</button></div>
<br>
<button class="btn" onclick="closeModal('craftModal')">关闭</button>
</div>
</div>
<div class="modal" id="bagModal">
<div class="modal-box">
<h3>背包 (<span id="bagCount">0</span>/20)</h3>
<div class="inv-row" id="bagList"></div>
<br>
<button class="btn" onclick="closeModal('bagModal')">关闭</button>
</div>
</div>
<div class="modal" id="offhandModal">
<div class="modal-box">
<h3>副手栏</h3>
<div class="offhand" id="offhandSlot">空</div>
<div id="offhandList"></div>
<br>
<button class="btn" onclick="closeModal('offhandModal')">关闭</button>
</div>
</div>
<div class="modal" id="saveModal">
<div class="modal-box">
<h3>存档 / 读档</h3>
<div>存档代码:</div>
<input id="saveCodeRead" readonly>
<button class="btn" onclick="saveGame()">生成存档</button>
<div style="margin-top:6px">读取存档:</div>
<input id="saveCodeWrite" placeholder="粘贴存档代码">
<button class="btn" onclick="loadGame()">读取</button>
<br><br>
<button class="btn" onclick="closeModal('saveModal')">关闭</button>
</div>
</div>
<div class="modal" id="unlockCraftModal">
<div class="modal-box">
<h3>提示</h3>
<p>已收集10份铁矿,可以解锁工作台,是否解锁?</p>
<button class="btn" onclick="unlockCraft()">解锁</button>
<button class="btn" onclick="closeModal('unlockCraftModal')">暂不解锁</button>
</div>
</div>
<div class="tip" id="tipBox"></div>
<script>
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:"🧟 僵尸", hp:20, maxHp:60, atk:6, type:"zombie"},
cd:false, cdTime:800, //攻击冷却0.8秒
critRate:0.15, dodgeRate:0.12
}
const bosses = [
{name:"僵尸王",hp:120,maxHp:120,atk:8},
{name:"苦力怕霸主",hp:180,maxHp:180,atk:12},
{name:"凋灵骑士",hp:280,maxHp:280,atk:15},
{name:"末影守卫",hp:400,maxHp:400,atk:20}
]
const quality = ["普通","优良","稀有","传奇"];
const qualityClass = ["quality-common","quality-good","quality-rare","quality-legend"];
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")}
// 關閉UI按鈕
function closeUI(){
const g = document.getElementById("game");
if(g.style.opacity === "0"){
g.style.opacity = "1";
}else{
g.style.opacity = "0";
}
}
// 全螢幕
function fullscreenToggle(){
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen().catch(e=>showTip("瀏覽器唔支援全荧幕"));
} else {
if(document.exitFullscreen) document.exitFullscreen();
}
}
function openMinePage(){
document.getElementById("mineFull").style.display="flex";
document.getElementById("mineTitle").innerText="正在前往矿场";
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("冷却未结束");return;}
game.cd=true;
const mineTotalTime = 500; //采矿0.5秒
let elapsed = 0;
const mineTxt = document.getElementById("mineCountText");
const mineBtn = document.getElementById("mineActBtn");
const mineBar = document.getElementById("mineCdBar");
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.3)game.iron++;
else if(r<0.5)game.coal++;
else game.stone++;
mineTxt.innerText="0";
mineBar.style.width="100%";
mineBtn.disabled=false;
// 0完即刻解除冷卻,唔再有額外延遲
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("craftBtn").style.display="flex";
closeModal("unlockCraftModal");
showTip("工作台已解锁");
refreshUI();
}
function craft(id){
if(id==="stoneSword"){
if(game.stone<2){showTip("材料不足");return}
if(game.bag.length>=game.bagMax){showTip("背包已满");return}
game.stone -=2;
const q = Math.floor(Math.random()*4);
game.bag.push({name:"石剑",type:"weapon",dmg:9,quality:quality[q],color:qualityClass[q]})
}else if(id==="ironSword"){
if(game.iron<2){showTip("材料不足");return}
if(game.bag.length>=game.bagMax){showTip("背包已满");return}
game.iron -=2;
const q = Math.floor(Math.random()*4);
game.bag.push({name:"铁剑",type:"weapon",dmg:12,quality:quality[q],color:qualityClass[q]})
}else if(id==="diamondSword"){
if(game.gem<3){showTip("材料不足");return}
if(game.bag.length>=game.bagMax){showTip("背包已满");return}
game.gem -=3;
const q = Math.floor(Math.random()*4);
game.bag.push({name:"钻石剑",type:"weapon",dmg:18,quality:quality[q],color:qualityClass[q]})
}else if(id==="shield"){
if(game.iron<3){showTip("材料不足");return}
if(game.bag.length>=game.bagMax){showTip("背包已满");return}
game.iron -=3;
game.bag.push({name:"铁盾牌",type:"shield",reduce:0.3})
}else if(id==="bread"){
if(game.stone<1){showTip("材料不足");return}
if(game.bag.length>=game.bagMax){showTip("背包已满");return}
game.stone -=1;
game.bag.push({name:"面包",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??"空";
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="装备"+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.name==="面包"){
game.playerHp = Math.min(game.playerHp + it.heal, game.playerMaxHp);
game.bag.splice(idx,1);
}
refreshUI();renderBag();
}
function attack(){
if(game.cd){showTip("冷却中");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("暴击!")}
game.monster.hp -= dmg;
document.getElementById("battleTip").innerText = "造成 "+Math.round(dmg)+" 点伤害";
if(game.monster.hp <=0){killMonster()}else{monsterAttack()}
refreshUI();
}
function monsterAttack(){
if(Math.random() < game.dodgeRate){showTip("闪避成功");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("你战败了,怪物重置");
spawnNormalMonster();
}
refreshUI();
}
function killMonster(){
const m = game.monster;
if(m.name.includes("僵尸")){
const meat = {name:"腐肉",type:"food"};
for(let i=0;i<Math.floor(Math.random()*2)+1;i++){
if(game.bag.length<game.bagMax) game.bag.push(meat);
}
const extra = [{name:"面包",type:"food",heal:15},{name:"箭"},{name:"附魔簿"},{name:"煤炭"}];
if(Math.random()<0.35 && game.bag.length<game.bagMax){
game.bag.push(extra[Math.floor(Math.random()*extra.length)]);
}
}
if(m.name==="【苦力怕】"){
if(game.bag.length<game.bagMax) game.bag.push({name:"火药"});
}
if(!m.name.includes("王") && !m.name.includes("霸主") && !m.name.includes("骑士") && !m.name.includes("守卫")){
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:"🧟 僵尸",hp:60,maxHp:60,atk:6,type:"zombie"};
else if(r<0.7) game.monster={name:"👶 小僵尸",hp:35,maxHp:35,atk:4,type:"babyZombie"};
else game.monster={name:"💥 苦力怕",hp:50,maxHp:50,atk:9,type:"creeper"};
}
function spawnBoss(){
const b = bosses[game.bossIndex];
game.monster = {...b, type:"boss"};
showTip("首领出现!"+b.name);
}
//修復存檔
function saveGame(){
const jsonStr = JSON.stringify(game);
const utf8 = unescape(encodeURIComponent(jsonStr));
const code = btoa(utf8);
document.getElementById("saveCodeRead").value = code;
showTip("存档已生成,请复制代码");
}
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("craftBtn").style.display="flex";
showTip("读取存档成功");
refreshUI();
}catch(e){showTip("存档代码错误")}
}
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=Math.max(0,game.playerHp.toFixed(1));
document.getElementById("playerMaxHp").innerText=game.playerMaxHp;
document.getElementById("monsterName").innerText=game.monster.name;
document.getElementById("monsterHp").innerText=Math.max(0,game.monster.hp.toFixed(1));
document.getElementById("monsterMaxHp").innerText=game.monster.maxHp;
}
refreshUI();
//========== 作弊碼 放最底呢度 ==========
//輸入指令,按Enter觸發
document.addEventListener("keydown",(e)=>{
if(e.key === "Enter"){
const cmd = prompt("輸入作弊碼:");
if(!cmd) return;
switch(cmd.trim()){
case "hp":
game.playerHp = game.playerMaxHp;
showTip("✅ 玩家血量補滿");
refreshUI();
break;
case "mine":
game.stone +=50;game.iron+=20;game.coal+=20;game.gem+=5;
showTip("✅ 礦物+50石、20鐵、20煤、5寶石");
refreshUI();
break;
case "gold":
game.gold += 1000;
showTip("✅ 金幣+1000");
refreshUI();
break;
case "kill":
game.monster.hp = 0;
killMonster();
showTip("✅ 擊殺當前怪物");
break;
case "unlockcraft":
game.craftUnlocked=true;
document.getElementById("craftBtn").style.display="flex";
showTip("✅ 解鎖工作台");
refreshUI();
break;
default:
showTip("❌ 未知指令");
}
}
})
</script>
</body>
</html>Game Source: Minecraft RPG
Creator: SparkShark50
Libraries: none
Complexity: complex (489 lines, 19.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" to link back to the original. Then publish at arcadelab.ai/publish.