{"id":6,"date":"2025-08-29T09:57:05","date_gmt":"2025-08-29T09:57:05","guid":{"rendered":"http:\/\/hgkim.ddns.net\/?page_id=6"},"modified":"2025-08-29T09:57:05","modified_gmt":"2025-08-29T09:57:05","slug":"fvz","status":"publish","type":"page","link":"https:\/\/hgkim.ddns.net\/?page_id=6","title":{"rendered":"fvz"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"ko\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n    <title>\uacfc\uc77c vs \uc880\ube44 \ub514\ud39c\uc2a4 (\ucd5c\uc885\ud310)<\/title>\n    <style>\n        body, html { margin: 0; padding: 0; overflow: hidden; background-color: #333; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; user-select: none; -webkit-user-select: none; display: flex; justify-content: center; align-items: center; height: 100vh; }\n        #game-container { position: relative; width: 960px; height: 540px; background-color: #000; box-shadow: 0 0 20px rgba(0,0,0,0.7); }\n        #game-canvas { width: 100%; height: 100%; display: block; }\n        .game-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); color: white; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; z-index: 100; }\n        .game-overlay h1 { font-size: 3.5rem; margin-bottom: 20px; text-shadow: 3px 3px 5px black; }\n        .game-overlay button { font-size: 1.5rem; padding: 15px 30px; cursor: pointer; border: 2px solid white; background-color: #4CAF50; color: white; border-radius: 10px; transition: background-color 0.3s; }\n        .game-overlay button:hover { background-color: #45a049; }\n        #game-ui { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }\n        #top-bar { position: absolute; top: 10px; left: 0; width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 0 20px; box-sizing: border-box; color: white; text-shadow: 2px 2px 4px black; }\n        #top-bar > div { font-size: 20px; background-color: rgba(0,0,0,0.5); padding: 10px 15px; border-radius: 10px; }\n        #plant-selector { position: absolute; top: 70px; left: 10px; display: flex; flex-direction: column; gap: 8px; pointer-events: auto; }\n        .plant-card { width: 54px; padding: 5px; background-color: rgba(0, 0, 0, 0.5); border: 2px solid #ddd; border-radius: 10px; cursor: grab; text-align: center; color: white; transition: background-color 0.2s, border-color 0.2s; }\n        .plant-card div { font-size: 12px; }\n        .plant-card.disabled { background-color: rgba(50, 50, 50, 0.8); cursor: not-allowed; opacity: 0.6; }\n        .plant-card img { width: 70%; height: auto; pointer-events: none; }\n        .plant-card .cost { font-weight: bold; color: #FFEB3B; }\n        #countdown { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 120px; color: #FFEB3B; text-shadow: 5px 5px 10px black; z-index: 150; display: none; }\n        #drag-image-container { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 200; display: none; }\n        #drag-image-container img { width: 100%; height: 100%; opacity: 0.7; }\n        #creator-credit { position: absolute; bottom: 10px; right: 15px; font-size: 14px; color: white; text-shadow: 1px 1px 2px black; }\n    <\/style>\n<\/head>\n<body>\n    <div id=\"game-container\">\n        <canvas id=\"game-canvas\"><\/canvas>\n        <div id=\"game-ui\">\n            <div id=\"top-bar\"><div id=\"stage-info\">Stage: 1<\/div><div id=\"lives-info\">\ubaa9\uc228: \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f<\/div><div id=\"coins-info\">\ucf54\uc778: 15 \ud83d\udcb0<\/div><\/div>\n            <div id=\"plant-selector\"><\/div>\n            <div id=\"countdown\">5<\/div>\n            <div id=\"creator-credit\">\ub9cc\ub4e0\uc0ac\ub78c: \uae40\ud0dc\uc624<\/div>\n        <\/div>\n        <div id=\"start-screen\" class=\"game-overlay\"><h1 >\uacfc\uc77c vs \uc880\ube44 \ub514\ud39c\uc2a4<\/h1><button id=\"start-button\">\uac8c\uc784 \uc2dc\uc791<\/button><\/div>\n        <div id=\"game-over-screen\" class=\"game-overlay\" style=\"display: none;\"><h1>\uac8c\uc784 \uc624\ubc84<\/h1><button onclick=\"location.reload()\">\ub2e4\uc2dc \uc2dc\uc791<\/button><\/div>\n        <div id=\"stage-clear-screen\" class=\"game-overlay\" style=\"display: none;\"><h1>\uc2a4\ud14c\uc774\uc9c0 \ud074\ub9ac\uc5b4!<\/h1><button id=\"next-stage-button\">\ub2e4\uc74c \uc2a4\ud14c\uc774\uc9c0<\/button><\/div>\n        <div id=\"drag-image-container\"><img decoding=\"async\" id=\"dragged-image\" src=\"\"><\/div>\n    <\/div>\n\n    <script>\n        const canvas = document.getElementById('game-canvas'); const ctx = canvas.getContext('2d'); const gameContainer = document.getElementById('game-container'); const startScreen = document.getElementById('start-screen'); const gameOverScreen = document.getElementById('game-over-screen'); const stageClearScreen = document.getElementById('stage-clear-screen'); const startButton = document.getElementById('start-button'); const nextStageButton = document.getElementById('next-stage-button'); const countdownEl = document.getElementById('countdown'); const stageInfo = document.getElementById('stage-info'); const livesInfo = document.getElementById('lives-info'); const coinsInfo = document.getElementById('coins-info'); const plantSelector = document.getElementById('plant-selector'); const dragImageContainer = document.getElementById('drag-image-container'); const draggedImage = document.getElementById('dragged-image');\n        const ROWS = 5; const COLS = 10;\n        let GAME_WIDTH, GAME_HEIGHT, GRID_WIDTH, GRID_HEIGHT;\n        let gameState = 'start'; let coins = 15; let lives = 5; let stage = 1; let frame = 0;\n        let isDragging = false; let draggedPlantId = null;\n        let plants = []; let zombies = []; let projectiles = []; let suns = [];\n        let zombiesToSpawn = 50; let zombiesSpawned = 0; let zombieSpawnCounter = 0;\n        let zombieSpawnInterval = 600; let waveTriggered1 = false; let waveTriggered2 = false;\n        const images = {};\n        const imageUrls = { background1: 'https:\/\/img.freepik.com\/free-vector\/green-grass-border-isolated-white-background-botanical-herbal-summer-frame-meadow-lawn-field-foliage-plant-leaves-foliage-floral-element-template-vector-illustration_106796-2391.jpg?w=2000', lotusCannon: 'https:\/\/img.icons8.com\/color\/96\/000000\/lotus.png', appleCannon: 'https:\/\/img.icons8.com\/plasticine\/100\/000000\/apple.png', strawberry: 'https:\/\/img.icons8.com\/plasticine\/100\/000000\/strawberry.png', normalZombie: 'https:\/\/img.icons8.com\/plasticine\/100\/000000\/zombie.png', shieldZombie: 'https:\/\/img.icons8.com\/external-flaticons-lineal-color-flat-icons\/64\/000000\/external-zombie-halloween-flaticons-lineal-color-flat-icons-3.png', seed: 'https:\/\/img.icons8.com\/emoji\/48\/000000\/sunflower-emoji.png', sun: 'https:\/\/img.icons8.com\/color\/96\/000000\/sun--v1.png', cherryBomb: 'https:\/\/img.icons8.com\/flat-round\/64\/000000\/cherry.png', chili: 'https:\/\/img.icons8.com\/color\/96\/000000\/chili-pepper.png' };\n        \n        \/\/ [\ucd94\uac00] 50\uc885 \uacfc\uc77c \ub370\uc774\ud130 \ub9c8\uc2a4\ud130 \ubaa9\ub85d\n        const plantMasterList = [\n            { id: 'lotusCannon', name: '\uc5f0\uaf43 \ub300\ud3ec', baseCost: 5, type: 'attacker', image: 'lotusCannon', attackSpeed: 120, damage: 10 },\n            { id: 'appleCannon', name: '\uc0ac\uacfc \ub300\ud3ec', baseCost: 5, type: 'attacker', image: 'appleCannon', attackSpeed: 180, damage: 20 },\n            { id: 'strawberry', name: '\ub538\uae30 \uc790\uc6d0', baseCost: 5, type: 'generator', image: 'strawberry', attackSpeed: 120, damage: 0 },\n        ];\n        \/\/ 50\uc885\uc744 \ucc44\uc6b0\uae30 \uc704\ud55c \ub098\uba38\uc9c0 \uacfc\uc77c \uc790\ub3d9 \uc0dd\uc131 (\uc2e4\uc81c \uac8c\uc784\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc815\uc758\ud574\uc57c \ud568)\n        for (let i = 3; i < 50; i++) {\n            plantMasterList.push({\n                id: `plant${i}`,\n                name: `\uc2dd\ubb3c ${i+1}`,\n                baseCost: 0, \/\/ \ube44\uc6a9\uc740 \uc2a4\ud14c\uc774\uc9c0\uc5d0 \ub530\ub77c \uacb0\uc815\ub428\n                type: 'attacker',\n                image: i % 2 === 0 ? 'cherryBomb' : 'chili', \/\/ \uc774\ubbf8\uc9c0 \uc7ac\uc0ac\uc6a9\n                attackSpeed: 150 + (i * 5), \/\/ \uac08\uc218\ub85d \uacf5\uaca9\uc18d\ub3c4 \ub290\ub824\uc9d0\n                damage: 25 + (i * 2), \/\/ \uac08\uc218\ub85d \uac15\ud574\uc9d0\n            });\n        }\n        \n        function loadImages() { for (const key in imageUrls) { images[key] = new Image(); images[key].src = imageUrls[key]; } }\n        \n        function setCanvasSize() { GAME_WIDTH = canvas.width = 960; GAME_HEIGHT = canvas.height = 540; GRID_WIDTH = GAME_WIDTH \/ COLS; GRID_HEIGHT = GAME_HEIGHT \/ ROWS; }\n        \n        function updateUI() { stageInfo.textContent = `Stage: ${stage}`; livesInfo.innerHTML = `\ubaa9\uc228: ${'\u2764\ufe0f'.repeat(lives)}`; coinsInfo.innerHTML = `\ucf54\uc778: ${coins} \ud83d\udcb0`; document.querySelectorAll('.plant-card').forEach(card => card.classList.toggle('disabled', coins < parseInt(card.dataset.cost))); }\n        \n        function createPlantSelector() {\n            plantSelector.innerHTML = '';\n            \/\/ [\uc218\uc815] \uc2a4\ud14c\uc774\uc9c0\uc5d0 \ub530\ub77c \ud45c\uc2dc\ud560 \uacfc\uc77c \uc218\uac00 \uacb0\uc815\ub428 (\uae30\ubcf8 3\uac1c + \uc2a4\ud14c\uc774\uc9c0-1 \uac1c)\n            const unlockedPlantsCount = Math.min(3 + (stage - 1), plantMasterList.length);\n\n            for (let i = 0; i < unlockedPlantsCount; i++) {\n                const plantData = plantMasterList[i];\n                \/\/ [\uc218\uc815] \ube44\uc6a9 \uacc4\uc0b0 \ub85c\uc9c1\n                let displayCost = plantData.baseCost;\n                if (i >= 3) {\n                    const unlockStage = i - 3 + 2; \/\/ index 3\uc740 \uc2a4\ud14c\uc774\uc9c0 2\uc5d0 \ud574\uae08\ub428\n                    displayCost = unlockStage * 5;\n                }\n\n                const card = document.createElement('div');\n                card.className = 'plant-card'; card.dataset.plantId = plantData.id; card.dataset.cost = displayCost;\n                card.innerHTML = `<img decoding=\"async\" src=\"${imageUrls[plantData.image]}\" alt=\"${plantData.name}\"><div>${plantData.name}<\/div><div class=\"cost\">${displayCost} \ud83d\udcb0<\/div>`;\n                card.addEventListener('mousedown', handleDragStart); card.addEventListener('touchstart', handleDragStart);\n                plantSelector.appendChild(card);\n            }\n        }\n\n        function gameLoop() { if (gameState === 'playing' || gameState === 'countdown') { ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT); drawBackground(); suns.forEach(sun => sun.draw()); plants.forEach(plant => plant.draw()); zombies.forEach(zombie => zombie.draw()); projectiles.forEach(p => p.draw()); drawGrid(); if (gameState === 'playing') { handleSuns(); handlePlants(); handleProjectiles(); handleZombies(); handleCollisions(); } updateUI(); frame++; } requestAnimationFrame(gameLoop); }\n        function drawBackground() { if (images.background1 && images.background1.complete) { ctx.drawImage(images.background1, 0, 0, GAME_WIDTH, GAME_HEIGHT); } else { ctx.fillStyle = '#70c548'; ctx.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); }}\n        function drawGrid() { if(isDragging) { const rect = canvas.getBoundingClientRect(); const mouseX = currentMousePos.x - rect.left; const mouseY = currentMousePos.y - rect.top; const col = Math.floor(mouseX \/ GRID_WIDTH); const row = Math.floor(mouseY \/ GRID_HEIGHT); if (col < 3) { ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; ctx.fillRect(col * GRID_WIDTH, row * GRID_HEIGHT, GRID_WIDTH, GRID_HEIGHT); }}}\n\n        function handleSuns() { if (frame % ((Math.floor(Math.random() * 3) + 3) * 60) === 0) { suns.push(new Sun()); } suns.forEach((sun) => sun.update()); }\n        function handlePlants() { plants.forEach(plant => plant.update()); }\n        function handleProjectiles() { for (let i = projectiles.length - 1; i >= 0; i--) { projectiles[i].update(); if (projectiles[i].x > GAME_WIDTH) projectiles.splice(i, 1); } }\n        \n        function handleZombies() { if (zombiesSpawned < zombiesToSpawn &#038;&#038; frame > zombieSpawnCounter) { zombieSpawnCounter = frame + zombieSpawnInterval + Math.random() * 240 - 120; spawnZombie(); if (zombiesSpawned === 10 && !waveTriggered1) { waveTriggered1 = true; spawnWave(15); } if (zombiesSpawned === 35 && !waveTriggered2) { waveTriggered2 = true; spawnWave(15); } } for (let i = zombies.length - 1; i >= 0; i--) { const z = zombies[i]; z.update(); if (z.x + z.width < 0) { zombies.splice(i, 1); lives--; if (lives <= 0) { gameState = 'gameOver'; gameOverScreen.style.display = 'flex'; } } } }\n        function spawnZombie() { zombiesSpawned++; const row = Math.floor(Math.random() * ROWS); if (stage >= 5 && Math.random() < 0.3) { zombies.push(new ShieldZombie(row)); } else { zombies.push(new NormalZombie(row)); } }\n        function spawnWave(count) { for (let i = 0; i < count; i++) { setTimeout(spawnZombie, Math.random() * 1000); } }\n\n        function handleCollisions() { for (let i = projectiles.length - 1; i >= 0; i--) { const p = projectiles[i]; let hit = false; for (let z of zombies) { if (!hit && z.row === p.row && p.x > z.x && p.x < z.x + z.width) { if (!(z.type === 'shield' &#038;&#038; Math.random() < 0.5 &#038;&#038; p.type !== 'laser')) { z.health -= p.damage; } if (p.type !== 'laser') { hit = true; } } } if (hit) { projectiles.splice(i, 1); } } zombies.forEach(z => { let currentlyEating = false; plants.forEach(p => { if (p.row === z.row && z.x < p.x + p.width &#038;&#038; z.x + z.width > p.x) { currentlyEating = true; p.health -= 0.5; z.health -= 0.5; }}); z.isEating = currentlyEating; }); plants = plants.filter(p => p.health > 0); zombies = zombies.filter(z => z.health > 0); if (gameState === 'playing' && zombiesSpawned === zombiesToSpawn && zombies.length === 0) { gameState = 'stageClear'; stageClearScreen.style.display = 'flex'; } }\n        \n        class Sun { constructor() { this.x = Math.random() * (GAME_WIDTH - 50); this.y = -50; this.size = GRID_WIDTH * 0.4; this.speed = Math.random() * 1 + 1; this.value = 10; } update() { this.y += this.speed; } draw() { ctx.drawImage(images.sun, this.x, this.y, this.size, this.size); } }\n        class Plant { constructor(row, col, plantData) { this.row = row; this.col = col; this.x = col * GRID_WIDTH; this.y = row * GRID_HEIGHT; this.width = GRID_WIDTH; this.height = GRID_HEIGHT; this.plantData = plantData; this.image = images[this.plantData.image]; this.attackTimer = 0; this.health = 100; this.maxHealth = 100; this.isAttacking = false; this.attackFrame = 0; } draw() { let scale = 1, offsetX = 0, offsetY = 0; if (this.isAttacking) { const p = (10 - this.attackFrame) \/ 10; scale = 1 + Math.sin(p * Math.PI) * 0.2; this.attackFrame--; if (this.attackFrame <= 0) this.isAttacking = false; offsetX = (this.width * (1 - scale)) \/ 2; offsetY = (this.height * (1 - scale)) \/ 2; } ctx.drawImage(this.image, this.x + offsetX, this.y + offsetY, this.width * scale, this.height * scale); if (this.health < this.maxHealth) { ctx.fillStyle = 'red'; ctx.fillRect(this.x, this.y, this.width, 5); ctx.fillStyle = 'green'; ctx.fillRect(this.x, this.y, this.width * (this.health \/ this.maxHealth), 5); }}\n            update() {\n                if (this.plantData.type === 'attacker') {\n                    this.attackTimer++;\n                    if (this.attackTimer % this.plantData.attackSpeed === 0) {\n                        projectiles.push(new Projectile(this.row, this.col, this.plantData.damage, 'seed'));\n                        this.isAttacking = true;\n                        this.attackFrame = 10;\n                    }\n                } else if (this.plantData.type === 'generator') {\n                     this.attackTimer++;\n                    if (this.attackTimer % this.plantData.attackSpeed === 0) {\n                        coins++;\n                    }\n                }\n            }\n        }\n        class Projectile { constructor(row, col, damage, type = 'seed') { this.row = row; this.x = (col + 0.5) * GRID_WIDTH; this.y = row * GRID_HEIGHT + GRID_HEIGHT \/ 3; this.speed = 5; this.damage = damage; this.type = type; this.width = GRID_WIDTH*0.2; this.height = GRID_WIDTH*0.2; } update() { this.x += this.speed; } draw() { if (this.type === 'laser') { ctx.fillStyle = 'red'; ctx.fillRect(this.x, this.y + 10, GAME_WIDTH, this.height\/3); } else { ctx.drawImage(images.seed, this.x, this.y, this.width, this.height); }}}\n        class Zombie { constructor(row, health, timePerCell, type) { this.row = row; this.x = GAME_WIDTH; this.y = row * GRID_HEIGHT; this.width = GRID_WIDTH * 0.8; this.height = GRID_HEIGHT; this.health = health; this.maxHealth = health; this.type = type; this.image = images[type === 'shield' ? 'shieldZombie' : 'normalZombie']; this.shakeOffset = 0; this.isEating = false; const baseSpeed = GRID_WIDTH \/ (timePerCell * 60); this.speed = (baseSpeed * 0.7 * Math.pow(1.1, stage - 1)) * 2; } update() { if (!this.isEating) { this.x -= this.speed; } this.shakeOffset = Math.sin(frame * 0.1) * 3; } draw() { ctx.drawImage(this.image, this.x, this.y + this.shakeOffset, this.width, this.height); ctx.fillStyle = 'red'; ctx.fillRect(this.x, this.y, this.width, 5); ctx.fillStyle = 'green'; ctx.fillRect(this.x, this.y, this.width * (this.health \/ this.maxHealth), 5); } }\n        class NormalZombie extends Zombie { constructor(row) { super(row, 50, 5, 'normal'); } }\n        class ShieldZombie extends Zombie { constructor(row) { super(row, 150, 7, 'shield'); } }\n\n        startButton.addEventListener('click', () => { startScreen.style.display = 'none'; initGame(); });\n        nextStageButton.addEventListener('click', () => { stage++; stageClearScreen.style.display = 'none'; initGame(); });\n        \n        \/\/ [\uc624\ub958 \uc218\uc815] \ud0dc\uc591 \ud074\ub9ad\uc744 \uc704\ud55c \ud1b5\ud569 \uc774\ubca4\ud2b8 \ud578\ub4e4\ub7ec\n        function handleCanvasInteraction(e) {\n            if (isDragging) return;\n            const pos = getEventPosition(e);\n            const rect = canvas.getBoundingClientRect();\n            const mouseX = pos.x - rect.left; const mouseY = pos.y - rect.top;\n            for (let i = suns.length - 1; i >= 0; i--) { const sun = suns[i]; const dist = Math.sqrt(Math.pow(mouseX - (sun.x + sun.size\/2), 2) + Math.pow(mouseY - (sun.y + sun.size\/2), 2)); if (dist < sun.size \/ 2) { coins += sun.value; suns.splice(i, 1); return; } }\n        }\n        canvas.addEventListener('click', handleCanvasInteraction);\n        canvas.addEventListener('touchend', handleCanvasInteraction);\n        \n        let currentMousePos = { x: 0, y: 0 };\n        function getEventPosition(e) { if (e.touches &#038;&#038; e.touches.length > 0) return { x: e.touches[0].clientX, y: e.touches[0].clientY }; if (e.changedTouches && e.changedTouches.length > 0) return { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY }; return { x: e.clientX, y: e.clientY }; }\n        function handleDragStart(e) { e.preventDefault(); const plantId = e.currentTarget.dataset.plantId; const cost = parseInt(e.currentTarget.dataset.cost); if (coins >= cost && !isDragging) { isDragging = true; draggedPlantId = plantId; const plantData = plantMasterList.find(p => p.id === plantId); draggedImage.src = imageUrls[plantData.image]; dragImageContainer.style.width = `${GRID_WIDTH}px`; dragImageContainer.style.height = `${GRID_HEIGHT}px`; dragImageContainer.style.display = 'block'; currentMousePos = getEventPosition(e); moveDraggedImage(); } }\n        function handleDragMove(e) { if (isDragging) { e.preventDefault(); currentMousePos = getEventPosition(e); moveDraggedImage(); } }\n        function moveDraggedImage() { const rect = gameContainer.getBoundingClientRect(); dragImageContainer.style.left = `${currentMousePos.x - rect.left - GRID_WIDTH \/ 2}px`; dragImageContainer.style.top = `${currentMousePos.y - rect.top - GRID_HEIGHT \/ 2}px`; }\n        function handleDragEnd(e) { if (isDragging) { const rect = canvas.getBoundingClientRect(); const mouseX = currentMousePos.x - rect.left; const mouseY = currentMousePos.y - rect.top; const col = Math.floor(mouseX \/ GRID_WIDTH); const row = Math.floor(mouseY \/ GRID_HEIGHT); if (mouseX > 0 && mouseX < GAME_WIDTH &#038;&#038; mouseY > 0 && mouseY < GAME_HEIGHT &#038;&#038; col < 3) { if (!plants.some(p => p.row === row && p.col === col)) { const card = document.querySelector(`.plant-card[data-plant-id=\"${draggedPlantId}\"]`); const cost = parseInt(card.dataset.cost); if (coins >= cost) { coins -= cost; const plantData = plantMasterList.find(p => p.id === draggedPlantId); plants.push(new Plant(row, col, plantData)); } } } isDragging = false; draggedPlantId = null; dragImageContainer.style.display = 'none'; } }\n        window.addEventListener('mousemove', handleDragMove); window.addEventListener('touchmove', handleDragMove, { passive: false }); window.addEventListener('mouseup', handleDragEnd); window.addEventListener('touchend', handleDragEnd);\n\n        function initGame() {\n            frame = 0; plants = []; zombies = []; projectiles = []; suns = []; zombiesSpawned = 0; waveTriggered1 = false; waveTriggered2 = false;\n            if(stage === 1) { coins = 15; lives = 5; }\n            createPlantSelector(); updateUI();\n            gameState = 'countdown'; gameLoop();\n            let count = 5; countdownEl.textContent = count; countdownEl.style.display = 'block';\n            const countdownInterval = setInterval(() => {\n                count--; countdownEl.textContent = count;\n                if (count <= 0) { clearInterval(countdownInterval); countdownEl.style.display = 'none'; gameState = 'playing'; spawnZombie(); zombieSpawnCounter = frame + zombieSpawnInterval; }\n            }, 1000);\n        }\n        \n        loadImages();\n        setCanvasSize();\n    <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>\uacfc\uc77c vs \uc880\ube44 \ub514\ud39c\uc2a4 (\ucd5c\uc885\ud310) Stage: 1 \ubaa9\uc228: \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f \ucf54\uc778: 15 \ud83d\udcb0 5 \ub9cc\ub4e0\uc0ac\ub78c: \uae40\ud0dc\uc624 \uacfc\uc77c vs \uc880\ube44 \ub514\ud39c\uc2a4 \uac8c\uc784 \uc2dc\uc791 \uac8c\uc784 \uc624\ubc84 \ub2e4\uc2dc \uc2dc\uc791 \uc2a4\ud14c\uc774\uc9c0 \ud074\ub9ac\uc5b4! \ub2e4\uc74c \uc2a4\ud14c\uc774\uc9c0<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/pages\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6"}],"version-history":[{"count":1,"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/pages\/6\/revisions"}],"predecessor-version":[{"id":8,"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=\/wp\/v2\/pages\/6\/revisions\/8"}],"wp:attachment":[{"href":"https:\/\/hgkim.ddns.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}