about summary refs log tree commit diff stats
path: root/html/tower/docs/mechanics.js.html
diff options
context:
space:
mode:
Diffstat (limited to 'html/tower/docs/mechanics.js.html')
-rw-r--r--html/tower/docs/mechanics.js.html480
1 files changed, 480 insertions, 0 deletions
diff --git a/html/tower/docs/mechanics.js.html b/html/tower/docs/mechanics.js.html
new file mode 100644
index 0000000..d629a87
--- /dev/null
+++ b/html/tower/docs/mechanics.js.html
@@ -0,0 +1,480 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: mechanics.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: mechanics.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/**
+ * Combat Mechanics Module
+ *  
+ * This module handles all combat-related game mechanics including:
+ * 1. Enemy movement and behavior
+ * 2. Tower attacks and targeting
+ * 3. Projectile and particle systems
+ * 4. Status effects and special abilities
+ * 
+ * @module mechanics
+ */
+
+/**
+ * Updates all enemy states including movement, health, and status effects
+ * Implements core game loop mechanics for enemy behavior
+ * 
+ * Key features:
+ * - Path following
+ * - Health management
+ * - Status effect processing
+ * - Collision detection
+ * 
+ * @returns {void}
+ */
+function updateEnemies() {
+    const cellSize = canvas.width / 20;
+    
+    gameState.enemies = gameState.enemies.filter(enemy => {
+        // Initialize progress tracking for new enemies
+        if (typeof enemy.progress === 'undefined') {
+            enemy.progress = 0;
+        }
+        
+        // Update movement progress
+        enemy.progress += enemy.speed * 0.001;
+        
+        // Handle path completion
+        if (enemy.progress >= 1) {
+            gameState.enemiesEscaped++;
+            // Deduct currency when enemy escapes
+            gameState.currency = Math.max(0, gameState.currency - 10);
+            // Check for game over
+            if (gameState.currency &lt;= 0) {
+                handleGameOver();
+            }
+            return false;
+        }
+        
+        // Projectile collision detection and damage application
+        const hitByProjectile = gameState.projectiles.some(projectile => {
+            // Calculate current projectile position based on lifetime
+            const age = performance.now() - projectile.createdAt;
+            const progress = Math.min(age / projectile.lifetime, 1);
+            
+            const currentX = projectile.startPos.x + (projectile.targetPos.x - projectile.startPos.x) * progress;
+            const currentY = projectile.startPos.y + (projectile.targetPos.y - projectile.startPos.y) * progress;
+            
+            const distance = Math.hypot(
+                enemy.position.x - currentX,
+                enemy.position.y - currentY
+            );
+            
+            if (distance &lt; 0.5) {
+                // Apply damage when projectile hits
+                enemy.currentHealth -= projectile.damage;
+                return true;
+            }
+            return false;
+        });
+        
+        if (enemy.currentHealth &lt;= 0) {
+            gameState.awardEnemyDestroyed();
+            // Create death particles
+            gameState.particles.push(...createDeathParticles(enemy, cellSize));
+            return false;
+        }
+        
+        // Update position based on path progress
+        const pathPosition = getPathPosition(enemy.progress, gameState.path);
+        enemy.position.x = pathPosition.x;
+        enemy.position.y = pathPosition.y;
+        
+        // Process slow effect expiration
+        if (enemy.slowed &amp;&amp; performance.now() > enemy.slowExpiry) {
+            enemy.slowed = false;
+            enemy.slowStacks = 0;
+            enemy.currentSlowAmount = 0;
+            enemy.speed = enemy.originalSpeed;
+        }
+        
+        // Visual feedback for slowed status
+        if (enemy.slowed &amp;&amp; Math.random() &lt; 0.2 + (enemy.slowStacks * 0.05)) {
+            gameState.particles.push(createSlimeTrail(enemy, cellSize));
+        }
+        
+        return true;
+    });
+    
+    // Remove projectiles that hit enemies
+    gameState.projectiles = gameState.projectiles.filter(projectile => {
+        const age = performance.now() - projectile.createdAt;
+        if (age >= projectile.lifetime) return false;
+        
+        const progress = age / projectile.lifetime;
+        const currentX = projectile.startPos.x + (projectile.targetPos.x - projectile.startPos.x) * progress;
+        const currentY = projectile.startPos.y + (projectile.targetPos.y - projectile.startPos.y) * progress;
+        
+        const hitEnemy = gameState.enemies.some(enemy => {
+            const distance = Math.hypot(
+                enemy.position.x - currentX,
+                enemy.position.y - currentY
+            );
+            return distance &lt; 0.5;
+        });
+        
+        return !hitEnemy;
+    });
+}
+
+/**
+ * Updates particle effects with time-based animation
+ * Implements particle system lifecycle management
+ * 
+ * @param {Array&lt;Object>} particles - Array of particle objects
+ * @param {number} timestamp - Current game timestamp
+ * @param {number} deltaTime - Time elapsed since last frame
+ * @returns {Array&lt;Object>} Updated particles array
+ */
+function updateParticles(particles, timestamp, deltaTime) {
+    return particles.filter(particle => {
+        const age = timestamp - particle.createdAt;
+        if (age > particle.lifetime) return false;
+        
+        if (particle.velocity) {
+            particle.position.x += particle.velocity.x * deltaTime;
+            particle.position.y += particle.velocity.y * deltaTime;
+        }
+        
+        return true;
+    });
+}
+
+/**
+ * Creates death effect particles for defeated entities
+ * Implements visual feedback system
+ * 
+ * @param {Object} target - The defeated entity
+ * @param {number} cellSize - Size of grid cell for scaling
+ * @returns {Array&lt;Object>} Array of particle objects
+ */
+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 &lt; 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;
+        
+        particles.push(createParticle(
+            {
+                ...ParticleTypes.DEATH_PARTICLE,
+                speed: ParticleTypes.DEATH_PARTICLE.speed * speedMultiplier,
+                lifetime: ParticleTypes.DEATH_PARTICLE.lifetime * (0.8 + Math.random() * 0.4)
+            },
+            {
+                x: centerX + Math.cos(randomAngle) * startOffset,
+                y: centerY + Math.sin(randomAngle) * startOffset
+            },
+            randomAngle
+        ));
+    }
+    return particles;
+}
+
+/**
+ * Processes tower attacks and targeting
+ * Implements combat mechanics and special abilities
+ * 
+ * @param {Array&lt;Object>} towers - Array of tower objects
+ * @param {Array&lt;Object>} enemies - Array of enemy objects
+ * @param {Array&lt;Object>} projectiles - Array of projectile objects
+ * @param {Array&lt;Object>} particles - Array of particle objects
+ * @param {number} timestamp - Current game timestamp
+ * @param {number} cellSize - Size of grid cell for scaling
+ */
+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 &amp;&amp; tower.ammo > 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) &lt;= tower.range;
+    });
+}
+
+function createAOEExplosion(position, cellSize) {
+    return {
+        position: {
+            x: (position.x + 0.5) * cellSize,
+            y: (position.y + 0.5) * cellSize
+        },
+        createdAt: performance.now(),
+        type: 'AOE_EXPLOSION',
+        ...ParticleTypes.AOE_EXPLOSION
+    };
+}
+
+function createSlimeTrail(enemy, cellSize) {
+    return {
+        position: {
+            x: (enemy.position.x + 0.5) * cellSize,
+            y: (enemy.position.y + 0.5) * cellSize
+        },
+        createdAt: performance.now(),
+        type: 'SLIME_TRAIL',
+        ...ParticleTypes.SLIME_TRAIL
+    };
+}
+
+/**
+ * Handles individual tower attack logic including special effects
+ * Implements tower ability system
+ * 
+ * @param {Object} tower - Attacking tower
+ * @param {Object} target - Target enemy
+ * @param {Array&lt;Object>} projectiles - Projectile array
+ * @param {Array&lt;Object>} particles - Particle array
+ * @param {number} timestamp - Current game timestamp
+ * @param {number} cellSize - Grid cell size
+ */
+function handleTowerAttack(tower, target, projectiles, particles, timestamp, cellSize) {
+    // Only attack if we have ammo
+    if (tower.ammo &lt;= 0) return;
+    
+    // Decrease ammo (already checked it's > 0)
+    tower.ammo--;
+    
+    // Create projectile
+    projectiles.push({
+        startPos: { ...tower.position },
+        targetPos: { ...target.position },
+        createdAt: timestamp,
+        lifetime: 300,
+        towerType: tower.type,
+        damage: tower.damage
+    });
+    
+    // Process special abilities
+    if (tower.special === 'slow') {
+        handleSlowEffect(target, tower, timestamp, particles, cellSize);
+    } else if (tower.special === 'aoe') {
+        handleAOEEffect(target, tower, gameState.enemies, particles, cellSize);
+    }
+    
+    tower.lastAttackTime = timestamp;
+}
+
+/**
+ * Processes enemy attack behaviors and targeting
+ * Implements enemy combat AI
+ * 
+ * @param {Array&lt;Object>} enemies - Array of enemy objects
+ * @param {Array&lt;Object>} towers - Array of tower objects
+ * @param {Array&lt;Object>} particles - Particle effect array
+ * @param {number} timestamp - Current game timestamp
+ * @param {number} cellSize - Grid cell size
+ */
+function processEnemyAttacks(enemies, towers, particles, timestamp, cellSize) {
+    enemies.forEach(enemy => {
+        if (!EnemyTypes[enemy.type].isRanged) return;
+        
+        if (timestamp - enemy.lastAttackTime > 1000 / EnemyTypes[enemy.type].attackSpeed) {
+            const towersInRange = findTowersInRange(enemy, towers);
+            
+            if (towersInRange.length > 0) {
+                const target = towersInRange[0];
+                handleEnemyAttack(enemy, target, particles, timestamp, cellSize);
+            }
+        }
+    });
+}
+
+/**
+ * Finds towers within enemy attack range
+ * Implements targeting system for enemies
+ * 
+ * @param {Object} enemy - Enemy doing the targeting
+ * @param {Array&lt;Object>} towers - Array of potential tower targets
+ * @returns {Array&lt;Object>} Array of towers in range
+ */
+function findTowersInRange(enemy, towers) {
+    return towers.filter(tower => {
+        const dx = tower.position.x - enemy.position.x;
+        const dy = tower.position.y - enemy.position.y;
+        return Math.sqrt(dx * dx + dy * dy) &lt;= EnemyTypes[enemy.type].attackRange;
+    });
+}
+
+/**
+ * Handles enemy attack execution and effects
+ * Implements enemy combat mechanics
+ * 
+ * @param {Object} enemy - Attacking enemy
+ * @param {Object} tower - Target tower
+ * @param {Array&lt;Object>} particles - Particle array for effects
+ * @param {number} timestamp - Current game timestamp
+ * @param {number} cellSize - Grid cell size
+ */
+function handleEnemyAttack(enemy, tower, particles, timestamp, cellSize) {
+    // Create projectile effect
+    particles.push(createParticle(
+        {
+            ...ParticleTypes.PROJECTILE,
+            color: '#8e44ad80', // Semi-transparent purple
+            lifetime: 500
+        },
+        {
+            x: (enemy.position.x + 0.5) * cellSize,
+            y: (enemy.position.y + 0.5) * cellSize
+        },
+        Math.atan2(
+            tower.position.y - enemy.position.y,
+            tower.position.x - enemy.position.x
+        )
+    ));
+    
+    // Apply damage and update tower state
+    tower.currentHealth -= enemy.damage;
+    enemy.lastAttackTime = timestamp;
+    
+    // Dynamic damage reduction based on tower health
+    tower.damage = TowerTypes[tower.type].damage * (tower.currentHealth / tower.maxHealth);
+}
+
+/**
+ * Handles slow effect application and stacking
+ * Implements status effect system
+ * 
+ * @param {Object} target - Enemy to apply slow to
+ * @param {Object} tower - Tower applying the effect
+ * @param {number} timestamp - Current game timestamp
+ * @param {Array&lt;Object>} particles - Particle array for effects
+ * @param {number} cellSize - Grid cell size
+ */
+function handleSlowEffect(target, tower, timestamp, particles, cellSize) {
+    // Initialize slow effect tracking
+    if (!target.slowStacks) {
+        target.slowStacks = 0;
+    }
+    
+    const maxStacks = 5;  // Maximum 5 stacks
+    if (target.slowStacks &lt; maxStacks) {
+        target.slowStacks++;
+        // Each stack slows by an additional 10% (multiplicative)
+        const newSlowAmount = 1 - Math.pow(0.9, target.slowStacks);
+        
+        // Only update if new slow is stronger
+        if (!target.slowed || newSlowAmount > target.currentSlowAmount) {
+            const originalSpeed = target.originalSpeed || target.speed;
+            target.originalSpeed = originalSpeed;
+            target.speed = originalSpeed * (1 - newSlowAmount);
+            target.currentSlowAmount = newSlowAmount;
+            target.slowed = true;
+        }
+        
+        // Visual feedback particles
+        for (let i = 0; i &lt; 4 + target.slowStacks; i++) {
+            particles.push(createSlimeTrail(target, cellSize));
+        }
+    }
+    
+    // Refresh effect duration
+    target.slowExpiry = timestamp + 2000;  // 2 second duration
+}
+
+/**
+ * Handles AOE (Area of Effect) damage and visual effects
+ * Implements area damage system
+ * 
+ * @param {Object} target - Primary target
+ * @param {Object} tower - Tower dealing AOE damage
+ * @param {Array&lt;Object>} enemies - All enemies for AOE calculation
+ * @param {Array&lt;Object>} particles - Particle array for effects
+ * @param {number} cellSize - Grid cell size
+ */
+function handleAOEEffect(target, tower, enemies, particles, cellSize) {
+    // Find all enemies in AOE radius
+    const enemiesInAOE = enemies.filter(enemy => {
+        const dx = enemy.position.x - target.position.x;
+        const dy = enemy.position.y - target.position.y;
+        return Math.sqrt(dx * dx + dy * dy) &lt;= tower.aoeRadius;
+    });
+    
+    // Create explosion effect
+    particles.push(createAOEExplosion(target.position, cellSize));
+    
+    // Apply AOE damage
+    enemiesInAOE.forEach(enemy => {
+        enemy.currentHealth -= tower.damage;
+        if (enemy.currentHealth &lt;= 0) {
+            particles.push(...createDeathParticles(enemy, cellSize));
+        }
+    });
+}
+
+// Update createEnemy to track original speed
+function createEnemy(startPosition) {
+    const enemy = {
+        // ... existing enemy properties ...
+        slowStacks: 0,
+        currentSlowAmount: 0
+    };
+    enemy.originalSpeed = enemy.speed;  // Store original speed
+    return enemy;
+} </code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-game.html">game</a></li><li><a href="module-gameState.html">gameState</a></li><li><a href="module-mechanics.html">mechanics</a></li><li><a href="module-path.html">path</a></li><li><a href="module-renderer.html">renderer</a></li><li><a href="module-uiHandlers.html">uiHandlers</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.3</a> on Mon Feb 17 2025 09:19:19 GMT-0500 (Eastern Standard Time)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>