Spaces:
Running
Running
| <html lang="ko"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ํด์ ์ ๋ต ์๋ฎฌ๋ ์ด์ </title> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 20px; | |
| background-color: #f0f0f0; | |
| font-family: Arial, sans-serif; | |
| } | |
| #gameContainer { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| #gameCanvas { | |
| border: 2px solid #333; | |
| box-shadow: 0 0 10px rgba(0,0,0,0.2); | |
| background-color: #fff; | |
| } | |
| #gameInfo { | |
| margin-top: 20px; | |
| padding: 10px; | |
| background-color: #fff; | |
| border: 1px solid #ccc; | |
| border-radius: 5px; | |
| } | |
| .controls { | |
| margin-top: 10px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| button { | |
| padding: 5px 10px; | |
| cursor: pointer; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="gameContainer"> | |
| <canvas id="gameCanvas"></canvas> | |
| <div id="gameInfo"> | |
| <div id="turnInfo">ํ์ฌ ํด: ์ ์๊ตฐ</div> | |
| <div id="selectedUnit">์ ํ๋ ์ ๋: ์์</div> | |
| <div class="controls"> | |
| <button id="endTurn">ํด ์ข ๋ฃ</button> | |
| <button id="resetGame">๊ฒ์ ์ฌ์์</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // ๊ฒ์ ์์ | |
| const GRID_SIZE = 80; | |
| const COLS = 10; | |
| const ROWS = 6; | |
| // Canvas ์ค์ | |
| const canvas = document.getElementById('gameCanvas'); | |
| const ctx = canvas.getContext('2d'); | |
| canvas.width = GRID_SIZE * COLS; | |
| canvas.height = GRID_SIZE * ROWS; | |
| // ์งํ ๋ฐ์ดํฐ | |
| const elevationData = [ | |
| [1, 1, 2, 2, 2, 2, 1, 1, 1, 1], | |
| [1, 2, 2, 3, 3, 2, 2, 1, 1, 1], | |
| [1, 2, 3, 3, 2, 2, 2, 2, 1, 1], | |
| [1, 2, 2, 2, 2, 2, 3, 2, 2, 1], | |
| [1, 1, 2, 2, 2, 3, 2, 2, 1, 1], | |
| [1, 1, 1, 2, 2, 2, 2, 1, 1, 1] | |
| ]; | |
| // ์ ๋ ํด๋์ค | |
| class Unit { | |
| constructor(type, team, x, y) { | |
| this.type = type; | |
| this.team = team; | |
| this.x = x; | |
| this.y = y; | |
| this.hp = this.getInitialHP(); | |
| this.moved = false; | |
| this.attacked = false; | |
| // ์ ๋ ํ์ ๋ณ ์คํฏ | |
| const stats = { | |
| 'Infantry': { move: 2, attack: 3, defense: 3, range: 1 }, | |
| 'Archer': { move: 2, attack: 2, defense: 2, range: 3 }, | |
| 'Cavalry': { move: 3, attack: 4, defense: 2, range: 1 } | |
| }; | |
| Object.assign(this, stats[type]); | |
| } | |
| getInitialHP() { | |
| const hpValues = { | |
| 'Infantry': 25, | |
| 'Archer': 20, | |
| 'Cavalry': 22 | |
| }; | |
| return hpValues[this.type]; | |
| } | |
| draw() { | |
| const x = this.x * GRID_SIZE; | |
| const y = this.y * GRID_SIZE; | |
| // ์ ๋ ๊ธฐ๋ณธ ๋ชจ์ | |
| ctx.fillStyle = this.team === 'red' ? '#ff0000' : '#0000ff'; | |
| ctx.beginPath(); | |
| ctx.arc(x + GRID_SIZE/2, y + GRID_SIZE/2, GRID_SIZE/3, 0, Math.PI * 2); | |
| ctx.fill(); | |
| // ์ ๋ ํ์ ํ์ | |
| ctx.fillStyle = '#ffffff'; | |
| ctx.font = '14px Arial'; | |
| ctx.textAlign = 'center'; | |
| ctx.fillText(this.type[0], x + GRID_SIZE/2, y + GRID_SIZE/2 + 5); | |
| // HP ๋ฐ | |
| this.drawHealthBar(x, y); | |
| } | |
| drawHealthBar(x, y) { | |
| const maxHP = this.getInitialHP(); | |
| const barWidth = GRID_SIZE * 0.8; | |
| const barHeight = 5; | |
| const barX = x + GRID_SIZE * 0.1; | |
| const barY = y + GRID_SIZE * 0.8; | |
| // ๋ฐฐ๊ฒฝ | |
| ctx.fillStyle = '#ff0000'; | |
| ctx.fillRect(barX, barY, barWidth, barHeight); | |
| // ํ์ฌ ์ฒด๋ ฅ | |
| ctx.fillStyle = '#00ff00'; | |
| ctx.fillRect(barX, barY, (this.hp / maxHP) * barWidth, barHeight); | |
| } | |
| } | |
| // ๊ฒ์ ์ํ | |
| let gameState = { | |
| units: [], | |
| selectedUnit: null, | |
| currentTurn: 'red', | |
| turnCount: 1 | |
| }; | |
| // ๊ฒ์ ์ด๊ธฐํ | |
| function initGame() { | |
| gameState.units = []; | |
| gameState.currentTurn = 'red'; | |
| gameState.turnCount = 1; | |
| gameState.selectedUnit = null; | |
| // ์ ์๊ตฐ ์ ๋ ๋ฐฐ์น | |
| for(let i = 0; i < 6; i++) { | |
| gameState.units.push(new Unit('Infantry', 'red', 0, i)); | |
| } | |
| for(let i = 0; i < 3; i++) { | |
| gameState.units.push(new Unit('Archer', 'red', 1, i*2)); | |
| gameState.units.push(new Unit('Cavalry', 'red', 2, i*2)); | |
| } | |
| // ์ฒญ์๊ตฐ ์ ๋ ๋ฐฐ์น | |
| for(let i = 0; i < 6; i++) { | |
| gameState.units.push(new Unit('Infantry', 'blue', 9, i)); | |
| } | |
| for(let i = 0; i < 3; i++) { | |
| gameState.units.push(new Unit('Archer', 'blue', 8, i*2)); | |
| gameState.units.push(new Unit('Cavalry', 'blue', 7, i*2)); | |
| } | |
| } | |
| // ๊ฒฉ์ ๊ทธ๋ฆฌ๊ธฐ | |
| function drawGrid() { | |
| ctx.strokeStyle = '#ccc'; | |
| ctx.lineWidth = 1; | |
| for(let x = 0; x <= canvas.width; x += GRID_SIZE) { | |
| ctx.beginPath(); | |
| ctx.moveTo(x, 0); | |
| ctx.lineTo(x, canvas.height); | |
| ctx.stroke(); | |
| } | |
| for(let y = 0; y <= canvas.height; y += GRID_SIZE) { | |
| ctx.beginPath(); | |
| ctx.moveTo(0, y); | |
| ctx.lineTo(canvas.width, y); | |
| ctx.stroke(); | |
| } | |
| } | |
| // ์งํ ๊ทธ๋ฆฌ๊ธฐ | |
| function drawTerrain() { | |
| // ๋ฐฐ๊ฒฝ | |
| ctx.fillStyle = '#e8e8d0'; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // ๋๋ฎ์ด ํ์ | |
| elevationData.forEach((row, y) => { | |
| row.forEach((height, x) => { | |
| ctx.fillStyle = `rgba(0,0,0,${height * 0.1})`; | |
| ctx.fillRect(x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE); | |
| }); | |
| }); | |
| // ๊ฐ | |
| ctx.strokeStyle = '#4040ff'; | |
| ctx.lineWidth = 20; | |
| ctx.beginPath(); | |
| ctx.moveTo(0, canvas.height/2); | |
| ctx.bezierCurveTo( | |
| canvas.width/4, canvas.height/2 - 40, | |
| canvas.width*3/4, canvas.height/2 + 40, | |
| canvas.width, canvas.height/2 | |
| ); | |
| ctx.stroke(); | |
| } | |
| // ๊ฒ์ ํ๋ฉด ๊ฐฑ์ | |
| function render() { | |
| ctx.clearRect(0, 0, canvas.width, canvas.height); | |
| drawTerrain(); | |
| drawGrid(); | |
| // ์ ๋ ๊ทธ๋ฆฌ๊ธฐ | |
| gameState.units.forEach(unit => unit.draw()); | |
| // ์ ํ๋ ์ ๋ ํ์ด๋ผ์ดํธ | |
| if(gameState.selectedUnit) { | |
| const x = gameState.selectedUnit.x * GRID_SIZE; | |
| const y = gameState.selectedUnit.y * GRID_SIZE; | |
| ctx.strokeStyle = '#ffff00'; | |
| ctx.lineWidth = 3; | |
| ctx.strokeRect(x, y, GRID_SIZE, GRID_SIZE); | |
| } | |
| // ํด ์ ๋ณด ์ ๋ฐ์ดํธ | |
| document.getElementById('turnInfo').textContent = | |
| `ํ์ฌ ํด: ${gameState.currentTurn === 'red' ? '์ ์๊ตฐ' : '์ฒญ์๊ตฐ'} (${gameState.turnCount}ํด)`; | |
| document.getElementById('selectedUnit').textContent = | |
| gameState.selectedUnit ? | |
| `์ ํ๋ ์ ๋: ${gameState.selectedUnit.type} (HP: ${gameState.selectedUnit.hp})` : | |
| '์ ํ๋ ์ ๋: ์์'; | |
| } | |
| // ์ด๋ฒคํธ ๋ฆฌ์ค๋ | |
| canvas.addEventListener('click', handleClick); | |
| document.getElementById('endTurn').addEventListener('click', endTurn); | |
| document.getElementById('resetGame').addEventListener('click', () => { | |
| initGame(); | |
| render(); | |
| }); | |
| function handleClick(e) { | |
| const rect = canvas.getBoundingClientRect(); | |
| const x = Math.floor((e.clientX - rect.left) / GRID_SIZE); | |
| const y = Math.floor((e.clientY - rect.top) / GRID_SIZE); | |
| const clickedUnit = gameState.units.find(unit => unit.x === x && unit.y === y); | |
| if(clickedUnit && clickedUnit.team === gameState.currentTurn) { | |
| gameState.selectedUnit = clickedUnit; | |
| } else if(gameState.selectedUnit) { | |
| // ์ด๋ ๋๋ ๊ณต๊ฒฉ ๋ก์ง | |
| moveUnit(gameState.selectedUnit, x, y); | |
| } | |
| render(); | |
| } | |
| function moveUnit(unit, targetX, targetY) { | |
| if(!unit.moved && isValidMove(unit, targetX, targetY)) { | |
| unit.x = targetX; | |
| unit.y = targetY; | |
| unit.moved = true; | |
| } | |
| } | |
| function isValidMove(unit, targetX, targetY) { | |
| const dx = Math.abs(targetX - unit.x); | |
| const dy = Math.abs(targetY - unit.y); | |
| return dx + dy <= unit.move; | |
| } | |
| function endTurn() { | |
| gameState.currentTurn = gameState.currentTurn === 'red' ? 'blue' : 'red'; | |
| if(gameState.currentTurn === 'red') gameState.turnCount++; | |
| // ์ ๋ ์ํ ์ด๊ธฐํ | |
| gameState.units.forEach(unit => { | |
| unit.moved = false; | |
| unit.attacked = false; | |
| }); | |
| gameState.selectedUnit = null; | |
| render(); | |
| } | |
| // ๊ฒ์ ์์ | |
| initGame(); | |
| render(); | |
| </script> | |
| </body> | |
| </html> |