Files
wownerogue/html/js/renderEngine.js
T

210 lines
9.5 KiB
JavaScript

// RenderEngine - Handles game screen rendering and drawing logic
var RenderEngine = {
defaultFg: "#FFF",
init: function(screenWidth, screenHeight) {
this._screenWidth = screenWidth;
this._screenHeight = screenHeight;
},
isVisible: function(x, y, visibleTiles) {
return visibleTiles[y] && visibleTiles[y][x] !== undefined;
},
drawGameScreen: function(gameState) {
if (!DisplayManager.ensureDisplay()) return;
// Ensure we have a clean display first
DisplayManager.clearDisplay();
const display = DisplayManager.getDisplay();
const player = gameState.player;
const monster = gameState.monster;
const items = gameState.items;
const entrance = gameState.entrance;
const exit = gameState.exit;
const treasure = gameState.treasure;
const torches = gameState.torches || []; // New torch positions
const visibleTiles = gameState.visibleTiles || {};
const exploredTiles = gameState.exploredTiles || {};
const message = gameState.message;
// Get configured tile types from options
const playerTile = window.GameTiles ? window.GameTiles.getPlayerTile() : '@';
const treasureTile = window.GameTiles ? window.GameTiles.getTreasureTile() : '$W';
const monsterTile = window.GameTiles ? window.GameTiles.getMonsterTile() : '~';
const torchTile = window.GameTiles ? window.GameTiles.getTorchTile() : 'torch';
const playerWX = player.x;
const playerWY = player.y;
const centerX = Math.floor(this._screenWidth / 2);
const centerY = Math.floor(this._screenHeight / 2);
const topLeftWX = playerWX - centerX;
const topLeftWY = playerWY - centerY;
for (let sy = 0; sy < this._screenHeight; sy++) {
for (let sx = 0; sx < this._screenWidth; sx++) {
const wx = topLeftWX + sx;
const wy = topLeftWY + sy;
let charStack = [];
let fgStack = [];
let bgStack = [];
let baseChar = ' ';
let baseFg = this.defaultFg;
let tileType;
// Render base terrain
if (this.isVisible(wx, wy, visibleTiles)) {
tileType = visibleTiles[wy][wx];
baseFg = this.defaultFg;
// Handle new string-based tile system
if (tileType === '#') {
baseChar = '#'; // Wall
} else if (tileType === "'1" || tileType === "'2") {
baseChar = tileType; // Use the specific floor tile type
} else if (tileType === 'torch') {
baseChar = '#'; // Torch tiles are walls with torches on top
} else if (tileType === 1) {
baseChar = '#'; // Legacy wall support
} else if (tileType === 0) {
baseChar = "'1"; // Legacy floor support - use primary floor
} else {
// Use the tile type directly if it's a string
baseChar = tileType || "'1"; // Default to primary floor for safety
}
} else if (exploredTiles[wy] && exploredTiles[wy][wx] !== undefined) {
tileType = exploredTiles[wy][wx];
baseFg = this.defaultFg;
// Handle new string-based tile system for explored tiles
if (tileType === '#') {
baseChar = '#'; // Wall
} else if (tileType === "'1" || tileType === "'2") {
baseChar = tileType; // Use the specific floor tile type
} else if (tileType === 'torch') {
baseChar = '#'; // Torch tiles are walls with torches on top
} else if (tileType === 1) {
baseChar = '#'; // Legacy wall support
} else if (tileType === 0) {
baseChar = "'1"; // Legacy floor support - use primary floor
} else {
// Use the tile type directly if it's a string
baseChar = tileType || "'1"; // Default to primary floor for safety
}
} else {
// No visible or explored tile - render empty space
baseChar = ' ';
baseFg = this.defaultFg;
}
// Only add to stacks if we have a valid character
if (baseChar && baseChar !== ' ') {
charStack.push(baseChar);
// Use black transparent overlay for explored tiles, normal colors for currently visible tiles
if (this.isVisible(wx, wy, visibleTiles)) {
fgStack.push("transparent"); // Currently visible - use normal tile colors
} else {
fgStack.push("rgba(0, 0, 0, 0.6)"); // Explored but not visible - use dark transparent overlay
}
bgStack.push("transparent"); // Always transparent background for terrain
}
// Render items
if (items) {
for (const itemKey in items) {
if (items.hasOwnProperty(itemKey)) {
const currentItem = items[itemKey];
if (currentItem && currentItem.x === wx && currentItem.y === wy && this.isVisible(wx, wy, visibleTiles)) {
charStack.push('$');
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
}
}
}
// Render entrance
if (entrance && entrance[0] === wx && entrance[1] === wy && this.isVisible(wx, wy, visibleTiles)) {
charStack.push('<');
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
// Render exit
if (exit && exit[0] === wx && exit[1] === wy && this.isVisible(wx, wy, visibleTiles)) {
charStack.push('>');
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
// Render treasure
if (treasure && treasure[0] === wx && treasure[1] === wy && this.isVisible(wx, wy, visibleTiles)) {
charStack.push(treasureTile);
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
// Render torches (check if this tile has a torch)
if (this.isVisible(wx, wy, visibleTiles) && visibleTiles[wy][wx] === 'torch') {
charStack.push(torchTile);
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
// Render monster
if (monster && monster.x === wx && monster.y === wy && this.isVisible(wx, wy, visibleTiles)) {
charStack.push(monsterTile);
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
// Render player (always on top)
if (wx === playerWX && wy === playerWY) {
charStack.push(playerTile);
fgStack.push("transparent"); // Use transparent for now
bgStack.push("transparent");
}
if (charStack.length > 0) {
// Validate array lengths
while (fgStack.length < charStack.length) fgStack.push("transparent");
while (bgStack.length < charStack.length) bgStack.push("transparent");
// Validate characters are in tileMap
for (let i = 0; i < charStack.length; i++) {
if (!charStack[i] || (window.options?.tileMap && !window.options.tileMap.hasOwnProperty(charStack[i]))) {
// Default to primary floor if tile not found
charStack[i] = "'1";
}
if (!fgStack[i]) fgStack[i] = "transparent";
if (!bgStack[i]) bgStack[i] = "transparent";
}
try {
display.draw(sx, sy, charStack, fgStack, bgStack);
} catch (error) {
display.draw(sx, sy, ["'"], ["transparent"], ["transparent"]);
}
}
}
}
// Render message at bottom if present
if (message) {
ScreenManager.drawCenteredText(this._screenHeight - 1, message);
}
}
};
// Make it available globally
if (typeof window !== 'undefined') {
window.RenderEngine = RenderEngine;
}