about summary refs log tree commit diff stats
path: root/html
diff options
context:
space:
mode:
Diffstat (limited to 'html')
-rw-r--r--html/tower/index.html2
-rw-r--r--html/tower/js/game.js142
-rw-r--r--html/tower/js/mechanics.js94
-rw-r--r--html/tower/js/uiHandlers.js48
4 files changed, 177 insertions, 109 deletions
diff --git a/html/tower/index.html b/html/tower/index.html
index 23755fa..e27cf28 100644
--- a/html/tower/index.html
+++ b/html/tower/index.html
@@ -99,6 +99,8 @@
     <script src="js/path.js"></script>
     <script src="js/tower.js"></script>
     <script src="js/enemy.js"></script>
+    <script src="js/mechanics.js"></script>
+    <script src="js/uiHandlers.js"></script>
     
     <!-- Rendering modules -->
     <script src="js/renderer.js"></script>
diff --git a/html/tower/js/game.js b/html/tower/js/game.js
index 263d25c..5c28f31 100644
--- a/html/tower/js/game.js
+++ b/html/tower/js/game.js
@@ -26,126 +26,50 @@ function gameLoop(timestamp) {
     const deltaTime = timestamp - lastTimestamp;
     lastTimestamp = timestamp;
     
-    // Clear canvas
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     
     if (gameState.phase === GamePhase.COMBAT) {
-        // Spawn enemies
-        if (enemiesRemaining > 0 && timestamp - lastEnemySpawn > ENEMY_SPAWN_INTERVAL) {
-            gameState.enemies.push(createEnemy({ x: 0, y: gameState.path[0].y }));
-            lastEnemySpawn = timestamp;
-            enemiesRemaining--;
-        }
-        
-        // Update enemy positions
-        gameState.enemies.forEach(enemy => {
-            if (enemy.pathIndex < gameState.path.length - 1) {
-                const targetPos = gameState.path[enemy.pathIndex + 1];
-                const dx = targetPos.x - enemy.position.x;
-                const dy = targetPos.y - enemy.position.y;
-                const distance = Math.sqrt(dx * dx + dy * dy);
-                
-                if (distance < enemy.speed * deltaTime / 1000) {
-                    enemy.position = { ...targetPos };
-                    enemy.pathIndex++;
-                } else {
-                    enemy.position.x += (dx / distance) * enemy.speed * deltaTime / 1000;
-                    enemy.position.y += (dy / distance) * enemy.speed * deltaTime / 1000;
-                }
-            }
-        });
-        
-        // Update particles
-        gameState.particles = gameState.particles.filter(particle => {
-            const age = timestamp - particle.createdAt;
-            if (age > particle.lifetime) return false;
-            
-            particle.position.x += particle.velocity.x * deltaTime;
-            particle.position.y += particle.velocity.y * deltaTime;
-            return true;
-        });
-        
-        // Update projectiles
-        gameState.projectiles = gameState.projectiles.filter(projectile => {
-            return timestamp - projectile.createdAt < projectile.lifetime;
-        });
-        
-        // Process tower attacks
-        gameState.towers.forEach(tower => {
-            if (timestamp - tower.lastAttackTime > 1000 / tower.attackSpeed) {
-                const enemiesInRange = gameState.enemies.filter(enemy => {
-                    const dx = enemy.position.x - tower.position.x;
-                    const dy = enemy.position.y - tower.position.y;
-                    return Math.sqrt(dx * dx + dy * dy) <= tower.range;
-                });
-                
-                if (enemiesInRange.length > 0) {
-                    const target = enemiesInRange[0];
-                    
-                    // Create projectile
-                    gameState.projectiles.push({
-                        startPos: tower.position,
-                        targetPos: target.position,
-                        createdAt: timestamp,
-                        lifetime: 300 // 300ms travel time
-                    });
-                    
-                    // Apply damage
-                    target.currentHealth -= tower.damage;
-                    tower.lastAttackTime = timestamp;
-                    
-                    // Create death particles if enemy dies
-                    if (target.currentHealth <= 0) {
-                        const cellSize = canvas.width / 20;
-                        const centerX = (target.position.x + 0.5) * cellSize;
-                        const centerY = (target.position.y + 0.5) * cellSize;
-                        
-                        // Create explosion particles with random angles and speeds
-                        const particleCount = 8 + Math.floor(Math.random() * 8); // Random number of particles (8-15)
-                        for (let i = 0; i < particleCount; i++) {
-                            // Random angle with some clustering
-                            const baseAngle = (Math.PI * 2 * i) / particleCount;
-                            const randomAngle = baseAngle + (Math.random() - 0.5) * 1.5; // Add up to ±0.75 radians of randomness
-                            
-                            // Random speed multiplier
-                            const speedMultiplier = 0.7 + Math.random() * 0.6; // Speed varies from 0.7x to 1.3x
-                            
-                            // Random offset from center
-                            const startOffset = Math.random() * 5;
-                            const startX = centerX + Math.cos(randomAngle) * startOffset;
-                            const startY = centerY + Math.sin(randomAngle) * startOffset;
-                            
-                            gameState.particles.push(
-                                createParticle(
-                                    {
-                                        ...ParticleTypes.DEATH_PARTICLE,
-                                        speed: ParticleTypes.DEATH_PARTICLE.speed * speedMultiplier,
-                                        lifetime: ParticleTypes.DEATH_PARTICLE.lifetime * (0.8 + Math.random() * 0.4) // Random lifetime 80%-120%
-                                    },
-                                    { x: startX, y: startY },
-                                    randomAngle
-                                )
-                            );
-                        }
-                    }
-                }
-            }
-        });
-        
-        // Remove dead enemies
-        gameState.enemies = gameState.enemies.filter(enemy => enemy.currentHealth > 0);
+        handleCombatPhase(timestamp, deltaTime);
     }
     
-    // Render game state
+    renderGame();
+    requestAnimationFrame(gameLoop);
+}
+
+function handleCombatPhase(timestamp, deltaTime) {
+    spawnEnemies(timestamp);
+    updateEnemies(gameState.enemies, gameState.path, deltaTime);
+    gameState.particles = updateParticles(gameState.particles, timestamp, deltaTime);
+    gameState.projectiles = gameState.projectiles.filter(p => timestamp - p.createdAt < p.lifetime);
+    
+    const cellSize = canvas.width / 20;
+    processTowerAttacks(
+        gameState.towers,
+        gameState.enemies,
+        gameState.projectiles,
+        gameState.particles,
+        timestamp,
+        cellSize
+    );
+    
+    gameState.enemies = gameState.enemies.filter(enemy => enemy.currentHealth > 0);
+}
+
+function spawnEnemies(timestamp) {
+    if (enemiesRemaining > 0 && timestamp - lastEnemySpawn > ENEMY_SPAWN_INTERVAL) {
+        gameState.enemies.push(createEnemy({ x: 0, y: gameState.path[0].y }));
+        lastEnemySpawn = timestamp;
+        enemiesRemaining--;
+    }
+}
+
+function renderGame() {
     renderGrid(ctx, gameState.grid);
     renderProjectiles(ctx, gameState.projectiles);
     renderEnemies(ctx, gameState.enemies);
     renderTowers(ctx, gameState.towers);
     renderParticles(ctx, gameState.particles);
     renderUI(ctx, gameState);
-    
-    // Request next frame
-    requestAnimationFrame(gameLoop);
 }
 
 // Start the game
diff --git a/html/tower/js/mechanics.js b/html/tower/js/mechanics.js
new file mode 100644
index 0000000..72b284a
--- /dev/null
+++ b/html/tower/js/mechanics.js
@@ -0,0 +1,94 @@
+// Combat mechanics
+function updateEnemies(enemies, path, deltaTime) {
+    enemies.forEach(enemy => {
+        if (enemy.pathIndex < path.length - 1) {
+            const targetPos = path[enemy.pathIndex + 1];
+            const dx = targetPos.x - enemy.position.x;
+            const dy = targetPos.y - enemy.position.y;
+            const distance = Math.sqrt(dx * dx + dy * dy);
+            
+            if (distance < enemy.speed * deltaTime / 1000) {
+                enemy.position = { ...targetPos };
+                enemy.pathIndex++;
+            } else {
+                enemy.position.x += (dx / distance) * enemy.speed * deltaTime / 1000;
+                enemy.position.y += (dy / distance) * enemy.speed * deltaTime / 1000;
+            }
+        }
+    });
+}
+
+function updateParticles(particles, timestamp, deltaTime) {
+    return particles.filter(particle => {
+        const age = timestamp - particle.createdAt;
+        if (age > particle.lifetime) return false;
+        
+        particle.position.x += particle.velocity.x * deltaTime;
+        particle.position.y += particle.velocity.y * deltaTime;
+        return true;
+    });
+}
+
+function createDeathParticles(target, cellSize) {
+    const particles = [];
+    const centerX = (target.position.x + 0.5) * cellSize;
+    const centerY = (target.position.y + 0.5) * cellSize;
+    
+    const particleCount = 8 + Math.floor(Math.random() * 8);
+    for (let i = 0; i < particleCount; i++) {
+        const baseAngle = (Math.PI * 2 * i) / particleCount;
+        const randomAngle = baseAngle + (Math.random() - 0.5) * 1.5;
+        const speedMultiplier = 0.7 + Math.random() * 0.6;
+        const startOffset = Math.random() * 5;
+        const startX = centerX + Math.cos(randomAngle) * startOffset;
+        const startY = centerY + Math.sin(randomAngle) * startOffset;
+        
+        particles.push(createParticle(
+            {
+                ...ParticleTypes.DEATH_PARTICLE,
+                speed: ParticleTypes.DEATH_PARTICLE.speed * speedMultiplier,
+                lifetime: ParticleTypes.DEATH_PARTICLE.lifetime * (0.8 + Math.random() * 0.4)
+            },
+            { x: startX, y: startY },
+            randomAngle
+        ));
+    }
+    return particles;
+}
+
+function processTowerAttacks(towers, enemies, projectiles, particles, timestamp, cellSize) {
+    towers.forEach(tower => {
+        if (timestamp - tower.lastAttackTime > 1000 / tower.attackSpeed) {
+            const enemiesInRange = findEnemiesInRange(tower, enemies);
+            
+            if (enemiesInRange.length > 0) {
+                const target = enemiesInRange[0];
+                handleTowerAttack(tower, target, projectiles, particles, timestamp, cellSize);
+            }
+        }
+    });
+}
+
+function findEnemiesInRange(tower, enemies) {
+    return enemies.filter(enemy => {
+        const dx = enemy.position.x - tower.position.x;
+        const dy = enemy.position.y - tower.position.y;
+        return Math.sqrt(dx * dx + dy * dy) <= tower.range;
+    });
+}
+
+function handleTowerAttack(tower, target, projectiles, particles, timestamp, cellSize) {
+    projectiles.push({
+        startPos: tower.position,
+        targetPos: target.position,
+        createdAt: timestamp,
+        lifetime: 300
+    });
+    
+    target.currentHealth -= tower.damage;
+    tower.lastAttackTime = timestamp;
+    
+    if (target.currentHealth <= 0) {
+        particles.push(...createDeathParticles(target, cellSize));
+    }
+} 
\ No newline at end of file
diff --git a/html/tower/js/uiHandlers.js b/html/tower/js/uiHandlers.js
new file mode 100644
index 0000000..5dc048a
--- /dev/null
+++ b/html/tower/js/uiHandlers.js
@@ -0,0 +1,48 @@
+function initializeDragAndDrop(canvas, gameState) {
+    let draggedTowerType = null;
+    let hoverCell = null;
+
+    const dragHandlers = {
+        onDragStart: (e) => {
+            draggedTowerType = e.target.dataset.towerType;
+            e.dataTransfer.setData('text/plain', '');
+        },
+        
+        onDragEnd: () => {
+            draggedTowerType = null;
+            hoverCell = null;
+        },
+        
+        onDragOver: (e) => {
+            e.preventDefault();
+            const rect = canvas.getBoundingClientRect();
+            const x = Math.floor((e.clientX - rect.left) / (canvas.width / 20));
+            const y = Math.floor((e.clientY - rect.top) / (canvas.height / 20));
+            
+            hoverCell = (x >= 0 && x < 20 && y >= 0 && y < 20) ? { x, y } : null;
+        },
+        
+        onDrop: (e) => {
+            e.preventDefault();
+            if (!draggedTowerType || !hoverCell) return;
+            
+            placeTower(gameState, draggedTowerType, hoverCell);
+            draggedTowerType = null;
+            hoverCell = null;
+        }
+    };
+
+    return { dragHandlers, getHoverInfo: () => ({ draggedTowerType, hoverCell }) };
+}
+
+function placeTower(gameState, towerType, position) {
+    const tower = TowerTypes[towerType];
+    if (
+        gameState.grid[position.y][position.x] === 'empty' &&
+        gameState.playerCurrency >= tower.cost
+    ) {
+        gameState.grid[position.y][position.x] = 'tower';
+        gameState.towers.push(createTower(towerType, { ...position }));
+        gameState.playerCurrency -= tower.cost;
+    }
+} 
\ No newline at end of file