Battle Realms
by FrozenOtter311241 lines61.1 KB
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Battle Realms</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Heebo:wght@400;700;900&display=swap');
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
body{font-family:'Heebo',sans-serif;background:#1a0f2e;color:#fff;min-height:100vh;overflow:hidden}
.screen{display:none;width:100%;height:100vh;overflow:hidden;position:relative}
.screen.active{display:flex;flex-direction:column}
#menuScreen{justify-content:center;align-items:center;text-align:center;padding:20px}
#menuScreen h1{font-size:3rem;font-weight:900;background:linear-gradient(90deg,#ffd700,#ff8c00,#ffd700);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:8px}
.subtitle{color:#b8a8d8;font-size:1.1rem;margin-bottom:30px}
.stats-row{display:flex;gap:20px;margin-bottom:30px;flex-wrap:wrap;justify-content:center}
.stat-pill{background:rgba(255,255,255,0.08);border:1px solid rgba(255,215,0,0.3);border-radius:16px;padding:12px 24px}
.stat-pill .lbl{color:#b8a8d8;font-size:0.8rem}
.stat-pill .val{font-size:1.5rem;font-weight:700;color:#ffd700}
.btn{padding:14px 40px;font-size:1.2rem;font-weight:700;border:none;border-radius:14px;cursor:pointer;transition:all 0.2s;font-family:'Heebo',sans-serif;min-width:260px;margin:6px 0}
.btn-gold{background:linear-gradient(135deg,#ffd700,#ff8c00);color:#1a0f2e;box-shadow:0 4px 20px rgba(255,140,0,0.4)}
.btn-gold:active{transform:scale(0.96)}
.btn-dark{background:rgba(255,255,255,0.1);color:#fff;border:1px solid rgba(255,255,255,0.2)}
.btn-red{background:linear-gradient(135deg,#ff4444,#cc0000);color:#fff}
.back-btn{position:absolute;top:10px;right:10px;z-index:200;padding:8px 16px;background:rgba(255,255,255,0.15);border:1px solid rgba(255,255,255,0.3);border-radius:10px;color:#fff;cursor:pointer;font-family:'Heebo',sans-serif;font-weight:700;font-size:0.9rem}
.back-btn:active{background:rgba(255,255,255,0.25)}
#deckScreen,#mapScreen,#collectionScreen,#trainingScreen,#leaderboardScreen,#rewardsScreen{padding:20px;overflow-y:auto}
.screen-title{text-align:center;font-size:1.6rem;margin-bottom:15px;margin-top:40px}
.deck-count{text-align:center;color:#b8a8d8;margin-bottom:15px}
.selected-row{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:20px}
.sel-slot{width:60px;height:60px;border-radius:10px;background:rgba(255,215,0,0.15);border:2px solid #ffd700;display:flex;align-items:center;justify-content:center;font-size:1.8rem}
.sel-slot.empty{background:rgba(255,255,255,0.05);border-color:rgba(255,255,255,0.15);color:rgba(255,255,255,0.3)}
.char-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;max-width:500px;margin:0 auto 20px}
.char-cell{background:rgba(255,255,255,0.06);border:2px solid rgba(255,255,255,0.1);border-radius:12px;padding:10px 5px;text-align:center;cursor:pointer;position:relative;transition:all 0.2s}
.char-cell:active{transform:scale(0.95)}
.char-cell.picked{border-color:#ffd700;background:rgba(255,215,0,0.15)}
.char-cell.locked{opacity:0.35;pointer-events:none}
.char-cell .c-icon{font-size:2rem}
.char-cell .c-name{font-size:0.75rem;font-weight:700;margin-top:3px}
.char-cell .c-info{font-size:0.65rem;color:#b8a8d8;line-height:1.5}
.char-cell .c-lvl{position:absolute;top:3px;right:3px;background:#ffd700;color:#1a0f2e;font-size:0.6rem;font-weight:700;padding:1px 5px;border-radius:5px}
.char-cell .c-lock{position:absolute;top:3px;left:3px;background:#ff4444;color:#fff;font-size:0.55rem;padding:1px 5px;border-radius:5px}
.map-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;max-width:400px;margin:0 auto 20px}
.map-cell{aspect-ratio:16/10;border-radius:14px;display:flex;flex-direction:column;align-items:center;justify-content:center;border:2px solid rgba(255,255,255,0.15);cursor:pointer;transition:all 0.2s}
.map-cell:active{transform:scale(0.95)}
.map-cell.chosen{border-color:#ffd700;box-shadow:0 0 20px rgba(255,215,0,0.3)}
.map-cell .m-emoji{font-size:2rem}
.map-cell .m-name{font-size:0.8rem;font-weight:700;margin-top:4px;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,0.5)}
#gameScreen{padding:0}
.game-hud{display:flex;justify-content:space-between;align-items:center;padding:8px 15px;background:rgba(0,0,0,0.5);z-index:100;position:relative}
.hud-side{text-align:center}
.hud-side .h-num{font-size:1.3rem;font-weight:700}
.hud-side .h-lbl{font-size:0.6rem;color:#aaa}
.hud-timer{font-size:1.4rem;font-weight:700;color:#ffd700}
.arena{flex:1;position:relative;overflow:hidden;background:linear-gradient(180deg,#4a7c59,#3d6b4a,#2d5a3a)}
.arena-river{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:40px;background:linear-gradient(180deg,#4a90d9,#357abd,#4a90d9);border-top:2px solid rgba(255,255,255,0.3);border-bottom:2px solid rgba(255,255,255,0.3);z-index:5}
.arena-bridge{position:absolute;width:50px;height:50px;background:linear-gradient(180deg,#8B7355,#6B5344);border:2px solid #5a4335;border-radius:8px;top:50%;transform:translateY(-50%);z-index:6}
.arena-bridge.left{left:25%}
.arena-bridge.right{right:25%}
.scenery{position:absolute;pointer-events:none;z-index:1;user-select:none;text-shadow:0 2px 8px rgba(0,0,0,0.3)}
.tower{position:absolute;width:55px;height:65px;border-radius:10px;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:20;border:3px solid;transition:all 0.3s;box-shadow:0 4px 15px rgba(0,0,0,0.5)}
.tower .t-icon{font-size:1.6rem}
.tower .t-hp{font-size:0.65rem;font-weight:700}
.tower.player{border-color:#4CAF50;background:rgba(76,175,80,0.4)}
.tower.bot{border-color:#f44336;background:rgba(244,67,54,0.4)}
.tower.inactive{opacity:0.4;filter:grayscale(0.7)}
.tower.destroyed{opacity:0.2;filter:grayscale(1)}
.tower.princess-left{left:5%}
.tower.princess-right{right:5%}
.tower.king{left:50%;transform:translateX(-50%);width:65px;height:75px}
.tower.bot-side{top:8%}
.tower.player-side{bottom:8%}
.unit{position:absolute;width:42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.4rem;border:2px solid;z-index:30;transition:transform 0.1s;box-shadow:0 2px 8px rgba(0,0,0,0.4)}
.unit.player{border-color:#4CAF50;background:rgba(76,175,80,0.5)}
.unit.bot{border-color:#f44336;background:rgba(244,67,54,0.5)}
.unit-hp-bg{position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:36px;height:4px;background:rgba(0,0,0,0.6);border-radius:2px;overflow:hidden}
.unit-hp-fg{height:100%;background:#4CAF50;border-radius:2px;transition:width 0.2s}
.dmg-pop{position:absolute;top:-18px;font-weight:900;font-size:0.75rem;color:#ff4444;animation:popUp 0.8s forwards;pointer-events:none}
@keyframes popUp{0%{opacity:1;transform:translateY(0)scale(1)}100%{opacity:0;transform:translateY(-25px)scale(1.3)}}
.tower-shot{position:absolute;width:10px;height:10px;border-radius:50%;z-index:35;pointer-events:none;animation:shotFly 0.3s forwards}
@keyframes shotFly{0%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(0.5)}}
.hand-bar{display:flex;justify-content:center;gap:8px;padding:10px;background:rgba(0,0,0,0.6);z-index:100;position:relative}
.hand-card{width:70px;height:90px;border-radius:12px;background:linear-gradient(180deg,rgba(255,255,255,0.12),rgba(255,255,255,0.05));border:2px solid rgba(255,255,255,0.2);display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;position:relative;transition:all 0.2s}
.hand-card:active{transform:scale(0.92)}
.hand-card.selected{border-color:#ffd700;box-shadow:0 0 15px rgba(255,215,0,0.4);transform:translateY(-5px)}
.hand-card.disabled{opacity:0.35;pointer-events:none}
.hand-card .hc-cost{position:absolute;top:-8px;right:-8px;width:22px;height:22px;background:linear-gradient(135deg,#9C27B0,#E91E63);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.7rem;font-weight:700;border:2px solid #fff}
.hand-card .hc-icon{font-size:1.6rem}
.hand-card .hc-name{font-size:0.6rem;margin-top:2px;font-weight:700}
.elixir-bar{height:14px;background:rgba(0,0,0,0.4);border-radius:7px;margin:0 15px 8px;overflow:hidden;position:relative}
.elixir-fill{height:100%;background:linear-gradient(90deg,#E91E63,#9C27B0,#E91E63);border-radius:7px;transition:width 0.3s}
.elixir-text{text-align:center;font-size:0.8rem;color:#E91E63;font-weight:700;margin-bottom:5px}
.placement-ghost{position:absolute;width:40px;height:40px;border-radius:50%;border:3px dashed #ffd700;background:rgba(255,215,0,0.2);pointer-events:none;z-index:50;display:none;animation:ghostPulse 1s infinite}
@keyframes ghostPulse{0%,100%{opacity:0.6}50%{opacity:1}}
.result-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.85);display:none;align-items:center;justify-content:center;z-index:1000}
.result-overlay.on{display:flex}
.result-box{background:linear-gradient(135deg,#2d1b4e,#1a0f2e);border:2px solid #ffd700;border-radius:24px;padding:35px;text-align:center;max-width:400px;width:90%}
.result-box .rtitle{font-size:2.2rem;font-weight:900;margin-bottom:15px}
.result-box .rtitle.win{color:#4CAF50}
.result-box .rtitle.lose{color:#f44336}
.result-box .rtitle.draw{color:#ffd700}
.r-reward{font-size:1.1rem;margin:6px 0}
.r-reward b{color:#ffd700}
.toast{position:fixed;top:15px;left:50%;transform:translateX(-50%) translateY(-80px);background:rgba(0,0,0,0.9);border:1px solid #ffd700;border-radius:12px;padding:12px 25px;font-weight:700;z-index:3000;transition:transform 0.4s;font-size:0.9rem}
.toast.show{transform:translateX(-50%) translateY(0)}
.upgrade-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;max-width:500px;margin:0 auto}
.up-card{background:rgba(255,255,255,0.06);border:2px solid rgba(255,255,255,0.1);border-radius:12px;padding:12px;text-align:center}
.up-card .up-icon{font-size:2rem}
.up-card .up-name{font-size:0.85rem;font-weight:700}
.up-card .up-stat{font-size:0.7rem;color:#b8a8d8}
.up-btn{padding:6px 14px;border:none;border-radius:8px;font-weight:700;font-family:'Heebo',sans-serif;font-size:0.8rem;cursor:pointer;background:linear-gradient(135deg,#ffd700,#ff8c00);color:#1a0f2e;margin-top:6px}
.up-btn:disabled{background:#444;color:#777}
.up-max{color:#4CAF50;font-size:0.8rem;font-weight:700;margin-top:6px}
.lb-table{width:100%;max-width:400px;margin:0 auto;border-collapse:collapse}
.lb-table th,.lb-table td{padding:12px;text-align:center;border-bottom:1px solid rgba(255,255,255,0.1)}
.lb-table th{color:#ffd700;font-size:0.9rem}
.lb-table td{font-size:1rem}
.lb-table tr:nth-child(1) td{color:#ffd700;font-weight:900;font-size:1.2rem}
.lb-table tr:nth-child(2) td{color:#c0c0c0;font-weight:700}
.lb-table tr:nth-child(3) td{color:#cd7f32;font-weight:700}
.lb-rank{width:40px}
.rewards-btn{position:fixed;bottom:20px;left:20px;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#ffd700,#ff8c00);color:#1a0f2e;border:3px solid #fff;box-shadow:0 4px 20px rgba(255,140,0,0.6);display:flex;align-items:center;justify-content:center;font-size:1.8rem;cursor:pointer;z-index:4000;animation:rewardPulse 2s infinite}
.rewards-btn:active{transform:scale(0.92)}
.rewards-btn.has-new::after{content:"";position:absolute;top:-2px;right:-2px;width:16px;height:16px;background:#f44336;border-radius:50%;border:2px solid #1a0f2e}
@keyframes rewardPulse{0%,100%{box-shadow:0 4px 20px rgba(255,140,0,0.6)}50%{box-shadow:0 4px 30px rgba(255,215,0,0.9)}}
.rewards-grid{display:grid;grid-template-columns:repeat(1,1fr);gap:12px;max-width:400px;margin:0 auto}
.reward-item{background:rgba(255,255,255,0.06);border:2px solid rgba(255,255,255,0.1);border-radius:14px;padding:16px;display:flex;align-items:center;gap:15px;position:relative;transition:all 0.2s}
.reward-item.available{border-color:#ffd700;background:rgba(255,215,0,0.1);animation:glowPulse 1.5s infinite;cursor:pointer}
.reward-item.available:active{transform:scale(0.98)}
.reward-item.claimed{border-color:#4CAF50;background:rgba(76,175,80,0.08);opacity:0.7}
.reward-item.locked{border-color:rgba(255,255,255,0.1);opacity:0.4}
@keyframes glowPulse{0%,100%{box-shadow:0 0 8px rgba(255,215,0,0.2)}50%{box-shadow:0 0 20px rgba(255,215,0,0.5)}}
.reward-icon{font-size:2.5rem;width:50px;text-align:center}
.reward-info{flex:1}
.reward-title{font-size:1rem;font-weight:700}
.reward-desc{font-size:0.8rem;color:#b8a8d8}
.reward-trophy{font-size:0.75rem;color:#ffd700;margin-top:2px}
.reward-check{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:28px;height:28px;background:#4CAF50;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1rem;color:#fff}
.chest-overlay{position:fixed;inset:0;background:rgba(10,5,20,0.95);display:none;align-items:center;justify-content:center;z-index:5000}
.chest-overlay.on{display:flex}
.chest-box{background:linear-gradient(180deg,#1a0f2e,#0d0618);border:2px solid rgba(255,215,0,0.3);border-radius:20px;padding:30px 20px;text-align:center;max-width:360px;width:90%;animation:chestPop 0.5s ease-out;position:relative}
@keyframes chestPop{0%{transform:scale(0.6);opacity:0}100%{transform:scale(1);opacity:1}}
.chest-title{font-size:1.6rem;font-weight:900;color:#ffd700;margin-bottom:6px;text-shadow:0 2px 10px rgba(255,215,0,0.3)}
.chest-sub{font-size:0.95rem;color:#888;margin-bottom:20px}
.chest-visual{position:relative;width:220px;height:180px;margin:0 auto 20px;cursor:pointer}
.chest-lid{position:absolute;top:0;left:10px;width:200px;height:70px;background:linear-gradient(180deg,#8B4513,#654321);border-radius:100px 100px 0 0;border:3px solid #DAA520;z-index:2;transition:transform 0.4s;transform-origin:bottom center}
.chest-lid.open{transform:rotateX(-110deg)}
.chest-lid-stripe{position:absolute;bottom:5px;left:0;right:0;height:8px;background:linear-gradient(90deg,transparent,#ffd700,transparent)}
.chest-lock{position:absolute;bottom:-12px;left:50%;transform:translateX(-50%);width:28px;height:32px;background:linear-gradient(180deg,#ffd700,#DAA520);border-radius:4px;border:2px solid #B8860B;z-index:3}
.chest-lock::after{content:"";position:absolute;top:6px;left:50%;transform:translateX(-50%);width:8px;height:10px;background:#654321;border-radius:50%}
.chest-body{position:absolute;bottom:0;left:10px;width:200px;height:100px;background:linear-gradient(180deg,#8B4513,#5D3A1A);border-radius:0 0 12px 12px;border:3px solid #DAA520;border-top:none;z-index:1;overflow:hidden}
.chest-body-stripe{position:absolute;top:0;left:0;right:0;height:6px;background:linear-gradient(90deg,transparent,#ffd700,transparent)}
.chest-coins{position:absolute;bottom:5px;left:50%;transform:translateX(-50%);font-size:2.2rem;z-index:4;opacity:0;transition:opacity 0.3s}
.chest-coins.show{opacity:1}
.chest-coins-glow{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);width:120px;height:60px;background:radial-gradient(ellipse,rgba(255,215,0,0.6),transparent 70%);opacity:0;transition:opacity 0.5s;z-index:3}
.chest-coins-glow.show{opacity:1}
.chest-visual.opened .chest-lid{transform:rotateX(-110deg)}
.chest-visual.opened .chest-coins{opacity:1}
.chest-visual.opened .chest-coins-glow{opacity:1}
.chest-shine{position:absolute;top:-20px;left:50%;transform:translateX(-50%);width:250px;height:250px;background:radial-gradient(circle,rgba(255,215,0,0.15),transparent 60%);pointer-events:none;animation:shineRotate 4s linear infinite}
@keyframes shineRotate{0%{transform:translateX(-50%) rotate(0deg)}100%{transform:translateX(-50%) rotate(360deg)}}
.chest-reward{font-size:2.2rem;font-weight:900;color:#ffd700;margin:15px 0;min-height:3rem;text-shadow:0 2px 15px rgba(255,215,0,0.4)}
.chest-home-btn{padding:14px 50px;font-size:1.1rem;font-weight:700;border:none;border-radius:14px;cursor:pointer;background:linear-gradient(135deg,#ffd700,#ff8c00);color:#1a0f2e;font-family:'Heebo',sans-serif;box-shadow:0 4px 20px rgba(255,140,0,0.4);transition:all 0.2s}
.chest-home-btn:active{transform:scale(0.95)}
.char-chest-visual {position:relative;width:220px;height:175px;margin:0 auto 20px;cursor:pointer;perspective:700px}
.char-chest-lid {position:absolute;top:0;left:10px;width:200px;height:70px;background:linear-gradient(180deg,#F4C430,#DAA520,#B8860B);border-radius:100px 100px 0 0;border:3px solid #FFD700;z-index:2;transform-origin:bottom center;transition:transform 0.5s cubic-bezier(0.4,0,0.2,1);box-shadow:inset 0 -8px 15px rgba(0,0,0,0.25),0 3px 8px rgba(0,0,0,0.4)}
.char-chest-lid::after {content:"";position:absolute;bottom:5px;left:0;right:0;height:6px;background:linear-gradient(90deg,transparent,rgba(255,255,255,0.4),transparent)}
.char-chest-body {position:absolute;bottom:0;left:10px;width:200px;height:105px;background:linear-gradient(180deg,#DAA520,#B8860B,#8B6914);border-radius:0 0 14px 14px;border:3px solid #FFD700;border-top:none;z-index:1;box-shadow:inset 0 8px 20px rgba(0,0,0,0.3),0 6px 20px rgba(0,0,0,0.5);overflow:hidden}
.char-chest-body::before {content:"";position:absolute;inset:0;background:repeating-linear-gradient(0deg,transparent,transparent 12px,rgba(0,0,0,0.08) 12px,rgba(0,0,0,0.08) 13px);pointer-events:none}
.char-chest-band-v {position:absolute;top:0;bottom:0;width:14px;background:linear-gradient(90deg,#B8860B,#FFD700,#F4C430,#FFD700,#B8860B);z-index:2;border-left:1px solid rgba(0,0,0,0.2);border-right:1px solid rgba(0,0,0,0.2)}
.char-chest-band-v.left {left:22px}
.char-chest-band-v.right {right:22px}
.char-chest-skull-wrap {position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:3;font-size:4.5rem;line-height:1;filter:drop-shadow(0 3px 6px rgba(0,0,0,0.6)) brightness(0.85) sepia(1) saturate(4) hue-rotate(5deg);opacity:0.95;pointer-events:none}
.char-chest-lock {position:absolute;bottom:-12px;left:50%;transform:translateX(-50%);width:28px;height:34px;background:linear-gradient(180deg,#FFD700,#DAA520,#B8860B);border-radius:5px;border:2px solid #8B6914;z-index:4;box-shadow:0 3px 8px rgba(0,0,0,0.5)}
.char-chest-lock::before {content:"";position:absolute;top:4px;left:50%;transform:translateX(-50%);width:12px;height:12px;border:3px solid #5D3A1A;border-bottom:none;border-radius:12px 12px 0 0}
.char-chest-lock::after {content:"";position:absolute;bottom:6px;left:50%;transform:translateX(-50%);width:5px;height:5px;background:#3d2b07;border-radius:50%;box-shadow:inset 0 1px 2px rgba(0,0,0,0.5)}
.char-chest-bolt {position:absolute;width:9px;height:9px;background:radial-gradient(circle at 30% 30%,#FFD700,#B8860B);border-radius:50%;border:1px solid #8B6914;z-index:3;box-shadow:0 1px 3px rgba(0,0,0,0.4)}
.char-chest-inner-glow {position:absolute;bottom:8px;left:50%;transform:translateX(-50%);width:150px;height:90px;background:radial-gradient(ellipse,rgba(255,215,0,0.45),transparent 70%);opacity:0;transition:opacity 0.6s;z-index:2;pointer-events:none}
.char-chest-visual.opened .char-chest-lid {transform:rotateX(-115deg)}
.char-chest-visual.opened .char-chest-inner-glow {opacity:1}
.char-chest-visual.opened .char-chest-skull-wrap {animation:skullPop 0.4s ease}
@keyframes skullPop {0%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.15)}100%{transform:translate(-50%,-50%) scale(1)}}
.name-box{background:rgba(255,255,255,0.06);border:2px solid rgba(255,215,0,0.3);border-radius:14px;padding:12px 16px;margin:10px auto;max-width:280px;display:flex;gap:8px;align-items:center}
.name-box input{flex:1;background:transparent;border:none;color:#ffd700;font-family:'Heebo',sans-serif;font-size:1rem;font-weight:700;outline:none;text-align:center}
.name-box input::placeholder{color:#b8a8d8;opacity:0.6}
.name-box button{padding:6px 14px;font-size:0.8rem;border:none;border-radius:8px;cursor:pointer;background:linear-gradient(135deg,#ffd700,#ff8c00);color:#1a0f2e;font-weight:700;font-family:'Heebo',sans-serif}
@media(max-width:400px){
.hand-card{width:60px;height:78px}
.char-grid{grid-template-columns:repeat(2,1fr)}
.tower{width:45px;height:55px}
.tower.king{width:55px;height:65px}
.rewards-btn{width:50px;height:50px;font-size:1.5rem}
}
</style>
</head>
<body>
<div class="toast" id="toast"></div>
<div class="result-overlay" id="resultOverlay">
<div class="result-box">
<div class="rtitle" id="rTitle"></div>
<div id="rRewards"></div>
<button class="btn btn-gold" style="margin-top:15px;" onclick="closeResult()">חזור לתפריט</button>
</div>
</div>
<!-- CHEST OVERLAY (coins) -->
<div class="chest-overlay" id="chestOverlay">
<div class="chest-shine"></div>
<div class="chest-box">
<div class="chest-title">תיבת מטבעות!</div>
<div class="chest-sub">לחץ על התיבה כדי לפתוח</div>
<div class="chest-visual" id="chestVisual" onclick="openChest()">
<div class="chest-lid" id="chestLid"><div class="chest-lid-stripe"></div><div class="chest-lock"></div></div>
<div class="chest-body"><div class="chest-body-stripe"></div></div>
<div class="chest-coins-glow" id="chestGlow"></div>
<div class="chest-coins" id="chestCoinsEmoji">💰💰💰</div>
</div>
<div class="chest-reward" id="chestReward"></div>
<button class="chest-home-btn" id="chestContinue" style="display:none;" onclick="closeChest()">🏠 המשך</button>
</div>
</div>
<!-- CHEST OVERLAY (character) -->
<div class="chest-overlay" id="charChestOverlay">
<div class="chest-shine"></div>
<div class="chest-box">
<div class="chest-title">📦 תיבת דמות!</div>
<div class="chest-sub">לחץ על התיבה כדי לפתוח</div>
<div class="char-chest-visual" id="charChestVisual" onclick="openCharChest()">
<div class="char-chest-lid" id="charChestLid">
<div class="char-chest-bolt" style="top:10px;left:12px;"></div>
<div class="char-chest-bolt" style="top:10px;right:12px;"></div>
<div class="char-chest-bolt" style="bottom:10px;left:12px;"></div>
<div class="char-chest-bolt" style="bottom:10px;right:12px;"></div>
</div>
<div class="char-chest-body">
<div class="char-chest-band-v left"></div>
<div class="char-chest-band-v right"></div>
<div class="char-chest-skull-wrap">☠️</div>
<div class="char-chest-inner-glow" id="charChestGlow"></div>
</div>
<div class="char-chest-lock"></div>
</div>
<div class="chest-reward" id="charChestReward"></div>
<button class="chest-home-btn" id="charChestContinue" style="display:none;" onclick="closeCharChest()">המשך</button>
</div>
</div>
<!-- MENU -->
<div class="screen active" id="menuScreen">
<h1>Battle Realms</h1>
<div class="subtitle">ממלכות הקרב</div>
<div class="name-box">
<input type="text" id="playerNameInput" placeholder="הזן שם..." maxlength="12" value="">
<button onclick="savePlayerName()">💾</button>
</div>
<div class="stats-row">
<div class="stat-pill"><div class="lbl">גביעים</div><div class="val" id="mTrophies">0</div></div>
<div class="stat-pill"><div class="lbl">מטבעות</div><div class="val" id="mCoins">0</div></div>
<div class="stat-pill"><div class="lbl">רמת בוט</div><div class="val" id="mBot">1</div></div>
</div>
<button class="btn btn-gold" onclick="goDeck()">שחק נגד בוט</button>
<button class="btn btn-dark" onclick="goTraining()">מוד אימון</button>
<button class="btn btn-dark" onclick="goCollection()">אוסף ושדרוגים</button>
<button class="btn btn-gold" onclick="goRewards()">🎁 הפתעות ופרסים</button>
<button class="btn btn-dark" onclick="goLeaderboard()">🏆 טבלת שחקנים</button>
<button class="btn btn-red" onclick="doReset()" style="margin-top:20px;">איפוס משחק</button>
</div>
<!-- DECK -->
<div class="screen" id="deckScreen">
<button class="back-btn" onclick="goMenu()">חזור</button>
<div class="screen-title">בחר 10 דמויות לדק</div>
<div class="deck-count">נבחרו: <span id="dCount">0</span>/10</div>
<div class="selected-row" id="selRow"></div>
<div class="char-grid" id="charGrid"></div>
<div style="text-align:center;">
<button class="btn btn-gold" id="dNext" onclick="goMaps()" disabled>המשך</button>
</div>
</div>
<!-- MAPS -->
<div class="screen" id="mapScreen">
<button class="back-btn" onclick="goDeck()">חזור</button>
<div class="screen-title">בחר מפה</div>
<div class="map-grid" id="mapGrid"></div>
<div style="text-align:center;">
<button class="btn btn-gold" id="mStart" onclick="startGame()" disabled>התחל!</button>
</div>
</div>
<!-- TRAINING -->
<div class="screen" id="trainingScreen">
<button class="back-btn" onclick="goMenu()">חזור</button>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;">
<div class="screen-title">מוד אימון</div>
<button class="btn btn-gold" onclick="startTrain('easy')">קל 😊</button>
<button class="btn btn-gold" onclick="startTrain('medium')">בינוני 😐</button>
<button class="btn btn-gold" onclick="startTrain('hard')">קשה 😠</button>
<button class="btn btn-red" onclick="startTrain('impossible')">בלתי אפשרי 😈</button>
</div>
</div>
<!-- GAME -->
<div class="screen" id="gameScreen">
<div class="game-hud">
<div class="hud-side"><div class="h-num" id="hPlayer">3</div><div class="h-lbl">מבנים</div></div>
<div class="hud-timer" id="hTimer">3:00</div>
<div class="hud-side"><div class="h-num" id="hBot">3</div><div class="h-lbl">מבנים</div></div>
</div>
<div class="arena" id="arena">
<div class="arena-river"></div>
<div class="arena-bridge left"></div>
<div class="arena-bridge right"></div>
<div class="tower bot bot-side princess-left" id="tB0">🏯<div class="t-hp" id="hpB0">2400</div></div>
<div class="tower bot bot-side princess-right" id="tB1">🏯<div class="t-hp" id="hpB1">2400</div></div>
<div class="tower bot bot-side king inactive" id="tB2">👑<div class="t-hp" id="hpB2">4000</div></div>
<div class="tower player player-side princess-left" id="tP0">🏰<div class="t-hp" id="hpP0">2400</div></div>
<div class="tower player player-side princess-right" id="tP1">🏰<div class="t-hp" id="hpP1">2400</div></div>
<div class="tower player player-side king inactive" id="tP2">👑<div class="t-hp" id="hpP2">4000</div></div>
<div class="placement-ghost" id="ghost"></div>
</div>
<div class="elixir-text" id="eText">אליקסיר: 0/10</div>
<div class="elixir-bar"><div class="elixir-fill" id="eFill" style="width:0%"></div></div>
<div class="hand-bar" id="handBar"></div>
</div>
<!-- COLLECTION -->
<div class="screen" id="collectionScreen">
<button class="back-btn" onclick="goMenu()">חזור</button>
<div class="screen-title">אוסף ושדרוגים</div>
<div style="text-align:center;color:#ffd700;margin-bottom:15px;">💰 <span id="cCoins">0</span></div>
<div class="upgrade-grid" id="upGrid"></div>
</div>
<!-- LEADERBOARD -->
<div class="screen" id="leaderboardScreen">
<button class="back-btn" onclick="goMenu()">חזור</button>
<div class="screen-title">🏆 טבלת השחקנים</div>
<table class="lb-table" id="lbTable">
<thead><tr><th class="lb-rank">#</th><th>שחקן</th><th>גביעים</th></tr></thead>
<tbody id="lbBody"></tbody>
</table>
</div>
<!-- REWARDS -->
<div class="screen" id="rewardsScreen">
<button class="back-btn" onclick="goMenu()">חזור</button>
<div class="screen-title">🎁 המתנות שלך</div>
<div class="rewards-grid" id="rewardsGrid"></div>
</div>
<!-- Floating Rewards Button -->
<div class="rewards-btn" id="rewardsBtn" onclick="goRewards()">🎁</div>
<script>
// ==================== DATA ====================
const CHARS=[
{id:0,name:"לוחם",icon:"⚔️",hp:800,dmg:120,speed:1.2,range:30,cost:3,special:"מתקפה כפולה",unlock:0},
{id:1,name:"קשת",icon:"🏹",hp:400,dmg:150,speed:0.9,range:150,cost:3,special:"ירי מרחוק",unlock:0},
{id:2,name:"מגן",icon:"🛡️",hp:1500,dmg:60,speed:0.7,range:30,cost:4,special:"בלימת נזק",unlock:0},
{id:3,name:"מכשף",icon:"🔮",hp:350,dmg:200,speed:0.8,range:120,cost:5,special:"כדור אש",unlock:0},
{id:4,name:"רוכב",icon:"🐴",hp:1000,dmg:180,speed:1.8,range:40,cost:5,special:"סערת פרשים",unlock:0},
{id:5,name:"מרפא",icon:"💚",hp:450,dmg:40,speed:0.8,range:100,cost:4,special:"ריפוי יחידה",unlock:0},
{id:6,name:"גולם",icon:"🗿",hp:2500,dmg:100,speed:0.5,range:35,cost:6,special:"הלם קרקע",unlock:0},
{id:7,name:"צלף",icon:"🎯",hp:300,dmg:300,speed:0.7,range:200,cost:5,special:"ירי קריטי",unlock:0},
{id:8,name:"נינג'ה",icon:"🥷",hp:600,dmg:220,speed:2.0,range:30,cost:4,special:"היעלמות",unlock:0},
{id:9,name:"כומת",icon:"🔨",hp:700,dmg:160,speed:1.0,range:30,cost:4,special:"הרס מבנים",unlock:0},
{id:10,name:"דרקון",icon:"🐉",hp:2000,dmg:250,speed:1.5,range:80,cost:7,special:"נשיפת אש",unlock:500},
{id:11,name:"רוח",icon:"👻",hp:500,dmg:180,speed:1.4,range:50,cost:4,special:"חדירת שריון",unlock:500},
{id:12,name:"אלף",icon:"🧝",hp:550,dmg:170,speed:1.3,range:110,cost:4,special:"חץ קסום",unlock:1000},
{id:13,name:"ענק",icon:"👹",hp:3500,dmg:200,speed:0.6,range:50,cost:8,special:"ריסוק",unlock:1000},
{id:14,name:"פניקס",icon:"🔥",hp:1200,dmg:280,speed:1.6,range:90,cost:7,special:"תחייה",unlock:1500},
{id:15,name:"קריפטון",icon:"💀",hp:900,dmg:240,speed:1.1,range:40,cost:5,special:"שאיבת חיים",unlock:1500},
{id:16,name:"טיטאן",icon:"⚡",hp:2800,dmg:220,speed:0.8,range:60,cost:8,special:"ברק",unlock:2000},
{id:17,name:"צייד",icon:"🐺",hp:750,dmg:190,speed:1.7,range:45,cost:4,special:"זאבים",unlock:2500},
{id:18,name:"מלך",icon:"👑",hp:1800,dmg:300,speed:1.0,range:50,cost:7,special:"עידוד צבא",unlock:3000},
{id:19,name:"אל",icon:"✨",hp:2200,dmg:350,speed:1.2,range:100,cost:9,special:"שיפור כללי",unlock:5000},
];
const MAPS=[
{id:0,name:"עמק הזריחה",emoji:"🌅",bg:"linear-gradient(180deg,#7a9a6a,#5a8a5a,#4a7a4a)",scenery:[{icon:"🌅",x:45,y:5,s:5,o:0.4},{icon:"☀️",x:75,y:8,s:4,o:0.35},{icon:"🌻",x:15,y:85,s:2.5,o:0.5},{icon:"🌻",x:85,y:88,s:2.5,o:0.5},{icon:"🦋",x:30,y:40,s:1.8,o:0.4},{icon:"🦋",x:70,y:55,s:1.8,o:0.4},{icon:"🌸",x:10,y:70,s:2,o:0.45},{icon:"🌸",x:90,y:65,s:2,o:0.45}]},
{id:1,name:"יער האפלה",emoji:"🌲",bg:"linear-gradient(180deg,#2a5a2a,#1f4a1f,#153a15)",scenery:[{icon:"🌲",x:8,y:5,s:4.5,o:0.5},{icon:"🌲",x:22,y:8,s:5,o:0.45},{icon:"🌲",x:78,y:6,s:4.8,o:0.5},{icon:"🌲",x:92,y:9,s:4.2,o:0.45},{icon:"🌳",x:5,y:75,s:5,o:0.5},{icon:"🌳",x:35,y:82,s:4.5,o:0.45},{icon:"🌳",x:65,y:78,s:5,o:0.5},{icon:"🌳",x:95,y:85,s:4.8,o:0.45},{icon:"🍄",x:18,y:55,s:2,o:0.4},{icon:"🍄",x:82,y:50,s:2,o:0.4},{icon:"🦉",x:50,y:15,s:2.2,o:0.35},{icon:"🦊",x:40,y:70,s:2,o:0.3}]},
{id:2,name:"מדבר הלוהט",emoji:"🏜️",bg:"linear-gradient(180deg,#d4b46a,#c4a45a,#b4944a)",scenery:[{icon:"🏜️",x:12,y:5,s:6,o:0.45},{icon:"🏜️",x:88,y:8,s:5.5,o:0.4},{icon:"🌵",x:8,y:80,s:3.5,o:0.5},{icon:"🌵",x:25,y:88,s:3,o:0.45},{icon:"🌵",x:75,y:82,s:3.5,o:0.5},{icon:"🌵",x:92,y:90,s:3,o:0.45},{icon:"🐪",x:40,y:65,s:3,o:0.35},{icon:"🦂",x:60,y:75,s:2,o:0.4},{icon:"💀",x:18,y:45,s:2,o:0.3},{icon:"☀️",x:80,y:12,s:4,o:0.35}]},
{id:3,name:"הרי הקרח",emoji:"🏔️",bg:"linear-gradient(180deg,#9ac8d8,#8ab8c8,#7aa8b8)",scenery:[{icon:"🏔️",x:10,y:3,s:6,o:0.45},{icon:"🏔️",x:85,y:5,s:5.5,o:0.4},{icon:"🏔️",x:50,y:2,s:7,o:0.5},{icon:"❄️",x:20,y:25,s:2,o:0.4},{icon:"❄️",x:70,y:30,s:2.2,o:0.4},{icon:"❄️",x:45,y:40,s:1.8,o:0.35},{icon:"⛄",x:15,y:80,s:3,o:0.5},{icon:"⛄",x:85,y:85,s:3,o:0.45},{icon:"🐧",x:35,y:70,s:2.2,o:0.4},{icon:"🐧",x:65,y:75,s:2.2,o:0.4},{icon:"🧊",x:5,y:50,s:3,o:0.35},{icon:"🧊",x:95,y:55,s:3,o:0.35}]},
{id:4,name:"המצודה",emoji:"🏰",bg:"linear-gradient(180deg,#6a5a7a,#5a4a6a,#4a3a5a)",scenery:[{icon:"🏰",x:50,y:2,s:6,o:0.5},{icon:"🕯️",x:15,y:15,s:2,o:0.4},{icon:"🕯️",x:85,y:18,s:2,o:0.4},{icon:"🦇",x:25,y:35,s:2,o:0.35},{icon:"🦇",x:75,y:40,s:2,o:0.35},{icon:"🕷️",x:10,y:55,s:1.8,o:0.3},{icon:"🕷️",x:90,y:60,s:1.8,o:0.3},{icon:"⚔️",x:30,y:78,s:2.5,o:0.35},{icon:"🛡️",x:70,y:82,s:2.5,o:0.35},{icon:"💎",x:50,y:88,s:2,o:0.4},{icon:"🔥",x:5,y:25,s:2.5,o:0.3},{icon:"🔥",x:95,y:28,s:2.5,o:0.3}]},
];
const UGCOSTS=[20,40,60,80,100,130,160,200,300,400,500,600,700,800,900,1000];
const TOWER_DMG=75;
const TOWER_RANGE=140;
const TOWER_ATK_SPEED=1200;
const REWARD_DEFS=[
{offset:50,icon:"💰",title:"80 מטבעות",desc:"בונוס ישיר",type:"coins",amount:80},
{offset:150,icon:"📦",title:"תיבת מטבעות",desc:"פתח וגלה כמה קיבלת",type:"coinChest"},
{offset:250,icon:"💰",title:"80 מטבעות",desc:"בונוס ישיר",type:"coins",amount:80},
{offset:400,icon:"📦",title:"תיבת מטבעות",desc:"פתח וגלה כמה קיבלת",type:"coinChest"},
{offset:500,icon:"🎁",title:"תיבת דמות",desc:"דמות חדשה אקראית",type:"charChest"},
];
let GS=loadGS();
let storageOK=false;
function loadGS(){
try{
const s=localStorage.getItem('brSave');
if(s){
const d=JSON.parse(s);
if(!d.rewardsClaimed)d.rewardsClaimed=[];
if(!d.leaderboard)d.leaderboard=[];
if(!d.playerName)d.playerName="שחקן";
storageOK=true;
return d;
}
}catch(e){storageOK=false;}
return{
trophies:0,coins:0,unlocked:[0,1,2,3,4,5,6,7,8,9],levels:{},deck:[0,1,2,3,4,5,6,7,8,9],
wins:0,losses:0,rewardsClaimed:[],leaderboard:[],playerName:"שחקן"
};
}
function saveGS(){
try{localStorage.setItem('brSave',JSON.stringify(GS));storageOK=true;}catch(e){storageOK=false;}
}
function doReset(){
if(!confirm('לאפס הכל? כל ההתקדמות תמחק!'))return;
resetGameSession();
try{localStorage.removeItem('brSave');}catch(e){}
GS={
trophies:0,coins:0,unlocked:[0,1,2,3,4,5,6,7,8,9],levels:{},deck:[0,1,2,3,4,5,6,7,8,9],
wins:0,losses:0,rewardsClaimed:[],leaderboard:[],playerName:"שחקן"
};
document.getElementById('resultOverlay').classList.remove('on');
document.getElementById('chestOverlay').classList.remove('on');
document.getElementById('charChestOverlay').classList.remove('on');
showScreen('menuScreen');
updateMenu();
toast('המשחק אופס בהצלחה!');
}
function toast(t){const el=document.getElementById('toast');el.textContent=t;el.classList.add('show');setTimeout(()=>el.classList.remove('show'),2500);}
function getBotLvl(){return Math.floor(GS.trophies/500)+1;}
function getTrophyFloor(){return Math.floor(GS.trophies/500)*500;}
function getLossAmount(){const l=getBotLvl();return 11+2*(l-1);}
function getLvl(id){return GS.levels[id]||1;}
function getCost(lvl){return (UGCOSTS[lvl-1]||200)*2;}
function getMaxLvl(){
const t=GS.trophies;
if(t>=10000)return 16;if(t>=9000)return 15;if(t>=8000)return 14;if(t>=7000)return 13;
if(t>=6000)return 12;if(t>=5000)return 11;if(t>=4000)return 10;if(t>=3000)return 10;
if(t>=2000)return 10;if(t>=1000)return 9;return 8;
}
function getStats(id){
const b=CHARS.find(c=>c.id===id);
const l=getLvl(id);
const m=1+(l-1)*0.1;
return{...b,hp:Math.floor(b.hp*m),dmg:Math.floor(b.dmg*m),speed:b.speed*(1+(l-1)*0.03)};
}
function isUnl(id){return GS.unlocked.includes(id);}
function canUnl(id){return GS.trophies>=CHARS.find(c=>c.id===id).unlock;}
function updateLeaderboard(){
let lb=GS.leaderboard||[];
const myName=(GS.playerName||'שחקן').trim();
const idx=lb.findIndex(p=>p.name===myName);
if(idx>=0){lb[idx].trophies=Math.max(lb[idx].trophies,GS.trophies);}
else{lb.push({name:myName,trophies:GS.trophies});}
lb.sort((a,b)=>b.trophies-a.trophies);
GS.leaderboard=lb.slice(0,10);saveGS();
}
function getTop5(){updateLeaderboard();return(GS.leaderboard||[]).slice(0,5);}
function showScreen(id){document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));document.getElementById(id).classList.add('active');}
function goMenu(){document.getElementById('resultOverlay').classList.remove('on');showScreen('menuScreen');saveGS();updateMenu();}
function closeResult(){document.getElementById('resultOverlay').classList.remove('on');goMenu();}
function updateMenu(){
document.getElementById('mTrophies').textContent=GS.trophies;
document.getElementById('mCoins').textContent=GS.coins;
document.getElementById('mBot').textContent=getBotLvl();
document.getElementById('playerNameInput').value=GS.playerName||'שחקן';
updateRewards();
}
function goTraining(){showScreen('trainingScreen');}
/* ==================== פרסים ופרופיל ==================== */
function updateRewards(){
const btn = document.getElementById('rewardsBtn');
if(!btn) return;
const floor = getTrophyFloor();
const hasNew = REWARD_DEFS.some((r,i) => !GS.rewardsClaimed.includes(i) && GS.trophies >= floor + r.offset);
btn.classList.toggle('has-new', hasNew);
}
function savePlayerName(){
const input = document.getElementById('playerNameInput');
if(!input) return;
const v = input.value.trim();
if(v){ GS.playerName = v; saveGS(); toast('השם נשמר!'); }
}
/* ==================== חפיסה ==================== */
let tempDeck = [];
function goDeck(){ tempDeck = [...GS.deck]; renderDeck(); showScreen('deckScreen'); }
function renderDeck(){
const dCount = document.getElementById('dCount');
const dNext = document.getElementById('dNext');
const selRow = document.getElementById('selRow');
const grid = document.getElementById('charGrid');
if(dCount) dCount.textContent = tempDeck.length;
if(dNext) dNext.disabled = tempDeck.length !== 10;
if(selRow){
selRow.innerHTML = '';
for(let i = 0; i < 10; i++){
const d = document.createElement('div');
d.className = 'sel-slot ' + (i < tempDeck.length ? '' : 'empty');
if(i < tempDeck.length){
const c = CHARS.find(x => x.id === tempDeck[i]);
if(c) d.textContent = c.icon;
}
selRow.appendChild(d);
}
}
if(grid){
grid.innerHTML = '';
CHARS.forEach(c => {
const el = document.createElement('div');
const picked = tempDeck.includes(c.id);
const locked = !isUnl(c.id);
el.className = 'char-cell ' + (picked ? 'picked ' : '') + (locked ? 'locked' : '');
el.innerHTML = `<div class="c-lvl">Lv.${getLvl(c.id)}</div>${locked ? '<div class="c-lock">נעול</div>' : ''}<div class="c-icon">${c.icon}</div><div class="c-name">${c.name}</div><div class="c-info">❤️${c.hp} ⚔️${c.dmg}<br>💧${c.cost} ${c.special}</div>`;
if(!locked) el.onclick = () => toggleChar(c.id);
grid.appendChild(el);
});
}
}
function toggleChar(id){
if(tempDeck.includes(id)){ tempDeck = tempDeck.filter(x => x !== id); }
else if(tempDeck.length < 10){ tempDeck.push(id); }
renderDeck();
}
function goMaps(){
if(tempDeck.length !== 10) return;
GS.deck = [...tempDeck];
saveGS();
renderMaps();
showScreen('mapScreen');
}
/* ==================== מפות ==================== */
let selMap = 0;
function renderMaps(){
const g = document.getElementById('mapGrid');
const mStart = document.getElementById('mStart');
if(!g) return;
g.innerHTML = '';
MAPS.forEach(m => {
const el = document.createElement('div');
el.className = 'map-cell ' + (selMap === m.id ? 'chosen' : '');
el.style.background = m.bg;
el.innerHTML = `<div class="m-emoji">${m.emoji}</div><div class="m-name">${m.name}</div>`;
el.onclick = () => { selMap = m.id; renderMaps(); if(mStart) mStart.disabled = false; };
g.appendChild(el);
});
}
/* ==================== ניהול סשן משחק ==================== */
let gameActive = false, gamePaused = false;
let gameTimers = {};
let gameUnits = [], gameProjectiles = [];
let gameElixir = 5, gameBotElixir = 5;
let gameTimeLeft = 180;
let gameHand = [], gameBotHand = [], gameDeckQueue = [], gameBotQueue = [];
let gameBotLvl = 1, gameBotDeck = [];
let gameMapData = null;
let gameTrainMode = false, gameTrainDiff = 'medium';
let gameTowers = {};
function clearGameTimers(){
Object.keys(gameTimers).forEach(k => {
if(gameTimers[k]) clearInterval(gameTimers[k]);
gameTimers[k] = null;
});
}
function resetGameSession(){
clearGameTimers();
gameActive = false; gamePaused = false;
gameUnits = []; gameProjectiles = [];
gameElixir = 5; gameBotElixir = 5; gameTimeLeft = 180;
gameHand = []; gameBotHand = []; gameDeckQueue = []; gameBotQueue = [];
gameBotLvl = 1; gameBotDeck = [];
gameMapData = null;
gameTrainMode = false; gameTrainDiff = 'medium';
gameTowers = {};
selCard = -1;
const arena = document.getElementById('arena');
if(arena) arena.querySelectorAll('.unit, .tower-shot, .dmg-pop, .scenery').forEach(e => e.remove());
const ghost = document.getElementById('ghost');
if(ghost) ghost.style.display = 'none';
}
/* ==================== לוגיקת משחק ==================== */
function startGame(){ gameTrainMode = false; initGame(); }
function startTrain(diff){ gameTrainMode = true; gameTrainDiff = diff; initGame(); }
function initGame(){
resetGameSession();
gameActive = true;
gameMapData = MAPS[selMap];
gameBotLvl = gameTrainMode ? diffToBotLvl(gameTrainDiff) : getBotLvl();
gameBotDeck = buildBotDeck(gameBotLvl);
gameDeckQueue = shuffle([...GS.deck]);
gameBotQueue = shuffle([...gameBotDeck]);
gameHand = drawHand(gameDeckQueue, 4);
gameBotHand = drawHand(gameBotQueue, 4);
gameTowers = {
hp: { p: [2400,2400,4000], b: [2400,2400,4000] },
active: { p: [true,true,false], b: [true,true,false] },
cooldown:{}
};
const arena = document.getElementById('arena');
if(arena){
arena.style.background = gameMapData ? gameMapData.bg : '';
arena.onclick = arenaClick;
}
renderScenery();
updateTowers();
showScreen('gameScreen');
renderHand();
updateHUD();
updateElixir();
gameTimers.tmr = setInterval(() => {
if(!gameActive || gamePaused) return;
gameTimeLeft--;
if(gameTimeLeft <= 0){ endGame(); return; }
updateHUD();
}, 1000);
gameTimers.loop = setInterval(gameTick, 50);
gameTimers.mana = setInterval(() => {
if(!gameActive || gamePaused) return;
gameElixir = Math.min(10, gameElixir + 0.15);
gameBotElixir = Math.min(10, gameBotElixir + getBotElixirRate());
updateElixir();
}, 200);
gameTimers.bot = setInterval(botTick, 1200);
}
function diffToBotLvl(d){ return d === 'easy' ? 1 : d === 'medium' ? 3 : d === 'hard' ? 6 : 10; }
function buildBotDeck(lvl){
const pool = CHARS.filter((_,i) => i < 10 + (lvl * 2)).map(c => c.id);
const d = [];
while(d.length < 10){
const r = pool[Math.floor(Math.random() * pool.length)];
if(!d.includes(r)) d.push(r);
}
return d;
}
function shuffle(a){
const n = [...a];
for(let i = n.length - 1; i > 0; i--){
const j = Math.floor(Math.random() * (i + 1));
[n[i], n[j]] = [n[j], n[i]];
}
return n;
}
function drawHand(queue, n){
const h = [];
while(h.length < n && queue.length > 0) h.push(queue.shift());
return h;
}
function renderScenery(){
const arena = document.getElementById('arena');
if(!arena) return;
arena.querySelectorAll('.scenery').forEach(e => e.remove());
if(gameMapData && gameMapData.scenery){
gameMapData.scenery.forEach(s => {
const e = document.createElement('div');
e.className = 'scenery';
e.textContent = s.icon;
e.style.left = s.x + '%';
e.style.top = s.y + '%';
e.style.fontSize = s.s + 'rem';
e.style.opacity = s.o;
arena.appendChild(e);
});
}
}
function updateHUD(){
const hTimer = document.getElementById('hTimer');
const hPlayer = document.getElementById('hPlayer');
const hBot = document.getElementById('hBot');
if(hTimer) hTimer.textContent = fmtTime(gameTimeLeft);
if(hPlayer) hPlayer.textContent = gameTowers.active.p.filter(Boolean).length;
if(hBot) hBot.textContent = gameTowers.active.b.filter(Boolean).length;
}
function fmtTime(s){
const m = Math.floor(s / 60);
const r = s % 60;
return m + ':' + (r < 10 ? '0' : '') + r;
}
function updateElixir(){
const eText = document.getElementById('eText');
const eFill = document.getElementById('eFill');
if(eText) eText.textContent = 'אליקסיר: ' + Math.floor(gameElixir) + '/10';
if(eFill) eFill.style.width = (gameElixir * 10) + '%';
renderHand();
}
function renderHand(){
const bar = document.getElementById('handBar');
if(!bar) return;
bar.innerHTML = '';
gameHand.forEach((id, idx) => {
const c = CHARS.find(x => x.id === id);
if(!c) return;
const el = document.createElement('div');
const can = gameElixir >= c.cost;
el.className = 'hand-card ' + (selCard === idx ? 'selected ' : '') + (can ? '' : 'disabled');
el.innerHTML = `<div class="hc-cost">${c.cost}</div><div class="hc-icon">${c.icon}</div><div class="hc-name">${c.name}</div>`;
el.onclick = (e) => { e.stopPropagation(); selectCard(idx); };
bar.appendChild(el);
});
}
let selCard = -1;
function selectCard(idx){
if(idx >= gameHand.length) return;
const c = CHARS.find(x => x.id === gameHand[idx]);
if(!c || gameElixir < c.cost) return;
selCard = selCard === idx ? -1 : idx;
renderHand();
const ghost = document.getElementById('ghost');
if(ghost) ghost.style.display = selCard >= 0 ? 'block' : 'none';
}
function arenaClick(e){
if(selCard < 0 || !gameActive || gamePaused) return;
const c = CHARS.find(x => x.id === gameHand[selCard]);
if(!c || gameElixir < c.cost) return;
const arena = document.getElementById('arena');
if(!arena) return;
const rect = arena.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
if(y > rect.height * 0.55 || y < rect.height * 0.25) return;
gameElixir -= c.cost;
spawnUnit(gameHand[selCard], 'player', x, y);
gameHand[selCard] = gameDeckQueue.length > 0 ? gameDeckQueue.shift() : gameHand[selCard];
selCard = -1;
const ghost = document.getElementById('ghost');
if(ghost) ghost.style.display = 'none';
updateElixir();
renderHand();
}
function spawnUnit(charId, side, x, y){
const s = getStats(charId);
const arena = document.getElementById('arena');
if(!arena) return null;
const el = document.createElement('div');
el.className = 'unit ' + side;
el.style.left = (x - 21) + 'px';
el.style.top = (y - 21) + 'px';
el.innerHTML = s.icon + `<div class="unit-hp-bg"><div class="unit-hp-fg" style="width:100%"></div></div>`;
arena.appendChild(el);
const unit = {
id: Date.now() + Math.random(),
charId, char: s, side, el, x, y,
hp: s.hp, maxHp: s.hp,
lastAtk: 0, state: 'walk', target: null
};
gameUnits.push(unit);
return unit;
}
function gameTick(){
if(!gameActive || gamePaused) return;
const arena = document.getElementById('arena');
if(!arena) return;
const w = arena.offsetWidth, h = arena.offsetHeight;
// עדכון יחידות
gameUnits.forEach(u => {
if(u.hp <= 0) return;
let nearest = null, nd = Infinity;
// יחידות אויב
gameUnits.forEach(o => {
if(o.hp <= 0 || o.side === u.side) return;
const d = dist(u, o);
if(d < nd){ nd = d; nearest = o; }
});
// מגדלים
[0,1,2].forEach(ti => {
const isBot = u.side === 'player';
const tSide = isBot ? 'b' : 'p';
if(!gameTowers.active[tSide][ti]) return;
const tx = getTowerX(ti, w);
const ty = isBot ? h * 0.11 : h * 0.89;
const d = Math.hypot(u.x - tx, u.y - ty);
if(d < nd){ nd = d; nearest = { x: tx, y: ty, tower: true, side: tSide, index: ti }; }
});
if(nearest && nd <= u.char.range){
u.state = 'attack';
if(Date.now() - u.lastAtk > 1000 / u.char.speed){
u.lastAtk = Date.now();
if(nearest.tower){ dmgTower(nearest.side, nearest.index, u.char.dmg); }
else { dmgUnit(nearest, u.char.dmg); }
}
} else {
u.state = 'walk';
const ty = u.side === 'player' ? 0 : h;
const tx = w / 2;
const angle = Math.atan2(ty - u.y, tx - u.x);
const spd = u.char.speed * 1.5;
u.x += Math.cos(angle) * spd;
u.y += Math.sin(angle) * spd;
u.el.style.left = (u.x - 21) + 'px';
u.el.style.top = (u.y - 21) + 'px';
}
});
// ירי מגדלים
[0,1,2].forEach(ti => {
['p','b'].forEach(ts => {
if(!gameTowers.active[ts][ti]) return;
const isBot = ts === 'b';
const tx = getTowerX(ti, w);
const ty = isBot ? h * 0.11 : h * 0.89;
let nearest = null, nd = TOWER_RANGE;
gameUnits.forEach(u => {
if(u.hp <= 0 || u.side === (isBot ? 'bot' : 'player')) return;
const d = Math.hypot(u.x - tx, u.y - ty);
if(d < nd){ nd = d; nearest = u; }
});
if(nearest){
const key = ts + ti;
const lastShot = gameTowers.cooldown[key] || 0;
if(Date.now() - lastShot > TOWER_ATK_SPEED){
gameTowers.cooldown[key] = Date.now();
fireShot(tx, ty, nearest, TOWER_DMG);
}
}
});
});
// חצים
gameProjectiles.forEach(p => {
if(p.done) return;
const dx = p.target.x - p.x;
const dy = p.target.y - p.y;
const d = Math.hypot(dx, dy);
if(d < 10){
p.done = true;
p.el.remove();
if(p.target.tower){
dmgTower(p.target.side, p.target.index, p.dmg);
} else if(gameUnits.includes(p.target)){
dmgUnit(p.target, p.dmg);
}
} else {
p.x += dx / d * 12;
p.y += dy / d * 12;
p.el.style.left = (p.x - 5) + 'px';
p.el.style.top = (p.y - 5) + 'px';
}
});
gameProjectiles = gameProjectiles.filter(p => !p.done);
// ניקוי מתים
gameUnits.forEach(u => {
if(u.hp <= 0 && u.el.parentNode){ u.el.remove(); }
});
gameUnits = gameUnits.filter(u => u.hp > 0);
// בדיקת סיום
if(gameTowers.active.p[2] === false || gameTowers.active.b[2] === false) endGame();
}
function getTowerX(i, w){ return i === 0 ? w * 0.05 : i === 1 ? w * 0.95 : w * 0.5; }
function dist(a, b){ return Math.hypot(a.x - b.x, a.y - b.y); }
function dmgUnit(u, dmg){
u.hp -= dmg;
const pct = Math.max(0, u.hp / u.maxHp * 100);
const bar = u.el.querySelector('.unit-hp-fg');
if(bar) bar.style.width = pct + '%';
showDmg(u.x, u.y - 25, dmg);
if(u.hp <= 0){
u.el.style.opacity = '0';
setTimeout(() => { if(u.el && u.el.parentNode) u.el.remove(); }, 300);
}
}
function dmgTower(side, idx, dmg){
const hpArr = gameTowers.hp[side];
hpArr[idx] -= dmg;
const currentHP = Math.max(0, Math.floor(hpArr[idx]));
const el = document.getElementById('hp' + (side === 'b' ? 'B' : 'P') + idx);
if(el) el.textContent = currentHP;
const arena = document.getElementById('arena');
if(!arena) return;
const w = arena.offsetWidth;
showDmg(getTowerX(idx, w), side === 'b' ? 40 : arena.offsetHeight - 40, dmg);
if(hpArr[idx] <= 0){
hpArr[idx] = 0;
gameTowers.active[side][idx] = false;
const tel = document.getElementById('t' + (side === 'b' ? 'B' : 'P') + idx);
if(tel){
tel.classList.add('destroyed');
if(idx === 2) tel.classList.remove('inactive');
}
if(idx < 2){
const king = document.getElementById('t' + (side === 'b' ? 'B' : 'P') + 2);
if(king) king.classList.remove('inactive');
gameTowers.active[side][2] = true;
}
}
}
function showDmg(x, y, dmg){
const arena = document.getElementById('arena');
if(!arena) return;
const el = document.createElement('div');
el.className = 'dmg-pop';
el.textContent = '-' + Math.floor(dmg);
el.style.left = (x - 15) + 'px';
el.style.top = y + 'px';
arena.appendChild(el);
setTimeout(() => el.remove(), 800);
}
function fireShot(x, y, target, dmg){
const arena = document.getElementById('arena');
if(!arena) return;
const el = document.createElement('div');
el.className = 'tower-shot';
el.style.left = (x - 5) + 'px';
el.style.top = (y - 5) + 'px';
el.style.background = target.side === 'b' ? '#4CAF50' : '#f44336';
arena.appendChild(el);
gameProjectiles.push({ el, x, y, target, dmg, done: false });
}
function getBotElixirRate(){
if(gameTrainMode){
if(gameTrainDiff === 'easy') return 0.05;
if(gameTrainDiff === 'medium') return 0.12;
if(gameTrainDiff === 'hard') return 0.2;
return 0.35;
}
return 0.1 + Math.min(0.15, (gameBotLvl - 1) * 0.02);
}
function botTick(){
if(!gameActive || gamePaused) return;
const arena = document.getElementById('arena');
if(!arena) return;
const w = arena.offsetWidth, h = arena.offsetHeight;
const affordable = gameBotHand.map((id, idx) => ({ id, idx, c: CHARS.find(x => x.id === id) }))
.filter(o => o.c && gameBotElixir >= o.c.cost);
if(affordable.length === 0) return;
const pick = affordable[Math.floor(Math.random() * affordable.length)];
gameBotElixir -= pick.c.cost;
const x = w * 0.2 + Math.random() * w * 0.6;
const y = h * 0.08 + Math.random() * h * 0.15;
spawnUnit(pick.id, 'bot', x, y);
gameBotHand[pick.idx] = gameBotQueue.length > 0 ? gameBotQueue.shift() : gameBotHand[pick.idx];
}
function updateTowers(){
[0,1,2].forEach(i => {
['P','B'].forEach(s => {
const el = document.getElementById('t' + s + i);
if(!el) return;
const side = s === 'B' ? 'b' : 'p';
if(gameTowers.active[side][i]){
el.classList.remove('inactive', 'destroyed');
} else if(gameTowers.hp[side][i] <= 0){
el.classList.add('destroyed');
}
});
});
}
function endGame(){
if(!gameActive) return;
gameActive = false;
clearGameTimers();
const pCount = gameTowers.active.p.filter(Boolean).length;
const bCount = gameTowers.active.b.filter(Boolean).length;
let result, title, coins = 0, trophies = 0;
if(pCount > bCount || gameTowers.active.b[2] === false){
result = 'win'; title = 'ניצחון! 🎉'; coins = 30 + Math.floor(Math.random() * 20); trophies = 30;
} else if(bCount > pCount || gameTowers.active.p[2] === false){
result = 'lose'; title = 'הפסד...'; coins = 5; trophies = -getLossAmount();
} else {
result = 'draw'; title = 'תיקו 🤝'; coins = 10; trophies = 0;
}
if(result === 'win') GS.wins++;
else if(result === 'lose') GS.losses++;
GS.coins = Math.max(0, GS.coins + coins);
GS.trophies = Math.max(0, GS.trophies + trophies);
updateLeaderboard();
saveGS();
const rTitle = document.getElementById('rTitle');
const rRewards = document.getElementById('rRewards');
const resultOverlay = document.getElementById('resultOverlay');
if(rTitle){
rTitle.textContent = title;
rTitle.className = 'rtitle ' + result;
}
if(rRewards){
rRewards.innerHTML = `<div class="r-reward">💰 <b>+${coins}</b> מטבעות</div>` + (trophies !== 0 ? `<div class="r-reward">🏆 <b>${trophies > 0 ? '+' : ''}${trophies}</b> גביעים</div>` : '');
}
if(resultOverlay) resultOverlay.classList.add('on');
}
/* ==================== אוסף ==================== */
function goCollection(){ renderUpgrades(); showScreen('collectionScreen'); }
function renderUpgrades(){
const cCoins = document.getElementById('cCoins');
const g = document.getElementById('upGrid');
if(cCoins) cCoins.textContent = GS.coins;
if(!g) return;
g.innerHTML = '';
CHARS.forEach(c => {
if(!isUnl(c.id)) return;
const lvl = getLvl(c.id);
const max = getMaxLvl();
const el = document.createElement('div');
el.className = 'up-card';
const s = getStats(c.id);
const cost = getCost(lvl);
const can = lvl < max && GS.coins >= cost;
el.innerHTML = `<div class="c-lvl" style="position:static;display:inline-block;margin-bottom:4px;">Lv.${lvl}</div><div class="up-icon">${c.icon}</div><div class="up-name">${c.name}</div><div class="up-stat">❤️${s.hp} ⚔️${s.dmg}<br>💰 שדרוג: ${lvl >= max ? 'מקסימום' : cost}</div>` + (lvl >= max ? '<div class="up-max">מקסימום ⭐</div>' : `<button class="up-btn" ${can ? '' : 'disabled'} onclick="doUpgrade(${c.id})">שדרג</button>`);
g.appendChild(el);
});
}
function doUpgrade(id){
const lvl = getLvl(id);
const cost = getCost(lvl);
if(GS.coins < cost || lvl >= getMaxLvl()) return;
GS.coins -= cost;
GS.levels[id] = lvl + 1;
saveGS();
toast('שודרג לרמה ' + (lvl + 1) + '!');
renderUpgrades();
updateMenu();
}
/* ==================== טבלת מובילים ==================== */
function goLeaderboard(){ renderLB(); showScreen('leaderboardScreen'); }
function renderLB(){
const tbody = document.getElementById('lbBody');
if(!tbody) return;
tbody.innerHTML = '';
const list = getTop5();
list.forEach((p, i) => {
const tr = document.createElement('tr');
tr.innerHTML = `<td>${i + 1}</td><td>${p.name}</td><td>${p.trophies}</td>`;
tbody.appendChild(tr);
});
if(list.length === 0){
tbody.innerHTML = '<tr><td colspan="3">אין נתונים עדיין</td></tr>';
}
}
/* ==================== פרסים ==================== */
function goRewards(){ renderRewards(); showScreen('rewardsScreen'); }
function renderRewards(){
const g = document.getElementById('rewardsGrid');
if(!g) return;
g.innerHTML = '';
const floor = getTrophyFloor();
REWARD_DEFS.forEach((r, i) => {
const el = document.createElement('div');
const claimed = GS.rewardsClaimed.includes(i);
const available = GS.trophies >= floor + r.offset;
el.className = 'reward-item ' + (claimed ? 'claimed' : available ? 'available' : 'locked');
el.innerHTML = `<div class="reward-icon">${r.icon}</div><div class="reward-info"><div class="reward-title">${r.title}</div><div class="reward-desc">${r.desc}</div><div class="reward-trophy">נדרש: ${floor + r.offset} גביעים</div></div>${claimed ? '<div class="reward-check">✓</div>' : ''}`;
if(available && !claimed) el.onclick = () => claimReward(i);
g.appendChild(el);
});
}
function claimReward(idx){
if(GS.rewardsClaimed.includes(idx)) return;
const r = REWARD_DEFS[idx];
GS.rewardsClaimed.push(idx);
if(r.type === 'coins'){
GS.coins += r.amount;
toast('קיבלת ' + r.amount + ' מטבעות!');
} else if(r.type === 'coinChest'){
openCoinChest();
} else if(r.type === 'charChest'){
openCharChestReward();
}
saveGS();
renderRewards();
updateMenu();
}
/* ==================== תיבות ==================== */
let pendingCoinReward = 0;
function openCoinChest(){
pendingCoinReward = 50 + Math.floor(Math.random() * 100);
const overlay = document.getElementById('chestOverlay');
const visual = document.getElementById('chestVisual');
const reward = document.getElementById('chestReward');
const cont = document.getElementById('chestContinue');
if(overlay) overlay.classList.add('on');
if(visual) visual.classList.remove('opened');
if(reward) reward.textContent = '';
if(cont) cont.style.display = 'none';
}
function openChest(){
const v = document.getElementById('chestVisual');
if(!v || v.classList.contains('opened')) return;
v.classList.add('opened');
const reward = document.getElementById('chestReward');
const cont = document.getElementById('chestContinue');
if(reward) reward.textContent = '💰 ' + pendingCoinReward + ' מטבעות!';
if(cont) cont.style.display = 'inline-block';
GS.coins += pendingCoinReward;
saveGS();
updateMenu();
}
function closeChest(){
const overlay = document.getElementById('chestOverlay');
if(overlay) overlay.classList.remove('on');
}
let pendingCharId = null;
function openCharChestReward(){
const locked = CHARS.filter(c => !isUnl(c.id) && canUnl(c.id));
if(locked.length === 0){
toast('אין דמויות חדשות לפתיחה!');
GS.coins += 200;
return;
}
pendingCharId = locked[Math.floor(Math.random() * locked.length)].id;
const overlay = document.getElementById('charChestOverlay');
const visual = document.getElementById('charChestVisual');
const reward = document.getElementById('charChestReward');
const cont = document.getElementById('charChestContinue');
if(overlay) overlay.classList.add('on');
if(visual) visual.classList.remove('opened');
if(reward) reward.textContent = '';
if(cont) cont.style.display = 'none';
}
function openCharChest(){
const v = document.getElementById('charChestVisual');
if(!v || v.classList.contains('opened')) return;
v.classList.add('opened');
const c = CHARS.find(x => x.id === pendingCharId);
const reward = document.getElementById('charChestReward');
const cont = document.getElementById('charChestContinue');
if(reward) reward.innerHTML = c ? c.icon + '<br><span style="font-size:1.2rem">' + c.name + '</span>' : '';
if(cont) cont.style.display = 'inline-block';
if(pendingCharId != null && !GS.unlocked.includes(pendingCharId)){
GS.unlocked.push(pendingCharId);
}
saveGS();
updateMenu();
}
function closeCharChest(){
const overlay = document.getElementById('charChestOverlay');
if(overlay) overlay.classList.remove('on');
}
/* ==================== רוח רפאים ==================== */
document.addEventListener('mousemove', e => {
const ghost = document.getElementById('ghost');
if(selCard < 0 || !ghost) return;
const arena = document.getElementById('arena');
if(!arena) return;
const rect = arena.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
if(x > 0 && x < rect.width && y > 0 && y < rect.height){
ghost.style.left = (x - 20) + 'px';
ghost.style.top = (y - 20) + 'px';
ghost.style.display = 'block';
} else {
ghost.style.display = 'none';
}
});
/* ==================== אתחול ==================== */
updateMenu();
updateRewards();
</script>
</body>
</html>
Game Source: Battle Realms
Creator: FrozenOtter31
Libraries: none
Complexity: complex (1241 lines, 61.1 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: battle-realms-frozenotter31-mst8p4ti" to link back to the original. Then publish at arcadelab.ai/publish.