+
+
+
+
+
+
+
+
+
+
+
diff --git a/html/js/game.js b/html/js/game.js
index 6e19788..ec053b8 100644
--- a/html/js/game.js
+++ b/html/js/game.js
@@ -1,3 +1,12 @@
+// This provides a mock socket when the real one isn't available
+if (typeof window !== 'undefined' && !window.socket) {
+ window.socket = {
+ emit: function(event, data) {
+ console.log("[Mock Socket] Would emit:", event, data);
+ }
+ };
+}
+
var Game = {
// Change dimensions to match the display options (25 ร 19 tiles)
_screenWidth: 25, // Used for drawing coordinates (columns)
@@ -13,21 +22,80 @@ var Game = {
_treasure: null,
_gameActive: false,
_message: "", // To display messages like 'waiting'
+ _visibleTiles: {}, // Store currently visible tiles
+ _exploredTiles: {}, // Store all tiles the player has seen
+
+ _isFirefox: function() {
+ return navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
+ },
init: function() {
- // Assuming 'options' is defined globally or passed correctly
- console.log("Creating ROT.Display with options:", options);
+ console.log("Initializing Game...");
+
+ // Check for Firefox
+ var isFirefox = this._isFirefox();
+ if (isFirefox) {
+ console.log("Firefox detected, applying special handling");
+ }
+
try {
- this._display = new ROT.Display(options);
+ // Create a display with the defined options
+ var displayOptions = { ...options }; // Clone options
+
+ // Firefox-specific tweaks if needed
+ if (isFirefox) {
+ // Force numerical dimensions for Firefox
+ displayOptions.width = parseInt(displayOptions.width);
+ displayOptions.height = parseInt(displayOptions.height);
+ }
+
+ console.log("Creating ROT.Display with options:", displayOptions);
+ this._display = new ROT.Display(displayOptions);
console.log("ROT.Display created.");
- // Do not append here; we use external logic to append container
+
+ // Get the DOM element and append display
+ var container = document.querySelector('.rotdis');
+ console.log("Found display container:", container);
+
+ if (container) {
+ // Clear any existing content
+ container.innerHTML = '';
+
+ // Add the new canvas
+ var canvas = this._display.getContainer();
+
+ // Firefox-specific attributes
+ if (isFirefox) {
+ canvas.style.width = 'auto';
+ canvas.style.height = 'auto';
+ canvas.style.display = 'block';
+ canvas.style.margin = 'auto';
+ }
+
+ container.appendChild(canvas);
+ console.log("Display container attached to DOM");
+
+ // Draw initial welcome screen
+ console.log("Drawing initial welcome screen");
+ this._drawWelcomeScreen();
+
+ // Extra check for Firefox
+ if (isFirefox) {
+ // Give Firefox a moment to render properly
+ setTimeout(() => {
+ console.log("Firefox re-render check");
+ this._drawWelcomeScreen();
+ }, 100);
+ }
+
+ } else {
+ console.error("Could not find .rotdis container");
+ }
} catch (e) {
- console.error("Error creating ROT.Display:", e);
- alert("Failed to initialize display. Check console for errors.");
- return;
+ console.error("Error during game initialization:", e);
}
- // Initialize empty map representation based on _mapWidth and _mapHeight
+ // Initialize empty map
this._map = [];
for (var i = 0; i < this._mapWidth; i++) {
this._map[i] = [];
@@ -38,141 +106,309 @@ var Game = {
}
var game = this;
- // Set up keyboard input
+ // Set up keyboard input - ONLY FOR MOVEMENT, not for starting the game
window.addEventListener("keydown", function(e) {
- var code = e.keyCode;
-
- // If game isn't active, ignore all keys except Enter
- if (!game._gameActive && code !== 13) {
+ // Check if an input/textarea has focus - if so, don't capture keys for game
+ const activeElement = document.activeElement;
+ const isInputFocused = activeElement && (
+ activeElement.tagName === 'INPUT' ||
+ activeElement.tagName === 'TEXTAREA' ||
+ activeElement.id === 'm' // Your chat input id
+ );
+
+ // If input is focused or game isn't active, don't process game controls
+ if (isInputFocused || !game._gameActive) {
return;
}
- // Enter key to start game
- if (code === 13 && !game._gameActive) {
- console.log("Enter pressed, sending 'enter' message to server.");
- socket.emit('chat message', 'enter');
- game._message = "Connecting...";
- game._drawWelcomeScreen();
- e.preventDefault();
- return;
- }
-
- // Movement controls
+ // Movement controls (only when game is active AND no input has focus)
var direction = "";
- switch (code) {
+ switch (e.keyCode) {
case 38: case 75: case 87: // up, k, w
direction = "up";
+ e.preventDefault(); // Prevent page scrolling
break;
case 40: case 74: case 83: // down, j, s
direction = "down";
+ e.preventDefault(); // Prevent page scrolling
break;
case 37: case 72: case 65: // left, h, a
direction = "left";
+ e.preventDefault(); // Prevent page scrolling
break;
case 39: case 76: case 68: // right, l, d
direction = "right";
+ e.preventDefault(); // Prevent page scrolling
break;
default:
return;
}
- if (direction && game._gameActive) {
- socket.emit('move', direction);
- e.preventDefault();
+ // If a direction key was pressed, update local state and send to server
+ if (direction) {
+ console.log("Game state updated:", direction);
+
+ // Send the move command to the server
+ if (window.socket) {
+ console.log("Sending move command to server:", direction);
+ window.socket.emit('move', direction);
+ }
}
});
- // Draw welcome screen
- this._message = "Press Enter or type 'enter' to Play!";
+ // Force draw welcome screen
+ this._gameActive = false;
+ this._message = "Type 'enter' in chat to play!";
+ console.log("Drawing initial welcome screen");
this._drawWelcomeScreen();
+
+ // Verify welcome screen was drawn by checking for canvas content
+ setTimeout(() => {
+ const container = this._display.getContainer();
+ const canvas = container.querySelector("canvas");
+ if (canvas) {
+ console.log("Canvas dimensions:", canvas.width, canvas.height);
+ console.log("Canvas is visible:", canvas.style.display !== "none");
+ }
+ }, 500);
},
// Initialize game with data from server
startGame: function(data) {
console.log("Starting game with data:", data);
- this._map = data.map;
- this._player = data.player;
- this._monster = data.monster;
- this._entrance = data.entrance;
- this._exit = data.exit;
- this._treasure = data.treasure;
- this._gameActive = true;
+ if (!data) {
+ console.error("No game data received!");
+ return false;
+ }
- this._drawGameScreen();
+ try {
+ // Set game as active
+ this._gameActive = true;
+
+ // Set all game properties from data
+ this._player = data.player || { x: 12, y: 12 };
+ this._monster = data.monster;
+ this._entrance = data.entrance;
+ this._exit = data.exit;
+ this._treasure = data.treasure;
+
+ // Get visible tiles, ensuring they're valid
+ if (data.visibleTiles && typeof data.visibleTiles === 'object') {
+ // Store the visible tiles
+ this._visibleTiles = data.visibleTiles;
+ console.log("Visible tiles:", Object.keys(this._visibleTiles).length, "rows");
+ } else {
+ // If no tiles, create a basic visible area around player
+ console.log("No visible tiles provided, creating basic view");
+ this._visibleTiles = {};
+ const px = this._player.x;
+ const py = this._player.y;
+
+ // Create a 5x5 visible area around player
+ for (let y = py-2; y <= py+2; y++) {
+ if (!this._visibleTiles[y]) this._visibleTiles[y] = {};
+ for (let x = px-2; x <= px+2; x++) {
+ this._visibleTiles[y][x] = 0; // Floor tiles
+ }
+ }
+ }
+
+ // Update explored tiles
+ this._updateExploredTiles();
+
+ // Clear and redraw the screen
+ this.clearDisplay();
+
+ console.log("Drawing game screen for active game");
+ console.log("Player position:", this._player);
+
+ // Draw the game with explicit console logging after each step
+ this._drawGameScreen();
+
+ return true;
+ } catch (err) {
+ console.error("Error starting game:", err);
+ return false;
+ }
},
-
+
+ // Update game state with new data from server
+ updateGameState: function(data) {
+ console.log("๐ฒ Updating game state with:", data);
+
+ if (!data) {
+ console.error("No update data received!");
+ return;
+ }
+
+ try {
+ // Update player position
+ if (data.player) {
+ console.log("Player position updated:", data.player);
+ this._player = data.player;
+ }
+
+ // Update monster position
+ if (data.monster !== undefined) {
+ this._monster = data.monster;
+ }
+
+ // Update visible tiles
+ if (data.visibleTiles && Object.keys(data.visibleTiles).length > 0) {
+ console.log("Visible tiles updated:", Object.keys(data.visibleTiles).length, "rows");
+ this._visibleTiles = data.visibleTiles;
+ this._updateExploredTiles();
+ }
+
+ // Redraw the game screen
+ console.log("Redrawing game screen after update");
+ this._drawGameScreen();
+ } catch (err) {
+ console.error("Error updating game state:", err);
+ }
+ },
+
+ _updateExploredTiles: function() {
+ // Add all currently visible tiles to explored tiles
+ for (var y in this._visibleTiles) {
+ if (!this._exploredTiles[y]) this._exploredTiles[y] = {};
+
+ for (var x in this._visibleTiles[y]) {
+ this._exploredTiles[y][x] = this._visibleTiles[y][x];
+ }
+ }
+ },
+
clearDisplay: function() {
// Clear the entire display area
this._display.clear();
},
_drawGameScreen: function() {
+ console.log("Drawing game screen...");
+
+ // Clear the display
this.clearDisplay();
-
- // Draw map
- for (var x = 0; x < this._mapWidth; x++) {
- for (var y = 0; y < this._mapHeight; y++) {
- var tile = this._map[y] && this._map[y][x] ? this._map[y][x] : 1;
+
+ // Calculate screen center for display
+ const centerX = Math.floor(this._screenWidth / 2);
+ const centerY = Math.floor(this._screenHeight / 2);
+
+ console.log("Screen center:", centerX, centerY);
+
+ // Draw visible tiles centered on player
+ for (let relY in this._visibleTiles) {
+ relY = parseInt(relY);
+ for (let relX in this._visibleTiles[relY]) {
+ relX = parseInt(relX);
- if (tile === 0) {
- this._display.draw(x, y, "'", "#fff"); // Floor
- } else {
- this._display.draw(x, y, "#", "#777"); // Wall
+ // Convert to screen coordinates (centered)
+ const screenX = centerX + relX;
+ const screenY = centerY + relY;
+
+ // Only draw if on screen
+ if (screenX >= 0 && screenY >= 0 && screenX < this._screenWidth && screenY < this._screenHeight) {
+ const tileType = this._visibleTiles[relY][relX];
+
+ // Draw tile based on type
+ if (tileType === 1) { // Wall
+ this._display.draw(screenX, screenY, '#', '#fff', '#000');
+ } else { // Floor
+ this._display.draw(screenX, screenY, '.', '#888', '#000');
+ }
}
}
}
-
- // Draw special features
- if (this._entrance) {
- this._display.draw(this._entrance[0], this._entrance[1], "<", "#0f0");
- }
- if (this._exit) {
- this._display.draw(this._exit[0], this._exit[1], ">", "#0f0");
- }
+ // Always draw player at center of screen
+ this._display.draw(centerX, centerY, '@', '#ff0', '#000');
+ console.log("Drew player at center:", centerX, centerY);
- if (this._treasure && (!this._player || !this._player.hasTreasure)) {
- this._display.draw(this._treasure[0], this._treasure[1], "$", "#ff0");
- }
+ // Draw other entities if visible (treasure, exit, entrance)
+ // ... additional drawing code for other entities ...
+
+ console.log("Game screen drawing complete");
+ },
+
+ _isVisible: function(x, y) {
+ // Check if a tile is currently visible
+ return this._visibleTiles[y] && this._visibleTiles[y][x] !== undefined;
+ },
+
+ // Add these functions to your client-side Game object (not the server-side one)
- // Draw player
- if (this._player) {
- this._display.draw(this._player.x, this._player.y, "@", "#fff");
+ // Function to switch to ASCII mode
+ switchToAsciiMode: function() {
+ console.log("Switching to ASCII mode");
+
+ var asciiOptions = {
+ width: 25,
+ height: 19,
+ fontSize: 16,
+ fontFamily: "monospace",
+ bg: "#000",
+ fg: "#fff"
+ };
+
+ try {
+ // Create new display with ASCII mode
+ var newDisplay = new ROT.Display(asciiOptions);
+
+ // Replace the existing display
+ var container = document.querySelector('.rotdis');
+ if (container) {
+ container.innerHTML = '';
+ container.appendChild(newDisplay.getContainer());
+ this._display = newDisplay;
+
+ // Redraw current game state
+ if (this._gameActive) {
+ this._drawGameScreen();
+ } else {
+ this._drawWelcomeScreen();
+ }
+ } else {
+ console.error("Could not find .rotdis container");
+ }
+ } catch (err) {
+ console.error("Error switching to ASCII mode:", err);
}
-
- // Draw monster
- if (this._monster) {
- this._display.draw(this._monster.x, this._monster.y, "~", "#f00");
- }
-
- // Draw status line
- var statusY = this._mapHeight; // Position below map
- this._display.drawText(0, statusY, "--------------------------------------------------------------------------------"); // Separator
- statusY++;
-
- var statusLine = `Use Arrows/WASD/HJKL. Find ($) and reach exit (>). Avoid (~).`;
- if (this._player && this._player.hasTreasure) {
- statusLine = "You have the treasure ($)! Reach the exit (>)!";
- }
- this._display.drawText(1, statusY, statusLine);
},
+ // Fix the welcome screen drawing
_drawWelcomeScreen: function() {
- this.clearDisplay();
+ console.log("Drawing welcome screen...");
+ this._display.clear();
+
+ // Draw borders
+ for (var x = 0; x < this._display.getOptions().width; x++) {
+ for (var y = 0; y < this._display.getOptions().height; y++) {
+ if (x === 0 || y === 0 || x === this._display.getOptions().width-1 || y === this._display.getOptions().height-1) {
+ this._display.draw(x, y, "#", "#666", "#000");
+ }
+ }
+ }
+
+ // Draw welcome text
+ var centerX = Math.floor(this._display.getOptions().width / 2);
+ var centerY = Math.floor(this._display.getOptions().height / 2);
+
+ // For ASCII mode, we can use drawText with colors
var y = 5;
this._display.drawText(this._screenWidth / 2 - 5, y++, "%c{yellow}WOWGUE");
y++;
+ this._display.drawText(this._screenWidth / 2 - 11, y++, "Type enter to start!");
+ this._display.drawText(this._screenWidth / 2 - 11, y++, "Or type help...");
y+=2;
this._display.drawText(this._screenWidth / 2 - 10, y++, "@ - This is you");
this._display.drawText(this._screenWidth / 2 - 10, y++, "> - Escape the dungeon");
- this._display.drawText(this._screenWidth / 2 - 10, y++, "~ - Avoid the monster");
- this._display.drawText(this._screenWidth / 2 - 10, y++, "$ - Find the treasure");
+ this._display.drawText(this._screenWidth / 2 - 10, y++, "~ - Avoid the wonster");
+ this._display.drawText(this._screenWidth / 2 - 10, y++, "$ - Secure the bag");
y+=2;
- // Display dynamic message (like waiting or error)
- if (this._message) {
- this._display.drawText(this._screenWidth / 2 - this._message.length / 2, y++, `%c{yellow}${this._message}`);
- }
+
+ // Draw instructions
+ this._display.drawText(2, this._display.getOptions().height - 2, "Type enter in chat =");
},
_drawWinScreen: function(hasTreasure) {
@@ -223,5 +459,136 @@ var Game = {
getScreenHeight: function() {
return this._screenHeight;
+ },
+
+ // Add these functions to your Game object
+
+ // Check if we're in ASCII mode
+ isAsciiMode: function() {
+ if (!this._display) return false;
+ var options = this._display.getOptions();
+ return !options.layout || options.layout !== "tile";
+ },
+
+ // Switch to ASCII mode
+ switchToAsciiMode: function() {
+ console.log("Switching to ASCII mode");
+
+ var asciiOptions = {
+ width: 25,
+ height: 19,
+ fontSize: 16,
+ fontFamily: "monospace",
+ bg: "#000",
+ fg: "#fff"
+ };
+
+ try {
+ // Create new display with ASCII mode
+ var newDisplay = new ROT.Display(asciiOptions);
+
+ // Replace the existing display in DOM
+ var container = document.querySelector('.rotdis');
+ if (container) {
+ container.innerHTML = '';
+ container.appendChild(newDisplay.getContainer());
+
+ // Update the game's display reference
+ this._display = newDisplay;
+
+ console.log("Switched to ASCII mode successfully");
+
+ // Redraw current game state
+ if (this._gameActive) {
+ this._drawGameScreen();
+ } else {
+ this._drawWelcomeScreen();
+ }
+
+ return true;
+ } else {
+ console.error("Could not find .rotdis container to replace display");
+ return false;
+ }
+ } catch (err) {
+ console.error("Error switching to ASCII mode:", err);
+ return false;
+ }
+ },
+
+ // Switch to tile mode
+ switchToTileMode: function() {
+ console.log("Switching to tile mode");
+
+ try {
+ // Create new display with tile mode
+ var newDisplay = new ROT.Display(options);
+
+ // Replace the existing display in DOM
+ var container = document.querySelector('.rotdis');
+ if (container) {
+ container.innerHTML = '';
+ container.appendChild(newDisplay.getContainer());
+
+ // Update the game's display reference
+ this._display = newDisplay;
+
+ console.log("Switched to tile mode successfully");
+
+ // Redraw current game state
+ if (this._gameActive) {
+ this._drawGameScreen();
+ } else {
+ this._drawWelcomeScreen();
+ }
+
+ return true;
+ } else {
+ console.error("Could not find .rotdis container to replace display");
+ return false;
+ }
+ } catch (err) {
+ console.error("Error switching to tile mode:", err);
+ return false;
+ }
}
-};
\ No newline at end of file
+};
+
+socket.on('game_start', function(data) {
+ console.log("๐ฎ Game start received with data:", data);
+ $('#messages').append($('
').text("Starting game..."));
+
+ if (!data) {
+ $('#messages').append($('
').text("Error: No game data received"));
+ return;
+ }
+
+ try {
+ // Make sure all game UI elements are visible
+ $('.container, .banner, .rotdis, .chat-container').css('display', '');
+
+ // Display what we received
+ $('#messages').append($('
').text(`Entering the dungeon...`));
+
+ // Start the game with received data
+ var success = Game.startGame(data);
+ console.log("Game start result:", success ? "SUCCESS" : "FAILED");
+
+ if (!success) {
+ $('#messages').append($('