Chrome Nexus - Cyberpunk Survival
Enemies: 5
WASD: Move | Mouse: Look | Click: Shoot | Space: Jump
]]>
{ this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.renderer.setSize(window.innerWidth, window.innerHeight); }); // Shooting this.renderer.domElement.addEventListener('click', (event) => { this.combatSystem.shoot(this.player.position, this.camera); }); } animate() { requestAnimationFrame(() => this.animate()); const deltaTime = this.clock.getDelta(); const cameraRotation = this.cameraController.update(); // Update player this.playerController.update(deltaTime, cameraRotation); // Update systems this.enemySystem.update(deltaTime); this.combatSystem.update(deltaTime); // Check for player damage const damage = this.enemySystem.checkPlayerDamage(this.player.position); if (damage > 0) { this.playerHealth = Math.max(0, this.playerHealth - damage); this.uiSystem.updateHealth(this.playerHealth / this.maxHealth); } // Check combat hits const hits = this.combatSystem.checkHits(this.enemySystem.enemies); hits.forEach(enemyId => { this.enemySystem.damageEnemy(enemyId, 25); }); // Update UI this.uiSystem.updateEnemyCount(this.enemySystem.enemies.length); this.renderer.render(this.scene, this.camera); } } // Start the game new ChromeNexusGame(); ]]>
{ const building = this.createBuilding(pos.width, pos.height, pos.depth); building.position.set(pos.x, pos.height / 2, pos.z); this.scene.add(building); // Add windows with glow this.addBuildingWindows(building, pos); }); } createBuilding(width, height, depth) { const geometry = new THREE.BoxGeometry(width, height, depth); const material = new THREE.MeshPhongMaterial({ color: 0x2a2a4a, shininess: 30 }); const building = new THREE.Mesh(geometry, material); building.castShadow = true; building.receiveShadow = true; return building; } addBuildingWindows(building, pos) { const windowCount = Math.floor(pos.height / 3); for (let i = 0; i < windowCount; i++) { const windowGeometry = new THREE.PlaneGeometry(0.8, 0.6); const windowMaterial = new THREE.MeshBasicMaterial({ color: Math.random() > 0.7 ? 0x00ffff : 0xff6b9d, transparent: true, opacity: 0.8 }); const window = new THREE.Mesh(windowGeometry, windowMaterial); // Position windows on building faces const side = Math.floor(Math.random() * 4); switch(side) { case 0: // Front window.position.set(pos.width / 2 + 0.1, (i - windowCount/2) * 2.5, 0); window.rotation.y = -Math.PI / 2; break; case 1: // Back window.position.set(-pos.width / 2 - 0.1, (i - windowCount/2) * 2.5, 0); window.rotation.y = Math.PI / 2; break; case 2: // Left window.position.set(0, (i - windowCount/2) * 2.5, pos.depth / 2 + 0.1); break; case 3: // Right window.position.set(0, (i - windowCount/2) * 2.5, -pos.depth / 2 - 0.1); window.rotation.y = Math.PI; break; } building.add(window); } } createNeonSigns() { // Floating neon elements const neonElements = [ {pos: {x: -8, y: 3, z: -12}, color: 0x00ffff, text: "NEXUS"}, {pos: {x: 12, y: 4, z: 8}, color: 0xff0080, text: "CHROME"}, {pos: {x: -18, y: 6, z: 15}, color: 0x8000ff, text: "ARENA"} ]; neonElements.forEach(element => { const signGeometry = new THREE.PlaneGeometry(4, 1); const signMaterial = new THREE.MeshBasicMaterial({ color: element.color, transparent: true, opacity: 0.9 }); const sign = new THREE.Mesh(signGeometry, signMaterial); sign.position.set(element.pos.x, element.pos.y, element.pos.z); this.scene.add(sign); // Add glow effect const glowGeometry = new THREE.PlaneGeometry(5, 1.5); const glowMaterial = new THREE.MeshBasicMaterial({ color: element.color, transparent: true, opacity: 0.2 }); const glow = new THREE.Mesh(glowGeometry, glowMaterial); glow.position.copy(sign.position); glow.position.z -= 0.1; this.scene.add(glow); }); } } ]]>
= 0; i--) { const projectile = this.projectiles[i]; // Move projectile const movement = projectile.direction.clone().multiplyScalar(projectile.speed * deltaTime); projectile.mesh.position.add(movement); // Update life projectile.life -= deltaTime; // Fade out over time const fadeRatio = projectile.life / projectile.maxLife; projectile.mesh.material.opacity = fadeRatio; // Remove expired projectiles if (projectile.life <= 0) { this.scene.remove(projectile.mesh); this.projectiles.splice(i, 1); } } // Update muzzle flashes for (let i = this.muzzleFlashes.length - 1; i >= 0; i--) { const flash = this.muzzleFlashes[i]; flash.life -= deltaTime; const fadeRatio = flash.life / flash.maxLife; flash.mesh.material.opacity = fadeRatio * 0.8; flash.mesh.scale.setScalar(1 + (1 - fadeRatio) * 2); if (flash.life <= 0) { this.scene.remove(flash.mesh); this.muzzleFlashes.splice(i, 1); } } } checkHits(enemies) { const hits = []; this.projectiles.forEach((projectile, pIndex) => { enemies.forEach((enemy, eIndex) => { const distance = projectile.mesh.position.distanceTo(enemy.mesh.position); if (distance < 1.0) { // Hit detection radius hits.push(eIndex); // Create hit effect this.createHitEffect(projectile.mesh.position); // Remove projectile this.scene.remove(projectile.mesh); this.projectiles.splice(pIndex, 1); } }); }); return hits; } createHitEffect(position) { const effectGeometry = new THREE.SphereGeometry(0.5, 8, 6); const effectMaterial = new THREE.MeshBasicMaterial({ color: 0xff4444, transparent: true, opacity: 0.7 }); const effect = new THREE.Mesh(effectGeometry, effectMaterial); effect.position.copy(position); this.scene.add(effect); // Animate effect const startTime = Date.now(); const animate = () => { const elapsed = (Date.now() - startTime) / 1000; const progress = elapsed / 0.3; if (progress >= 1) { this.scene.remove(effect); return; } effect.scale.setScalar(1 + progress * 2); effect.material.opacity = 0.7 * (1 - progress); requestAnimationFrame(animate); }; animate(); } } ]]>
{ const enemy = this.createEnemy(); enemy.position.set(pos.x, 1, pos.z); this.scene.add(enemy); this.enemies.push({ mesh: enemy, health: 50, maxHealth: 50, lastAttack: 0, attackCooldown: 2.0, moveSpeed: 2, detectionRange: 15, attackRange: 8, healthBar: this.createHealthBar(enemy) }); }); } createEnemy() { const enemyGeometry = new THREE.CapsuleGeometry(0.25, 1.2, 4, 8); const enemyMaterial = new THREE.MeshPhongMaterial({ color: 0xff4444, emissive: 0x440000, shininess: 50 }); const enemy = new THREE.Mesh(enemyGeometry, enemyMaterial); enemy.castShadow = true; return enemy; } createHealthBar(enemy) { const barGeometry = new THREE.PlaneGeometry(1.5, 0.2); const barMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.8 }); const healthBar = new THREE.Mesh(barGeometry, barMaterial); healthBar.position.set(0, 2, 0); healthBar.lookAt(0, 2, 1); // Face forward initially enemy.add(healthBar); return healthBar; } update(deltaTime) { const currentTime = Date.now() / 1000; this.enemies.forEach((enemy, index) => { const distanceToPlayer = enemy.mesh.position.distanceTo(this.player.position); // AI behavior if (distanceToPlayer < enemy.detectionRange) { // Move towards player const direction = new THREE.Vector3() .subVectors(this.player.position, enemy.mesh.position) .normalize(); if (distanceToPlayer > enemy.attackRange) { // Move closer const movement = direction.clone().multiplyScalar(enemy.moveSpeed * deltaTime); enemy.mesh.position.add(movement); // Face player enemy.mesh.lookAt(this.player.position); } } // Update health bar orientation (always face camera) if (enemy.healthBar) { enemy.healthBar.lookAt( enemy.mesh.position.x, enemy.mesh.position.y + 2, enemy.mesh.position.z + 10 ); // Update health bar scale based on health const healthRatio = enemy.health / enemy.maxHealth; enemy.healthBar.scale.x = healthRatio; // Change color based on health if (healthRatio > 0.6) { enemy.healthBar.material.color.setHex(0x00ff00); } else if (healthRatio > 0.3) { enemy.healthBar.material.color.setHex(0xffff00); } else { enemy.healthBar.material.color.setHex(0xff0000); } } }); // Remove dead enemies for (let i = this.enemies.length - 1; i >= 0; i--) { if (this.enemies[i].health <= 0) { this.scene.remove(this.enemies[i].mesh); this.enemies.splice(i, 1); } } } damageEnemy(enemyIndex, damage) { if (enemyIndex >= 0 && enemyIndex < this.enemies.length) { this.enemies[enemyIndex].health -= damage; // Create damage flash effect const enemy = this.enemies[enemyIndex]; const originalColor = enemy.mesh.material.color.clone(); enemy.mesh.material.color.setHex(0xffffff); setTimeout(() => { if (enemy.mesh.material) { enemy.mesh.material.color.copy(originalColor); } }, 100); } } checkPlayerDamage(playerPosition) { const currentTime = Date.now() / 1000; let totalDamage = 0; // Prevent damage spam if (currentTime - this.lastDamageTime < 0.5) { return 0; } this.enemies.forEach(enemy => { const distance = enemy.mesh.position.distanceTo(playerPosition); if (distance < enemy.attackRange && currentTime - enemy.lastAttack > enemy.attackCooldown) { totalDamage += 15; enemy.lastAttack = currentTime; this.lastDamageTime = currentTime; } }); return totalDamage; } } ]]>
0.6) { this.healthBar.style.background = 'linear-gradient(90deg, #ff0080, #ff4080)'; } else if (healthRatio > 0.3) { this.healthBar.style.background = 'linear-gradient(90deg, #ffaa00, #ff8800)'; } else { this.healthBar.style.background = 'linear-gradient(90deg, #ff0000, #aa0000)'; } } } updateEnemyCount(count) { if (this.enemyCounter) { this.enemyCounter.textContent = `Enemies: ${count}`; if (count === 0) { this.enemyCounter.textContent = 'VICTORY! All enemies eliminated!'; this.enemyCounter.style.color = '#00ff00'; } } } } ]]>