<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PokeAPI ポケモンバトル & ボール選択</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
@import url('https://fonts.googleapis.com/css2?family=DotGothic16&display=swap');
body {
font-family: 'Helvetica Neue', Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
background-color: #2c3e50;
color: #333;
overflow-x: hidden;
}
.pixel-font {
font-family: 'DotGothic16', sans-serif;
}
.battle-screen {
background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 60%, #90EE90 60%, #90EE90 100%);
position: relative;
height: 350px;
border-radius: 8px;
overflow: hidden;
box-shadow: inset 0 0 50px rgba(0,0,0,0.2);
}
.pokemon-img {
image-rendering: pixelated;
transition: transform 0.3s ease, opacity 0.5s ease, filter 0.5s;
}
.evolving {
animation: evolveEffect 2s infinite;
}
@keyframes evolveEffect {
0% { filter: brightness(1) contrast(1); transform: scale(1); }
50% { filter: brightness(5) contrast(0); transform: scale(1.1); }
100% { filter: brightness(1) contrast(1); transform: scale(1); }
}
.hp-bar {
height: 10px;
transition: width 0.5s ease-in-out;
}
.shake {
animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes shake {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }
}
.attack-player {
animation: attackPlayer 0.5s ease-in-out;
}
@keyframes attackPlayer {
0% { transform: translateX(0); }
50% { transform: translateX(30px) translateY(-20px); }
100% { transform: translateX(0); }
}
.attack-enemy {
animation: attackEnemy 0.5s ease-in-out;
}
@keyframes attackEnemy {
0% { transform: translateX(0); }
50% { transform: translateX(-30px) translateY(20px); }
100% { transform: translateX(0); }
}
.throw-ball {
position: absolute;
bottom: 50px;
left: 50px;
z-index: 50;
animation: throw 1s forwards cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@keyframes throw {
0% { transform: translate(0, 0) rotate(0deg); opacity: 1; }
50% { transform: translate(150px, -150px) rotate(360deg); }
100% { transform: translate(250px, -80px) rotate(720deg); opacity: 0; }
}
.message-box {
background-color: rgba(255, 255, 255, 0.9);
border: 4px solid #333;
min-height: 85px;
}
.controls-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.loader {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.collection-item {
image-rendering: pixelated;
background: #f8f9fa;
border: 2px solid #ddd;
transition: all 0.2s;
cursor: pointer;
position: relative;
}
.collection-item:hover {
transform: scale(1.1);
border-color: #3498db;
}
.collection-item.active {
border-color: #e74c3c;
background: #ffebee;
}
.evolve-ready::after {
content: '▲';
position: absolute;
top: -5px;
right: -5px;
color: #f1c40f;
font-size: 10px;
text-shadow: 0 0 2px black;
animation: bounce 1s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-3px); }
}
.starter-card {
cursor: pointer;
transition: all 0.2s;
border: 3px solid transparent;
}
.starter-card:hover {
transform: translateY(-5px);
border-color: #3498db;
background-color: #ebf8ff;
}
.ball-menu-btn {
transition: all 0.2s;
}
.ball-menu-btn:hover {
filter: brightness(1.1);
transform: scale(1.02);
}
</style>
</head>
<body class="flex flex-col items-center justify-center min-h-screen p-4 bg-slate-800">
<div id="game-container" class="max-w-md w-full bg-white rounded-xl shadow-2xl overflow-hidden border-4 border-gray-800">
<!-- 相棒選択画面 -->
<div id="starter-selection" class="p-6">
<h2 class="text-xl font-bold text-center mb-4 pixel-font">さいしょの ポケモンを えらぼう!</h2>
<div class="grid grid-cols-3 gap-3" id="starter-list"></div>
<div id="selection-loader" class="mt-8 flex flex-col items-center">
<div class="loader mb-2"></div>
<p class="text-sm text-gray-500">博士が準備中...</p>
</div>
</div>
<!-- バトル画面 -->
<div id="battle-area" class="hidden">
<div class="battle-screen p-4 flex flex-col justify-between">
<div id="ball-layer"></div>
<!-- 相手エリア -->
<div class="flex justify-start items-start">
<div id="enemy-stats" class="bg-white/90 p-2 rounded-lg border-2 border-gray-700 w-52 shadow-md">
<div class="flex justify-between items-center mb-1">
<span id="enemy-name" class="font-bold text-sm">読み込み中...</span>
<span class="text-[10px] font-bold">Lv.50</span>
</div>
<div class="w-full bg-gray-300 rounded-full border border-gray-400">
<div id="enemy-hp-fill" class="hp-bar bg-green-500 rounded-full" style="width: 100%"></div>
</div>
<div class="text-right text-[10px] mt-1 font-bold" id="enemy-hp-text">0/0</div>
</div>
<div id="enemy-sprite-container" class="ml-auto">
<img id="enemy-img" src="" alt="Enemy" class="w-32 h-32 pokemon-img object-contain">
</div>
</div>
<!-- プレイヤーエリア -->
<div class="flex justify-end items-end">
<div id="player-sprite-container" class="mr-auto">
<img id="player-img" src="" alt="Player" class="w-40 h-40 pokemon-img object-contain">
</div>
<div id="player-stats" class="bg-white/90 p-2 rounded-lg border-2 border-gray-700 w-52 shadow-md">
<div class="flex justify-between items-center mb-1">
<span id="player-name" class="font-bold text-sm">読み込み中...</span>
<span class="text-[10px] font-bold">Lv.50</span>
</div>
<div class="w-full bg-gray-300 rounded-full border border-gray-400">
<div id="player-hp-fill" class="hp-bar bg-green-500 rounded-full" style="width: 100%"></div>
</div>
<div class="text-right text-[10px] mt-1 font-bold" id="player-hp-text">0/0</div>
</div>
</div>
</div>
<div id="log-container" class="message-box p-3 m-2 rounded-lg border-double border-4 flex flex-col justify-center">
<p id="message-text" class="text-sm font-bold leading-relaxed pixel-font">ポケモンのデータを取得しています...</p>
<div id="evolution-btn-container" class="hidden mt-2">
<button onclick="evolveActivePokemon()" class="w-full bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-1 px-4 rounded shadow-md text-xs pixel-font animate-pulse">
おや!? 様子が おかしいぞ! (進化させる)
</button>
</div>
</div>
<div id="controls" class="p-3 bg-gray-200 border-t-4 border-gray-800">
<div id="action-controls">
<div class="controls-grid" id="move-buttons"></div>
<div class="mt-2 flex gap-2">
<button onclick="healPlayer()" class="flex-1 bg-green-600 hover:bg-green-700 text-white font-bold py-2 rounded shadow-md text-xs transition-colors">
きずぐすり
</button>
<button onclick="toggleBallMenu()" class="flex-1 bg-red-600 hover:bg-red-700 text-white font-bold py-2 rounded shadow-md text-xs transition-colors">
モンスターボール
</button>
<button id="next-battle-btn" onclick="startNewBattle()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-3 rounded shadow-md text-xs transition-colors">
つぎのあいて
</button>
</div>
</div>
<!-- ボール選択メニュー -->
<div id="ball-selection-menu" class="hidden">
<p class="text-[10px] font-bold text-gray-600 mb-2 px-1">どのボールをなげる?</p>
<div class="grid grid-cols-3 gap-2">
<button onclick="catchWithBall('common')" class="ball-menu-btn bg-white border-2 border-red-500 p-2 rounded flex flex-col items-center">
<span class="text-lg">⚾</span>
<span class="text-[9px] font-bold">通常</span>
</button>
<button onclick="catchWithBall('great')" class="ball-menu-btn bg-white border-2 border-blue-500 p-2 rounded flex flex-col items-center">
<span class="text-lg">🔵</span>
<span class="text-[9px] font-bold">スーパー</span>
</button>
<button onclick="catchWithBall('ultra')" class="ball-menu-btn bg-white border-2 border-yellow-500 p-2 rounded flex flex-col items-center">
<span class="text-lg">🟡</span>
<span class="text-[9px] font-bold">ハイパー</span>
</button>
</div>
<button onclick="toggleBallMenu()" class="w-full mt-2 text-[10px] font-bold text-gray-500 py-1 underline">キャンセル</button>
</div>
</div>
</div>
<!-- ローディング中 -->
<div id="main-loader" class="p-8 hidden flex flex-col items-center justify-center">
<div class="loader mb-4"></div>
<p class="text-gray-600 font-bold">準備中...</p>
</div>
</div>
<!-- 手持ちポケモン・コレクション -->
<div class="max-w-md w-full mt-4 p-4 bg-white/10 rounded-xl backdrop-blur-sm border-2 border-white/20">
<h3 class="text-white font-bold text-sm mb-2 flex items-center justify-between">
<span><i class="fas fa-briefcase mr-2"></i> 手持ち・コレクション</span>
<span class="text-[10px] opacity-80">2回勝つと進化できるかも?</span>
</h3>
<div id="collection-list" class="flex flex-wrap gap-2 min-h-[50px]"></div>
</div>
<script>
const API_URL = "https://pokeapi.co/api/v2/pokemon/";
const SPECIES_URL = "https://pokeapi.co/api/v2/pokemon-species/";
const MAX_POKEMON = 1010;
const EVOLVE_THRESHOLD = 2;
let activePartnerId = null;
let player = null;
let enemy = null;
let isProcessing = false;
let capturedPokemons = [];
const ballData = {
common: { name: "モンスターボール", rate: 1.0, icon: "⚾" },
great: { name: "スーパーボール", rate: 1.5, icon: "🔵" },
ultra: { name: "ハイパーボール", rate: 2.0, icon: "🟡" }
};
const typeChart = {
fire: { water: 0.5, grass: 2.0, fire: 0.5, ice: 2.0, bug: 2.0, steel: 2.0, rock: 0.5 },
water: { fire: 2.0, grass: 0.5, water: 0.5, ground: 2.0, rock: 2.0 },
grass: { water: 2.0, fire: 0.5, grass: 0.5, ground: 2.0, rock: 2.0, poison: 0.5, flying: 0.5, bug: 0.5, steel: 0.5 },
electric: { water: 2.0, grass: 0.5, electric: 0.5, flying: 2.0, ground: 0 },
normal: { rock: 0.5, ghost: 0, steel: 0.5 },
dark: { psychic: 2.0, ghost: 2.0, dark: 0.5, fairy: 0.5, fighting: 0.5 },
ghost: { ghost: 2.0, psychic: 2.0, normal: 0, dark: 0.5 }
};
function getJapaneseName(names) {
const ja = names.find(n => n.language.name === 'ja-Hrkt' || n.language.name === 'ja');
return ja ? ja.name : names[0].name;
}
async function fetchPokemon(id) {
const [pokeRes, speciesRes] = await Promise.all([
fetch(`${API_URL}${id}`),
fetch(`${SPECIES_URL}${id}`)
]);
const data = await pokeRes.json();
const speciesData = await speciesRes.json();
const japaneseName = getJapaneseName(speciesData.names);
const moves = await Promise.all(
data.moves.slice(0, 4).map(async (m) => {
const moveRes = await fetch(m.move.url);
const moveData = await moveRes.json();
return {
name: getJapaneseName(moveData.names),
power: moveData.power || 40,
type: moveData.type.name
};
})
);
const gen5Sprite = data.sprites.versions['generation-v']['black-white']?.animated;
const frontSprite = gen5Sprite?.front_default || data.sprites.front_default;
const backSprite = gen5Sprite?.back_default || data.sprites.back_default;
return {
id: data.id,
name: japaneseName,
hp: data.stats[0].base_stat * 2,
maxHp: data.stats[0].base_stat * 2,
attack: data.stats[1].base_stat,
defense: data.stats[2].base_stat,
sprite: frontSprite,
backSprite: backSprite,
staticSprite: data.sprites.front_default,
moves: moves,
types: data.types.map(t => t.type.name),
speciesUrl: data.species.url,
wins: 0,
evolved: false
};
}
async function initStarterSelection() {
const starters = [1, 4, 7, 810, 813, 816];
const starterList = document.getElementById('starter-list');
for (const id of starters) {
try {
const pokemon = await fetchPokemon(id);
const card = document.createElement('div');
card.className = 'starter-card bg-white p-2 rounded-lg text-center shadow-sm border-gray-100 border';
card.onclick = () => selectPartner(pokemon);
card.innerHTML = `
<img src="${pokemon.staticSprite}" class="w-16 h-16 object-contain mx-auto">
<p class="text-[10px] font-bold mt-1">${pokemon.name}</p>
`;
starterList.appendChild(card);
} catch (e) { console.error(e); }
}
document.getElementById('selection-loader').classList.add('hidden');
}
async function selectPartner(pokemon) {
addCollection(pokemon);
switchActivePokemon(pokemon.id);
document.getElementById('starter-selection').classList.add('hidden');
document.getElementById('battle-area').classList.remove('hidden');
startNewBattle();
}
function switchActivePokemon(id) {
const target = capturedPokemons.find(p => p.id === id);
if (!target) return;
activePartnerId = id;
player = JSON.parse(JSON.stringify(target));
updateUI();
renderMoves();
renderCollection();
updateMessage(`${player.name} に 入れ替えた!`);
checkEvolutionAvailability();
}
async function startNewBattle() {
if (isProcessing) return;
isProcessing = true;
document.getElementById('evolution-btn-container').classList.add('hidden');
document.getElementById('ball-selection-menu').classList.add('hidden');
document.getElementById('action-controls').classList.remove('hidden');
document.getElementById('main-loader').classList.remove('hidden');
document.getElementById('controls').classList.add('hidden');
document.getElementById('player-img').style.opacity = '1';
document.getElementById('enemy-img').style.opacity = '1';
try {
const currentPartner = capturedPokemons.find(p => p.id === activePartnerId);
player = JSON.parse(JSON.stringify(currentPartner));
const enemyID = Math.floor(Math.random() * MAX_POKEMON) + 1;
enemy = await fetchPokemon(enemyID);
updateUI();
renderMoves();
document.getElementById('main-loader').classList.add('hidden');
document.getElementById('controls').classList.remove('hidden');
updateMessage(`あ! 野生の ${enemy.name} が とびだしてきた!`);
isProcessing = false;
} catch (error) {
console.error(error);
isProcessing = false;
startNewBattle();
}
}
function updateUI() {
if (!player || !enemy) return;
document.getElementById('player-name').innerText = player.name;
document.getElementById('player-img').src = player.backSprite;
updateHPBar('player', player.hp, player.maxHp);
document.getElementById('enemy-name').innerText = enemy.name;
document.getElementById('enemy-img').src = enemy.sprite;
updateHPBar('enemy', enemy.hp, enemy.maxHp);
}
function updateHPBar(who, current, max) {
const percent = Math.max(0, (current / max) * 100);
const bar = document.getElementById(`${who}-hp-fill`);
const text = document.getElementById(`${who}-hp-text`);
bar.style.width = `${percent}%`;
text.innerText = `${Math.ceil(current)} / ${max}`;
if (percent < 20) bar.className = 'hp-bar bg-red-500 rounded-full';
else if (percent < 50) bar.className = 'hp-bar bg-yellow-500 rounded-full';
else bar.className = 'hp-bar bg-green-500 rounded-full';
}
function renderMoves() {
const container = document.getElementById('move-buttons');
container.innerHTML = '';
player.moves.forEach(move => {
const btn = document.createElement('button');
btn.className = 'bg-white hover:bg-gray-100 text-gray-800 border-2 border-gray-400 font-bold py-2 rounded text-[11px] shadow-sm transition-all active:translate-y-1';
btn.innerText = move.name;
btn.onclick = () => handleAttack(move);
container.appendChild(btn);
});
}
function updateMessage(text) {
document.getElementById('message-text').innerText = text;
}
async function performMove(attacker, defender, move, role) {
updateMessage(`${attacker.name} の ${move.name}!`);
const attackerImg = document.getElementById(`${role}-img`);
const defenderImg = document.getElementById(`${role === 'player' ? 'enemy' : 'player'}-img`);
attackerImg.classList.add(role === 'player' ? 'attack-player' : 'attack-enemy');
await new Promise(r => setTimeout(r, 500));
attackerImg.classList.remove(role === 'player' ? 'attack-player' : 'attack-enemy');
let multiplier = 1;
defender.types.forEach(defType => {
if (typeChart[move.type] && typeChart[move.type][defType] !== undefined) multiplier *= typeChart[move.type][defType];
});
const isCritical = Math.random() < 0.0625;
let damage = (((2 * 50 / 5 + 2) * move.power * (attacker.attack / defender.defense)) / 50) + 2;
damage *= multiplier;
if (isCritical) damage *= 1.5;
damage = Math.floor(damage * (Math.random() * 0.15 + 0.85));
defender.hp = Math.max(0, defender.hp - damage);
defenderImg.classList.add('shake');
updateHPBar(role === 'player' ? 'enemy' : 'player', defender.hp, defender.maxHp);
await new Promise(r => setTimeout(r, 400));
defenderImg.classList.remove('shake');
if (isCritical) { updateMessage("急所に あたった!"); await new Promise(r => setTimeout(r, 800)); }
if (multiplier > 1) { updateMessage("効果は バツグンだ!"); await new Promise(r => setTimeout(r, 800)); }
else if (multiplier > 0 && multiplier < 1) { updateMessage("効果は いまひとつの ようだ..."); await new Promise(r => setTimeout(r, 800)); }
}
async function handleAttack(move) {
if (isProcessing || player.hp <= 0 || enemy.hp <= 0) return;
isProcessing = true;
await performMove(player, enemy, move, 'player');
if (enemy.hp <= 0) {
updateMessage(`相手の ${enemy.name} は たおれた!`);
recordWin();
triggerVictory();
return;
}
await enemyTurn();
}
async function enemyTurn() {
await new Promise(r => setTimeout(r, 1000));
if (enemy.hp <= 0) return;
const enemyMove = enemy.moves[Math.floor(Math.random() * enemy.moves.length)];
await performMove(enemy, player, enemyMove, 'enemy');
if (player.hp <= 0) {
updateMessage(`${player.name} は たおれてしまった...`);
triggerGameOver();
return;
}
isProcessing = false;
}
function toggleBallMenu() {
if (isProcessing || player.hp <= 0 || enemy.hp <= 0) return;
const action = document.getElementById('action-controls');
const menu = document.getElementById('ball-selection-menu');
if (menu.classList.contains('hidden')) {
action.classList.add('hidden');
menu.classList.remove('hidden');
} else {
action.classList.remove('hidden');
menu.classList.add('hidden');
}
}
async function catchWithBall(ballType) {
toggleBallMenu();
if (isProcessing) return;
isProcessing = true;
const selectedBall = ballData[ballType];
updateMessage(`${player.name} は ${selectedBall.name} を なげた!`);
const ball = document.createElement('div');
ball.className = 'throw-ball text-2xl';
ball.innerHTML = selectedBall.icon;
document.getElementById('ball-layer').appendChild(ball);
await new Promise(r => setTimeout(r, 1000));
ball.remove();
const hpRatio = enemy.hp / enemy.maxHp;
// ボールの種類によって捕獲率を調整 (通常よりハイパーの方が捕まえやすい)
const catchProbability = (0.2 + (0.7 * (1 - hpRatio))) * selectedBall.rate;
const isSuccess = Math.random() < catchProbability;
if (isSuccess) {
document.getElementById('enemy-img').style.opacity = '0';
updateMessage(`やったー! ${enemy.name} を つかまえたぞ!`);
recordWin();
addCollection(enemy);
showReset();
} else {
updateMessage(`だめだ! ${enemy.name} は ボールから ぬけだした!`);
await enemyTurn();
}
}
function recordWin() {
const p = capturedPokemons.find(p => p.id === activePartnerId);
if (p) {
p.wins++;
renderCollection();
checkEvolutionAvailability();
}
}
async function checkEvolutionAvailability() {
const p = capturedPokemons.find(p => p.id === activePartnerId);
if (p && p.wins >= EVOLVE_THRESHOLD) {
const nextEvoId = await getNextEvolutionId(p.speciesUrl, p.id);
if (nextEvoId) {
p.nextEvoId = nextEvoId;
document.getElementById('evolution-btn-container').classList.remove('hidden');
}
}
}
async function getNextEvolutionId(speciesUrl, currentId) {
try {
const speciesRes = await fetch(speciesUrl);
const speciesData = await speciesRes.json();
const evoRes = await fetch(speciesData.evolution_chain.url);
const evoData = await evoRes.json();
let current = evoData.chain;
const findInChain = (node, id) => {
const nodeUrlParts = node.species.url.split('/');
const nodeId = parseInt(nodeUrlParts[nodeUrlParts.length - 2]);
if (nodeId === id) return node;
for (let next of node.evolves_to) {
const found = findInChain(next, id);
if (found) return found;
}
return null;
};
const currentNode = findInChain(current, currentId);
if (currentNode && currentNode.evolves_to.length > 0) {
const nextUrlParts = currentNode.evolves_to[0].species.url.split('/');
return parseInt(nextUrlParts[nextUrlParts.length - 2]);
}
return null;
} catch (e) {
console.error("Evolution check failed:", e);
return null;
}
}
async function evolveActivePokemon() {
if (isProcessing) return;
isProcessing = true;
const p = capturedPokemons.find(p => p.id === activePartnerId);
if (!p || !p.nextEvoId) return;
document.getElementById('evolution-btn-container').classList.add('hidden');
document.getElementById('controls').classList.add('hidden');
updateMessage(`${p.name} の 様子が......!`);
const playerImg = document.getElementById('player-img');
playerImg.classList.add('evolving');
await new Promise(r => setTimeout(r, 2500));
const newPokemon = await fetchPokemon(p.nextEvoId);
newPokemon.wins = 0;
const index = capturedPokemons.findIndex(x => x.id === p.id);
capturedPokemons[index] = newPokemon;
activePartnerId = newPokemon.id;
player = JSON.parse(JSON.stringify(newPokemon));
playerImg.classList.remove('evolving');
updateUI();
renderMoves();
renderCollection();
updateMessage(`おめでとう! ${p.name} は ${newPokemon.name} に 進化した!`);
await new Promise(r => setTimeout(r, 2000));
document.getElementById('controls').classList.remove('hidden');
isProcessing = false;
}
function addCollection(pokemon) {
if (capturedPokemons.some(p => p.id === pokemon.id)) return;
capturedPokemons.push(pokemon);
renderCollection();
}
function renderCollection() {
const list = document.getElementById('collection-list');
list.innerHTML = '';
capturedPokemons.forEach(p => {
const item = document.createElement('div');
const isActive = p.id === activePartnerId;
const canEvolve = p.wins >= EVOLVE_THRESHOLD;
item.className = `collection-item w-12 h-12 rounded-lg flex items-center justify-center p-1 border-2 ${isActive ? 'active' : 'border-gray-200'} ${canEvolve ? 'evolve-ready' : ''}`;
item.onclick = () => {
if (isProcessing && player.hp > 0 && enemy.hp > 0) {
updateMessage("バトル中は入れ替えられません!");
return;
}
switchActivePokemon(p.id);
};
item.innerHTML = `<img src="${p.staticSprite}" class="w-full h-full object-contain" title="${p.name} (勝利数: ${p.wins})">`;
list.appendChild(item);
});
}
async function healPlayer() {
if (isProcessing || player.hp <= 0) return;
isProcessing = true;
player.hp = Math.min(player.maxHp, player.hp + Math.floor(player.maxHp * 0.4));
updateMessage(`${player.name} は きずぐすりを つかった!`);
updateHPBar('player', player.hp, player.maxHp);
await enemyTurn();
}
function triggerVictory() { document.getElementById('enemy-img').style.opacity = '0'; showReset(); }
function triggerGameOver() { document.getElementById('player-img').style.opacity = '0'; showReset(); }
function showReset() {
document.getElementById('move-buttons').innerHTML = `
<button onclick="startNewBattle()" class="col-span-2 bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded text-xs shadow-lg">
別のポケモンを探す
</button>`;
isProcessing = false;
}
window.onload = initStarterSelection;
</script>
</body>
</html>
ポケモンの作品