lighting works!

This commit is contained in:
jwinterm
2025-05-26 13:45:46 -04:00
parent eb2bdaa825
commit f550ee069d
16 changed files with 1643 additions and 231 deletions
+63 -1
View File
@@ -141,10 +141,11 @@ class Game {
player: this.player.getState(), // Use Player's getState method
monster: this.monster ? this.monster.getState() : null, // Use Monster's getState method
visibleTiles: { ...this.visibleTiles }, // Send a copy of visible tiles
lighting: this.calculateLighting(), // Add lighting data
entrance: this.dungeon ? this.dungeon.entrance : null,
exit: this.dungeon ? this.dungeon.exit : null,
treasure: this.dungeon ? this.dungeon.treasure : null,
torches: this.dungeon ? this.dungeon.torches : [], // Include torch positions
// Don't send torch positions - client doesn't need them since lighting is calculated server-side
};
// Debug logging to verify entity data
@@ -155,6 +156,67 @@ class Game {
return state;
}
// Calculate lighting levels for all visible tiles based on distance from torches
calculateLighting() {
const lightingData = {};
// Get torch positions from dungeon
const torches = this.dungeon?.torches || [];
console.log("🔥 calculateLighting() - torch positions:", torches);
// For each visible tile, calculate the lighting level
for (const yKey in this.visibleTiles) {
const y = parseInt(yKey);
lightingData[y] = {};
for (const xKey in this.visibleTiles[y]) {
const x = parseInt(xKey);
// Calculate minimum distance to any torch
let minDistanceToTorch = Infinity;
for (const torch of torches) {
const distance = Math.max(Math.abs(x - torch[0]), Math.abs(y - torch[1])); // Chebyshev distance (diagonal movement)
minDistanceToTorch = Math.min(minDistanceToTorch, distance);
}
// Convert distance to alpha value for darkness overlay
let alpha = 0.0;
if (minDistanceToTorch === 0) {
// On a torch - no darkness
alpha = 0.0;
} else if (minDistanceToTorch === 1) {
// Adjacent to torch - light darkness with flickering effect
alpha = 0.15 + Math.random() * 0.15; // 0.15-0.3
} else if (minDistanceToTorch === 2) {
// Two tiles away - moderate darkness with flickering
alpha = 0.3 + Math.random() * 0.2; // 0.3-0.5
} else if (minDistanceToTorch === 3) {
// Three tiles away - heavier darkness with flickering
alpha = 0.5 + Math.random() * 0.2; // 0.5-0.7
} else {
// Far from torches - scale up to maximum darkness with flickering
const maxDistance = 6; // Beyond this distance, maximum darkness
const scaledDistance = Math.min(minDistanceToTorch, maxDistance);
alpha = 0.7 + (scaledDistance - 3) / (maxDistance - 3) * 0.2; // 0.7-0.9
}
// Clamp alpha to reasonable bounds
alpha = Math.max(0.0, Math.min(0.9, alpha));
lightingData[y][x] = alpha;
}
}
const lightingTileCount = Object.keys(lightingData).reduce((acc, yKey) => acc + Object.keys(lightingData[yKey]).length, 0);
console.log("💡 calculateLighting() - generated lighting for", lightingTileCount, "tiles");
console.log("💡 LIGHTING DATA SAMPLE:", JSON.stringify(lightingData).substring(0, 200));
return lightingData;
}
}
// Check if monster killed player
+21 -1
View File
@@ -173,6 +173,11 @@ function checkGamesTimeout(currentHeight) {
* @param {object} gameState - The game state to broadcast
*/
function sendGameUpdate(playerSocketId, gameState) {
// Debug logging for lighting data in updates
console.log(`📡 sendGameUpdate to ${playerSocketId}:`);
console.log(` - Lighting data: ${!!gameState.lighting} (${gameState.lighting ? Object.keys(gameState.lighting).length : 0} rows)`);
console.log(` - Torch data: ${!!gameState.torches} (${gameState.torches ? gameState.torches.length : 0} torches)`);
// Send to the player
io.to(playerSocketId).emit('game_update', gameState);
@@ -383,8 +388,23 @@ io.on('connection', function(socket) {
const updatedGameState = game.getState(); // Get the new state
// Debug logging for lighting data in game updates
console.log(`🔍 GAME UPDATE DEBUG for ${socket.id}:`);
console.log(` - Player position: (${updatedGameState.player?.x}, ${updatedGameState.player?.y})`);
console.log(` - Visible tiles keys: ${Object.keys(updatedGameState.visibleTiles || {}).length} rows`);
console.log(` - Lighting data included: ${!!updatedGameState.lighting}`);
if (updatedGameState.lighting) {
const lightingTileCount = Object.keys(updatedGameState.lighting).reduce((acc, yKey) =>
acc + Object.keys(updatedGameState.lighting[yKey] || {}).length, 0);
console.log(` - Lighting tiles count: ${lightingTileCount}`);
}
console.log(` - Torch data included: ${!!updatedGameState.torches}`);
if (updatedGameState.torches) {
console.log(` - Torch count: ${updatedGameState.torches.length}`);
}
// Log before sending to client for debugging
console.log(`Sending game_update to ${socket.id} after player move. Player:`, updatedGameState.player, "Visible tiles keys:", Object.keys(updatedGameState.visibleTiles || {}));
console.log(`Sending game_update to ${socket.id} after player move.`);
// Send game update to player (current implementation)
// TODO: In future, also broadcast to spectators of this game
+8 -3
View File
@@ -27,10 +27,15 @@ class Monster {
const dx = Math.sign(player.x - this.x);
const dy = Math.sign(player.y - this.y);
// Check if a tile is passable (floor)
const isPassable = (tile) => {
return tile === "'1" || tile === "'2" || tile === 0; // Support both new and legacy floor types
};
// Try horizontal move first
if (dx !== 0) {
const newX = this.x + dx;
if (dungeon.map[this.y] && dungeon.map[this.y][newX] === 0) {
if (dungeon.map[this.y] && isPassable(dungeon.map[this.y][newX])) {
this.x = newX;
return;
}
@@ -39,7 +44,7 @@ class Monster {
// Try vertical move
if (dy !== 0) {
const newY = this.y + dy;
if (dungeon.map[newY] && dungeon.map[newY][this.x] === 0) {
if (dungeon.map[newY] && isPassable(dungeon.map[newY][this.x])) {
this.y = newY;
return;
}
@@ -52,7 +57,7 @@ class Monster {
for (const [dx, dy] of shuffledDirs) {
const nx = this.x + dx;
const ny = this.y + dy;
if (dungeon.map[ny] && dungeon.map[ny][nx] === 0) {
if (dungeon.map[ny] && isPassable(dungeon.map[ny][nx])) {
this.x = nx;
this.y = ny;
break;