diff options
Diffstat (limited to 'html/space/renderer.js')
-rw-r--r-- | html/space/renderer.js | 202 |
1 files changed, 106 insertions, 96 deletions
diff --git a/html/space/renderer.js b/html/space/renderer.js index 6af271d..04646cf 100644 --- a/html/space/renderer.js +++ b/html/space/renderer.js @@ -1,14 +1,22 @@ // Renderer module using HTML5 Canvas -import { getPlayerState } from './physics.js'; +import { getPlayerState, getWeaponStates } from './physics.js'; import { getGameState } from './gameState.js'; +// Import weapon constants +import { + PRIMARY_COOLDOWN, + SECONDARY_COOLDOWN, + PRIMARY_BURST_COUNT, + PRIMARY_BURST_DELAY +} from './physics.js'; + let canvas; let ctx; let width; let height; // Star field -const stars = []; +let starfield = []; // Declare starfield array const NUM_STARS = 2000; // Increased from 1000 const STAR_FIELD_DEPTH = 20000; // Increased from 2000 @@ -24,60 +32,33 @@ const TARGET_LOCK_THRESHOLD = 20; // Pixels from center to consider locked // Initialize the renderer export function initRenderer() { - canvas = document.createElement('canvas'); - document.body.appendChild(canvas); + console.log('Initializing renderer...'); + canvas = document.getElementById('gameCanvas'); ctx = canvas.getContext('2d'); - // Make canvas fullscreen - function resize() { - width = window.innerWidth; - height = window.innerHeight; - canvas.width = width; - canvas.height = height; - } - - window.addEventListener('resize', resize); - resize(); + // Set canvas size + width = canvas.width = window.innerWidth; + height = canvas.height = window.innerHeight; - // Initialize star field - for (let i = 0; i < NUM_STARS; i++) { - stars.push({ - x: (Math.random() - 0.5) * width * 4, // Increased spread - y: (Math.random() - 0.5) * height * 4, // Increased spread - z: Math.random() * STAR_FIELD_DEPTH, - size: Math.random() * 2 - }); - } + // Initialize starfield + console.log('Creating starfield with', NUM_STARS, 'stars...'); + starfield = Array.from({ length: NUM_STARS }, () => ({ + x: (Math.random() - 0.5) * STAR_FIELD_DEPTH, + y: (Math.random() - 0.5) * STAR_FIELD_DEPTH, + z: Math.random() * STAR_FIELD_DEPTH, + size: Math.random() * 2 + 1 + })); + console.log('Starfield initialized'); } // Project 3D point to 2D screen coordinates -function projectPoint(point, player) { - // Calculate relative position to player - const relativeX = point.x - player.position.x; - const relativeY = point.y - player.position.y; - const relativeZ = point.z - player.position.z; - - // Apply player rotation - const cosY = Math.cos(player.rotation.y); - const sinY = Math.sin(player.rotation.y); - const cosX = Math.cos(player.rotation.x); - const sinX = Math.sin(player.rotation.x); - - // Rotate around Y axis (yaw) - let rotatedX = relativeX * cosY - relativeZ * sinY; - let rotatedZ = relativeX * sinY + relativeZ * cosY; - - // Rotate around X axis (pitch) - let rotatedY = relativeY * cosX - rotatedZ * sinX; - rotatedZ = relativeY * sinX + rotatedZ * cosX; - - // Project to screen - if (rotatedZ <= 0) return null; // Behind camera - - const scale = 1000 / rotatedZ; +function projectPoint(x, y, z) { + if (z <= 0) return null; // Behind camera + + const scale = 2000 / z; // Increased scale factor return { - x: width/2 + rotatedX * scale, - y: height/2 + rotatedY * scale, + x: width/2 + x * scale, + y: height/2 + y * scale, scale }; } @@ -88,7 +69,7 @@ function getTargetLock(player, gameState) { const centerY = height / 2; for (const ship of gameState.enemyShips) { - const projected = projectPoint(ship.position, player); + const projected = projectPoint(ship.x - player.x, ship.y - player.y, ship.z - player.z); if (projected) { const distance = Math.sqrt( Math.pow(projected.x - centerX, 2) + @@ -135,8 +116,8 @@ function drawRadar(player, gameState, targetLock) { // Draw planets gameState.planets.forEach(planet => { - const dx = (planet.position.x - player.position.x) * RADAR_SCALE; - const dy = (planet.position.z - player.position.z) * RADAR_SCALE; + const dx = (planet.x - player.x) * RADAR_SCALE; + const dy = (planet.z - player.z) * RADAR_SCALE; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < RADAR_RADIUS) { @@ -154,8 +135,8 @@ function drawRadar(player, gameState, targetLock) { // Draw enemy ships gameState.enemyShips.forEach(ship => { - const dx = (ship.position.x - player.position.x) * RADAR_SCALE; - const dy = (ship.position.z - player.position.z) * RADAR_SCALE; + const dx = (ship.x - player.x) * RADAR_SCALE; + const dy = (ship.z - player.z) * RADAR_SCALE; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < RADAR_RADIUS) { @@ -181,18 +162,18 @@ function drawSpeedIndicator(player, targetLock) { ctx.fillStyle = targetLock ? TARGET_LOCK_COLOR : HUD_COLOR; ctx.font = '14px monospace'; - // Calculate speed + // Calculate speed from velocity components const speed = Math.sqrt( - player.velocity.x * player.velocity.x + - player.velocity.y * player.velocity.y + - player.velocity.z * player.velocity.z + player.vx * player.vx + + player.vy * player.vy + + player.vz * player.vz ); // Draw speed ctx.fillText(`Speed: ${speed.toFixed(2)}`, 20, height - 40); - // Draw direction - const direction = Math.atan2(player.velocity.x, player.velocity.z); + // Draw direction (using x and z components for heading) + const direction = Math.atan2(player.vx, player.vz); ctx.fillText(`Heading: ${(direction * 180 / Math.PI).toFixed(1)}°`, 20, height - 20); ctx.restore(); @@ -255,6 +236,39 @@ function drawTargetingReticle(player, gameState) { ctx.restore(); } +// Draw weapon cooldown indicators +function drawWeaponCooldowns() { + const weaponStates = getWeaponStates(); + ctx.save(); + ctx.fillStyle = HUD_COLOR; + ctx.font = '14px monospace'; + + // Primary weapon cooldown (bottom left) + const primaryCooldown = weaponStates.primary.cooldown / PRIMARY_COOLDOWN; + ctx.fillText('Primary:', 20, height - 80); + ctx.fillStyle = `rgba(0, 255, 0, ${primaryCooldown})`; + ctx.fillRect(20, height - 70, 100, 10); + ctx.strokeStyle = HUD_COLOR; + ctx.strokeRect(20, height - 70, 100, 10); + + // Secondary weapon cooldown (bottom left, below primary) + const secondaryCooldown = weaponStates.secondary.cooldown / SECONDARY_COOLDOWN; + ctx.fillStyle = HUD_COLOR; + ctx.fillText('Secondary:', 20, height - 50); + ctx.fillStyle = `rgba(0, 255, 0, ${secondaryCooldown})`; + ctx.fillRect(20, height - 40, 100, 10); + ctx.strokeStyle = HUD_COLOR; + ctx.strokeRect(20, height - 40, 100, 10); + + // Draw burst indicator for primary weapon + if (weaponStates.primary.burstCount > 0) { + ctx.fillStyle = HUD_COLOR; + ctx.fillText(`Burst: ${weaponStates.primary.burstCount}`, 20, height - 20); + } + + ctx.restore(); +} + // Main render function export function render() { const player = getPlayerState(); @@ -262,49 +276,44 @@ export function render() { const targetLock = getTargetLock(player, gameState); // Clear canvas - ctx.fillStyle = 'black'; - ctx.fillRect(0, 0, width, height); + ctx.fillStyle = '#000000'; + ctx.fillRect(0, 0, canvas.width, canvas.height); - // Draw star field - ctx.fillStyle = 'white'; - stars.forEach(star => { + // Draw starfield + let starsRendered = 0; + starfield.forEach(star => { // Calculate star position relative to player - const relativeX = star.x - player.position.x; - const relativeY = star.y - player.position.y; - const relativeZ = star.z - player.position.z; - + let relativeX = star.x - player.x; + let relativeY = star.y - player.y; + let relativeZ = star.z - player.z; + // Apply player rotation - const cosY = Math.cos(player.rotation.y); - const sinY = Math.sin(player.rotation.y); - const cosX = Math.cos(player.rotation.x); - const sinX = Math.sin(player.rotation.x); - - // Rotate around Y axis (yaw) - let rotatedX = relativeX * cosY - relativeZ * sinY; - let rotatedZ = relativeX * sinY + relativeZ * cosY; - - // Rotate around X axis (pitch) - let rotatedY = relativeY * cosX - rotatedZ * sinX; - rotatedZ = relativeY * sinX + rotatedZ * cosX; - - // Project to screen - if (rotatedZ <= 0) return; // Behind camera - - const scale = STAR_FIELD_DEPTH / rotatedZ; - const x = width/2 + rotatedX * scale; - const y = height/2 + rotatedY * scale; - const size = star.size * scale; + let rotatedX = relativeX * Math.cos(player.rotation) - relativeY * Math.sin(player.rotation); + let rotatedY = relativeX * Math.sin(player.rotation) + relativeY * Math.cos(player.rotation); + let rotatedZ = relativeZ; - if (x >= 0 && x <= width && y >= 0 && y <= height) { - ctx.beginPath(); - ctx.arc(x, y, size, 0, Math.PI * 2); - ctx.fill(); + // Project to screen coordinates + if (rotatedZ > 0) { + const projected = projectPoint(rotatedX, rotatedY, rotatedZ); + if (projected) { + const brightness = Math.min(1, 2000 / rotatedZ); + ctx.fillStyle = `rgba(255, 255, 255, ${brightness})`; + ctx.beginPath(); + ctx.arc(projected.x, projected.y, star.size * brightness, 0, Math.PI * 2); + ctx.fill(); + starsRendered++; + } } }); + + // Debug output + if (Math.random() < 0.01) { // Only log occasionally to avoid spam + console.log('Stars rendered:', starsRendered); + } // Draw planets gameState.planets.forEach(planet => { - const projected = projectPoint(planet.position, player); + const projected = projectPoint(planet.x - player.x, planet.y - player.y, planet.z - player.z); if (projected) { const radius = planet.radius * projected.scale; ctx.fillStyle = planet.color; @@ -316,7 +325,7 @@ export function render() { // Draw enemy ships gameState.enemyShips.forEach(ship => { - const projected = projectPoint(ship.position, player); + const projected = projectPoint(ship.x - player.x, ship.y - player.y, ship.z - player.z); if (projected) { const size = 20 * projected.scale; ctx.fillStyle = '#ff0000'; @@ -331,7 +340,7 @@ export function render() { // Draw projectiles gameState.projectiles.forEach(projectile => { - const projected = projectPoint(projectile.position, player); + const projected = projectPoint(projectile.x - player.x, projectile.y - player.y, projectile.z - player.z); if (projected) { const size = 3 * projected.scale; ctx.fillStyle = projectile.type === 'primary' ? '#ffff00' : '#00ffff'; @@ -345,4 +354,5 @@ export function render() { drawRadar(player, gameState, targetLock); drawSpeedIndicator(player, targetLock); drawTargetingReticle(player, gameState); + drawWeaponCooldowns(); } \ No newline at end of file |