Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Tiny Healer</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
margin: 0; | |
background-color: #1a1a1a; | |
color: white; | |
} | |
#game-container { | |
width: 800px; | |
height: 600px; | |
border: 2px solid #333; | |
padding: 20px; | |
background-color: #222; | |
} | |
#combat-window { | |
display: flex; | |
justify-content: space-between; | |
margin-bottom: 20px; | |
} | |
#allies { | |
width: 45%; | |
} | |
#boss { | |
width: 45%; | |
} | |
.health-bar { | |
height: 30px; | |
background-color: #4CAF50; | |
margin-bottom: 10px; | |
position: relative; | |
cursor: pointer; | |
} | |
.health-bar.selected { | |
background-color: #2196F3; | |
} | |
.health-bar-text { | |
position: absolute; | |
width: 100%; | |
text-align: center; | |
line-height: 30px; | |
} | |
#boss-health-bar { | |
height: 50px; | |
background-color: #f44336; | |
} | |
#spell-buttons { | |
display: flex; | |
justify-content: space-between; | |
margin-bottom: 10px; | |
} | |
.spell-button { | |
width: 18%; | |
height: 50px; | |
background-color: #008CBA; | |
border: none; | |
color: white; | |
text-align: center; | |
text-decoration: none; | |
display: inline-block; | |
font-size: 14px; | |
margin: 4px 2px; | |
cursor: pointer; | |
position: relative; | |
overflow: hidden; | |
} | |
.spell-button:disabled { | |
background-color: #555; | |
cursor: not-allowed; | |
} | |
.cooldown-progress { | |
position: absolute; | |
top: 0; | |
left: 0; | |
height: 100%; | |
width: 0; | |
background-color: rgba(0, 0, 0, 0.5); | |
transition: width linear; | |
} | |
#spellbook { | |
width: 100%; | |
padding: 10px; | |
background-color: #333; | |
border: none; | |
color: white; | |
font-size: 16px; | |
margin-top: 10px; | |
} | |
#spell-info { | |
margin-top: 10px; | |
padding: 10px; | |
background-color: #444; | |
border-radius: 5px; | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="game-container"> | |
<div id="combat-window"> | |
<div id="allies"></div> | |
<div id="boss"> | |
<div id="boss-health-bar" class="health-bar"> | |
<div class="health-bar-text">Boss HP: 5000/5000</div> | |
</div> | |
</div> | |
</div> | |
<div id="spell-buttons"></div> | |
<select id="spellbook"> | |
<option value="">Spellbook - Select a spell for info</option> | |
<option value="0">Quick Heal</option> | |
<option value="1">Strong Heal</option> | |
<option value="2">Healing Stream</option> | |
<option value="3">Chain Heal</option> | |
<option value="4">Team Heal</option> | |
</select> | |
<div id="spell-info"></div> | |
</div> | |
<script> | |
const allies = []; | |
let boss = { hp: 5000, maxHp: 5000 }; | |
let selectedAlly = null; | |
let globalCooldown = false; | |
const spells = [ | |
{ name: "Quick Heal", cooldown: 1.5, heal: 10, description: "Heals the target for 10 HP. Global cooldown: 1.5 seconds." }, | |
{ name: "Strong Heal", cooldown: 15, heal: 30, description: "Heals the target for 30 HP. Cooldown: 15 seconds." }, | |
{ name: "Healing Stream", cooldown: 45, heal: 3, duration: 10, interval: 0.5, description: "Heals the target for 3 HP every 0.5 seconds for 10 seconds. Cooldown: 45 seconds." }, | |
{ name: "Chain Heal", cooldown: 15, heal: 10, targets: 3, description: "Heals 3 random allies for 10 HP each. Cooldown: 15 seconds." }, | |
{ name: "Team Heal", cooldown: 120, heal: 50, description: "Heals all allies for 50 HP. Cooldown: 2 minutes." } | |
]; | |
function createAlly(id) { | |
return { id, hp: 100, maxHp: 100 }; | |
} | |
function updateHealthBar(entity, barElement) { | |
const percentage = (entity.hp / entity.maxHp) * 100; | |
barElement.style.width = `${percentage}%`; | |
barElement.querySelector('.health-bar-text').textContent = `HP: ${entity.hp}/${entity.maxHp}`; | |
} | |
function createAllies() { | |
const alliesContainer = document.getElementById('allies'); | |
for (let i = 0; i < 5; i++) { | |
const ally = createAlly(i); | |
allies.push(ally); | |
const healthBar = document.createElement('div'); | |
healthBar.className = 'health-bar'; | |
healthBar.innerHTML = `<div class="health-bar-text">Ally ${i + 1} HP: 100/100</div>`; | |
healthBar.onclick = () => selectAlly(i); | |
alliesContainer.appendChild(healthBar); | |
updateHealthBar(ally, healthBar); | |
} | |
} | |
function selectAlly(index) { | |
const healthBars = document.querySelectorAll('#allies .health-bar'); | |
healthBars.forEach(bar => bar.classList.remove('selected')); | |
healthBars[index].classList.add('selected'); | |
selectedAlly = allies[index]; | |
updateSpellButtons(); | |
} | |
function createSpellButtons() { | |
const spellButtonsContainer = document.getElementById('spell-buttons'); | |
spells.forEach((spell, index) => { | |
const button = document.createElement('button'); | |
button.className = 'spell-button'; | |
button.innerHTML = `${spell.name}<div class="cooldown-progress"></div>`; | |
button.onclick = () => castSpell(index); | |
button.disabled = true; | |
spellButtonsContainer.appendChild(button); | |
}); | |
} | |
function updateSpellButtons() { | |
const spellButtons = document.querySelectorAll('.spell-button'); | |
spellButtons.forEach((button, index) => { | |
button.disabled = !selectedAlly || globalCooldown || button.classList.contains('on-cooldown'); | |
}); | |
} | |
function castSpell(spellIndex) { | |
if (selectedAlly && !globalCooldown && !document.querySelectorAll('.spell-button')[spellIndex].classList.contains('on-cooldown')) { | |
const spell = spells[spellIndex]; | |
switch (spellIndex) { | |
case 0: | |
case 1: | |
healAlly(selectedAlly, spell.heal); | |
break; | |
case 2: | |
startHealingStream(selectedAlly, spell); | |
break; | |
case 3: | |
chainHeal(spell); | |
break; | |
case 4: | |
teamHeal(spell); | |
break; | |
} | |
startSpellCooldown(spellIndex); | |
startGlobalCooldown(); | |
} | |
} | |
function healAlly(ally, amount) { | |
ally.hp = Math.min(ally.hp + amount, ally.maxHp); | |
updateHealthBar(ally, document.querySelectorAll('.health-bar')[ally.id]); | |
} | |
function startHealingStream(ally, spell) { | |
let ticks = spell.duration / spell.interval; | |
function tick() { | |
if (ticks > 0) { | |
healAlly(ally, spell.heal); | |
ticks--; | |
setTimeout(tick, spell.interval * 1000); | |
} | |
} | |
tick(); | |
} | |
function chainHeal(spell) { | |
const targets = allies.sort(() => 0.5 - Math.random()).slice(0, spell.targets); | |
targets.forEach(ally => healAlly(ally, spell.heal)); | |
} | |
function teamHeal(spell) { | |
allies.forEach(ally => healAlly(ally, spell.heal)); | |
} | |
function startSpellCooldown(spellIndex) { | |
const button = document.querySelectorAll('.spell-button')[spellIndex]; | |
const progressBar = button.querySelector('.cooldown-progress'); | |
button.classList.add('on-cooldown'); | |
progressBar.style.transition = `width ${spells[spellIndex].cooldown}s linear`; | |
progressBar.style.width = '100%'; | |
setTimeout(() => { | |
button.classList.remove('on-cooldown'); | |
progressBar.style.width = '0'; | |
updateSpellButtons(); | |
}, spells[spellIndex].cooldown * 1000); | |
} | |
function startGlobalCooldown() { | |
globalCooldown = true; | |
updateSpellButtons(); | |
setTimeout(() => { | |
globalCooldown = false; | |
updateSpellButtons(); | |
}, 1500); | |
} | |
function bossDamage() { | |
const damageAmount = 8; | |
const targetAlly = allies[Math.floor(Math.random() * allies.length)]; | |
targetAlly.hp = Math.max(targetAlly.hp - damageAmount, 0); | |
updateHealthBar(targetAlly, document.querySelectorAll('.health-bar')[targetAlly.id]); | |
} | |
function gameLoop() { | |
bossDamage(); | |
setTimeout(gameLoop, 1000); | |
} | |
document.addEventListener('keydown', (event) => { | |
const key = event.key; | |
if (key >= '1' && key <= '5') { | |
castSpell(parseInt(key) - 1); | |
} | |
}); | |
document.getElementById('spellbook').addEventListener('change', (event) => { | |
const spellIndex = event.target.value; | |
const spellInfo = document.getElementById('spell-info'); | |
if (spellIndex !== "") { | |
spellInfo.textContent = spells[spellIndex].description; | |
spellInfo.style.display = 'block'; | |
} else { | |
spellInfo.style.display = 'none'; | |
} | |
}); | |
createAllies(); | |
createSpellButtons(); | |
updateHealthBar(boss, document.getElementById('boss-health-bar')); | |
gameLoop(); | |
</script> | |
</body> | |
</html> |