diff options
Diffstat (limited to 'html')
-rw-r--r-- | html/fps/game.js | 173 |
1 files changed, 72 insertions, 101 deletions
diff --git a/html/fps/game.js b/html/fps/game.js index 1dd0384..ad4d8bf 100644 --- a/html/fps/game.js +++ b/html/fps/game.js @@ -334,7 +334,6 @@ const render = (ctx) => { const fov = Math.PI / 3; const numRays = Math.floor(width / 2); // Reduce ray count by half const rayResults = []; - const sprites = []; // Pre-calculate common values const halfHeight = height / 2; @@ -355,16 +354,14 @@ const render = (ctx) => { }; } - for (let i = 0; i < width; i += 2) { // Draw every other pixel + for (let i = 0; i < width; i += 2) { const rayIndex = Math.floor(i / 2); const rayAngle = GameState.player.angle - fov/2 + fov * rayIndex / numRays; let distance = 0; let hit = false; - let hitEnemy = null; - let hitItem = null; while (!hit && distance < 20) { - distance += 0.2; // Increase ray step size + distance += 0.2; const testX = GameState.player.x + Math.sin(rayAngle) * distance; const testY = GameState.player.y + Math.cos(rayAngle) * distance; @@ -372,49 +369,10 @@ const render = (ctx) => { if (GameState.level.map[Math.floor(testY)][Math.floor(testX)] === 1) { hit = true; } - - // Check for enemy hits - if (!hit) { - hitEnemy = GameState.enemies.find(enemy => { - const dx = testX - enemy.x; - const dy = testY - enemy.y; - return Math.sqrt(dx * dx + dy * dy) < 0.5; - }); - if (hitEnemy) { - hit = true; - sprites.push({ - type: 'enemy', - x: rayIndex, - distance, - angle: rayAngle, - data: hitEnemy - }); - } - } - - // Check for item hits - if (!hit) { - hitItem = GameState.items.find(item => { - const dx = testX - item.x; - const dy = testY - item.y; - return Math.sqrt(dx * dx + dy * dy) < 0.5; - }); - if (hitItem) { - hit = true; - sprites.push({ - type: 'item', - x: rayIndex, - distance, - angle: rayAngle, - data: hitItem - }); - } - } } rayResults[rayIndex] = { distance, - hitEnemy, angle: rayAngle }; @@ -423,37 +381,23 @@ const render = (ctx) => { const brightnessIndex = Math.floor(brightness * brightnessSteps); const colors = gradientCache[brightnessIndex]; - if (hitEnemy) { - // Draw enemy - const enemyColor = Math.floor(brightness * 255); - ctx.fillStyle = `rgb(${enemyColor}, 0, 0)`; - ctx.fillRect(i, halfHeight - wallHeight/2, 2, wallHeight); - } else if (hitItem) { - // Draw item - const itemColor = hitItem.type === 'health' ? - `rgb(0, ${Math.floor(brightness * 255)}, 0)` : - `rgb(0, ${Math.floor(brightness * 255)}, ${Math.floor(brightness * 255)})`; - ctx.fillStyle = itemColor; - ctx.fillRect(i, halfHeight - wallHeight/2, 2, wallHeight); - } else { - const wallTop = halfHeight - wallHeight/2; - const wallBottom = halfHeight + wallHeight/2; - - // Draw wall with cached colors - ctx.fillStyle = colors.middle; - ctx.fillRect(i, wallTop, 2, wallHeight); // Draw 2 pixels wide - - // Draw top and bottom highlights - ctx.fillStyle = colors.top; - ctx.fillRect(i, wallTop, 2, 1); - ctx.fillStyle = colors.bottom; - ctx.fillRect(i, wallBottom - 1, 2, 1); - - // Draw vertical lines less frequently - if (i % 8 === 0) { - ctx.fillStyle = colors.line; - ctx.fillRect(i, wallTop, 2, wallHeight); - } + const wallTop = halfHeight - wallHeight/2; + const wallBottom = halfHeight + wallHeight/2; + + // Draw wall with cached colors + ctx.fillStyle = colors.middle; + ctx.fillRect(i, wallTop, 2, wallHeight); + + // Draw top and bottom highlights + ctx.fillStyle = colors.top; + ctx.fillRect(i, wallTop, 2, 1); + ctx.fillStyle = colors.bottom; + ctx.fillRect(i, wallBottom - 1, 2, 1); + + // Draw vertical lines less frequently + if (i % 8 === 0) { + ctx.fillStyle = colors.line; + ctx.fillRect(i, wallTop, 2, wallHeight); } } @@ -531,35 +475,62 @@ const render = (ctx) => { ctx.fillText(`Ammo: ${GameState.player.ammo}`, 80, 80); ctx.fillText(`Score: ${GameState.player.score}`, 80, 115); - // Draw sprites with proper wall occlusion - sprites.forEach(sprite => { - // Calculate sprite size based on distance - const baseSize = 0.5; // Base size in world units - const screenSize = (baseSize / sprite.distance) * height; // Scale based on distance - const spriteX = sprite.x - screenSize/2; - const spriteY = halfHeight - screenSize/2; - - // Only draw if not occluded by a wall - if (sprite.distance < rayResults[sprite.x].distance) { - if (sprite.type === 'enemy') { - // Draw enemy as red square - ctx.fillStyle = '#f00'; - ctx.fillRect(spriteX, spriteY, screenSize, screenSize); - } else if (sprite.data.type === 'health') { - // Draw health as green square - ctx.fillStyle = '#0f0'; - ctx.fillRect(spriteX, spriteY, screenSize, screenSize); - } else if (sprite.data.type === 'ammo') { - // Draw ammo as cyan square - ctx.fillStyle = '#0ff'; - ctx.fillRect(spriteX, spriteY, screenSize, screenSize); - } else if (sprite.data.type === 'flag') { - // Draw flag as yellow square - ctx.fillStyle = '#ff0'; - ctx.fillRect(spriteX, spriteY, screenSize, screenSize); + // Draw sprites + const drawSprite = (x, y, distance, type) => { + // Calculate screen position + const dx = x - GameState.player.x; + const dy = y - GameState.player.y; + const angle = Math.atan2(dx, dy) - GameState.player.angle; + + // Convert to screen coordinates + const screenX = (angle / (Math.PI / 3) + 0.5) * width; + const screenY = height / 2; + + // Calculate size based on distance + const baseSize = 0.5; + const size = (baseSize / distance) * height; + + // Only draw if on screen and not behind a wall + if (screenX >= 0 && screenX < width) { + const wallDistance = rayResults[Math.floor(screenX / 2)].distance; + if (distance < wallDistance) { + // Set color based on type + if (type === 'enemy') { + ctx.fillStyle = '#f00'; + } else if (type === 'health') { + ctx.fillStyle = '#0f0'; + } else if (type === 'ammo') { + ctx.fillStyle = '#0ff'; + } else if (type === 'flag') { + ctx.fillStyle = '#ff0'; + } + + // Draw single square + ctx.fillRect(screenX - size/2, screenY - size/2, size, size); } } + }; + + // Draw all sprites + GameState.enemies.forEach(enemy => { + const dx = enemy.x - GameState.player.x; + const dy = enemy.y - GameState.player.y; + const distance = Math.sqrt(dx * dx + dy * dy); + drawSprite(enemy.x, enemy.y, distance, 'enemy'); }); + + GameState.items.forEach(item => { + const dx = item.x - GameState.player.x; + const dy = item.y - GameState.player.y; + const distance = Math.sqrt(dx * dx + dy * dy); + drawSprite(item.x, item.y, distance, item.type); + }); + + // Draw flag + const dx = GameState.level.flag.x - GameState.player.x; + const dy = GameState.level.flag.y - GameState.player.y; + const flagDistance = Math.sqrt(dx * dx + dy * dy); + drawSprite(GameState.level.flag.x, GameState.level.flag.y, flagDistance, 'flag'); // Draw particles GameState.particles.forEach(particle => { |