about summary refs log tree commit diff stats
path: root/html/tower/js/gameState.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/tower/js/gameState.js')
-rw-r--r--html/tower/js/gameState.js288
1 files changed, 288 insertions, 0 deletions
diff --git a/html/tower/js/gameState.js b/html/tower/js/gameState.js
new file mode 100644
index 0000000..ac7a968
--- /dev/null
+++ b/html/tower/js/gameState.js
@@ -0,0 +1,288 @@
+/**
+ * Game State Module
+ * 
+ * This module defines the game state and game phases
+ * 
+ * @module gameState
+ */
+
+
+/**
+ * Game phases
+ * 
+ * @enum {string}
+ * @readonly
+ */
+const GamePhase = {
+    PLACEMENT: 'place',
+    COMBAT: 'run'
+};
+
+/**
+ * Tower types
+ * 
+ * @enum {string}
+ * @readonly
+ */
+const TowerTypes = {
+    BASIC: {
+        name: 'Basic',
+        cost: 5,
+        range: 3,
+        damage: 1,
+        attackSpeed: 1,
+        color: '#3498db',
+        maxAmmo: 75
+    },
+    RAPID: {
+        name: 'Fast',
+        cost: 10,
+        range: 2,
+        damage: 1,
+        attackSpeed: 3,
+        color: '#16a085',
+        maxAmmo: 50
+    },
+    SNIPER: {
+        name: 'Distance',
+        cost: 20,
+        range: 6,
+        damage: 2,
+        attackSpeed: 0.5,
+        color: '#8e44ad',
+        maxAmmo: 50
+    },
+    GOOP: {
+        name: 'Goop',
+        cost: 20,
+        range: 3,
+        damage: 0,
+        attackSpeed: 1,
+        color: '#27ae60',
+        special: 'slow',
+        slowAmount: 0.75,
+        maxAmmo: 25
+    },
+    AOE: {
+        name: 'AOE',
+        cost: 25,
+        range: 2,
+        damage: 3,
+        attackSpeed: 0.25,
+        color: '#d35400',
+        special: 'aoe',
+        aoeRadius: 2,
+        maxAmmo: 25
+    }
+};
+
+/**
+ * Particle types
+ * 
+ * @enum {string}
+ * @readonly
+ */
+const ParticleTypes = {
+    DEATH_PARTICLE: {
+        lifetime: 1000, // milliseconds
+        speed: 0.1,
+        colors: ['#e74c3c', '#c0392b', '#d35400', '#e67e22']
+    },
+    PROJECTILE: {
+        lifetime: 300,
+        speed: 0.3,
+        color: '#ecf0f1'
+    },
+    AOE_EXPLOSION: {
+        lifetime: 500,
+        initialRadius: 10,
+        finalRadius: 60,
+        color: '#d35400',
+        ringWidth: 3
+    },
+    SLIME_TRAIL: {
+        lifetime: 800,
+        color: '#27ae60',  // Same as Goop tower
+        size: 12,
+        fadeStart: 0.2     // When the fade should begin (percentage of lifetime)
+    }
+};
+
+/**
+ * Enemy types
+ * 
+ * @enum {string}
+ * @readonly
+ */
+const EnemyTypes = {
+    BASIC: {
+        color: '#c0392b',
+        baseHealth: { min: 2, max: 6 },
+        speed: { min: 1, max: 1.5 },
+        damage: 0,
+        isRanged: false
+    },
+    RANGED: {
+        color: '#2c3e50',
+        baseHealth: { min: 1, max: 4 },
+        speed: { min: 0.7, max: 1.2 },
+        damage: 0.3,
+        attackRange: 3,
+        attackSpeed: 1, // attacks per second
+        isRanged: true
+    }
+};
+
+/**
+ * Creates a tower
+ * 
+ * @param {string} type - Tower type
+ * @param {Object} position - Position of the tower
+ */
+function createTower(type, position) {
+    const towerType = TowerTypes[type];
+    return {
+        ...towerType,
+        type,
+        position,
+        lastAttackTime: 0,
+        currentHealth: 10,
+        maxHealth: 10,
+        ammo: towerType.maxAmmo  // Initialize ammo
+    };
+}
+
+/**
+ * Creates an enemy
+ * 
+ * @param {Object} startPosition - Starting position of the enemy
+ */
+function createEnemy(startPosition) {
+    // 20% chance for ranged enemy
+    const type = Math.random() < 0.2 ? 'RANGED' : 'BASIC';
+    const enemyType = EnemyTypes[type];
+    
+    // Scale health ranges with level
+    const levelScaling = 1 + (gameState.level - 1) * 0.25; // increase health by 25% per level
+    const minHealth = Math.floor(enemyType.baseHealth.min * levelScaling);
+    const maxHealth = Math.floor(enemyType.baseHealth.max * levelScaling);
+    
+    const health = Math.floor(Math.random() * 
+        (maxHealth - minHealth + 1)) + minHealth;
+    
+    return {
+        position: { ...startPosition },
+        currentHealth: health,
+        maxHealth: health,
+        speed: enemyType.speed.min + Math.random() * (enemyType.speed.max - enemyType.speed.min),
+        pathIndex: 0,
+        type,
+        lastAttackTime: 0,
+        damage: enemyType.damage
+    };
+}
+
+/**
+ * Creates a particle
+ * 
+ * @param {string} type - Particle type
+ * @param {Object} position - Position of the particle
+ */
+function createParticle(type, position, angle) {
+    return {
+        position: { ...position },
+        velocity: {
+            x: Math.cos(angle) * type.speed,
+            y: Math.sin(angle) * type.speed
+        },
+        color: Array.isArray(type.colors) 
+            ? type.colors[Math.floor(Math.random() * type.colors.length)]
+            : type.color,
+        createdAt: performance.now(),
+        lifetime: type.lifetime,
+        size: 3 + Math.random() * 2
+    };
+}
+
+
+/**
+ * Game state
+ * 
+ * @type {Object}
+ */
+const gameState = {
+    grid: Array(20).fill().map(() => Array(20).fill('empty')),
+    path: [],
+    towers: [],
+    enemies: [],
+    currency: 100,
+    phase: GamePhase.PLACEMENT,
+    isGameOver: false,
+    particles: [],
+    projectiles: [],
+    enemiesDestroyed: 0,
+    enemiesEscaped: 0,
+    level: 1,
+    
+    /**
+     * Resets the game state
+     */
+    resetGame() {
+        this.grid = Array(20).fill().map(() => Array(20).fill('empty'));
+        this.path = [];
+        this.towers = [];
+        this.enemies = [];
+        this.currency = 100;
+        this.phase = GamePhase.PLACEMENT;
+        this.isGameOver = false;
+        this.particles = [];
+        this.projectiles = [];
+        this.enemiesDestroyed = 0;
+        this.enemiesEscaped = 0;
+        this.level = 1;
+    },
+    
+
+    /**
+     * Awards the enemy destroyed
+     */
+    awardEnemyDestroyed() {
+        this.enemiesDestroyed++;
+        // Random reward between 1 and 3
+        const reward = Math.floor(Math.random() * 3) + 1;
+        this.currency += reward;
+    },
+    
+
+    /**
+     * Checks if the level is complete
+     * 
+     * @returns {boolean}
+     */
+    checkLevelComplete() {
+        return this.enemies.length === 0 && 
+               enemiesRemaining === 0 && 
+               this.phase === GamePhase.COMBAT;
+    },
+    
+
+    /**
+     * Advances to the next level
+     */
+    advanceToNextLevel() {
+
+        let ammoBonus = 0;
+        this.towers.forEach(tower => {
+            ammoBonus += tower.ammo * 0.25;
+        });
+        this.currency += Math.floor(ammoBonus);  // Round down to nearest whole number
+        
+        this.level++;
+        this.phase = GamePhase.PLACEMENT;
+        this.towers = [];
+        this.enemies = [];
+        this.projectiles = [];
+        this.particles = [];
+        this.grid = Array(20).fill().map(() => Array(20).fill('empty'));
+    }
+}; 
\ No newline at end of file