-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathisometricRenderer.js
More file actions
624 lines (545 loc) · 24.8 KB
/
Copy pathisometricRenderer.js
File metadata and controls
624 lines (545 loc) · 24.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
/**
* Isometric Renderer Module for AI Alchemist's Lair
* Handles advanced isometric rendering with image assets
*/
import assetLoader from './assetLoader.js';
import { debug } from './utils.js';
/**
* Handles advanced isometric grid rendering with image-based tiles
*/
class IsometricRenderer {
constructor() {
// Track when assets are ready
this.assetsReady = false;
this.checkAssetsInterval = setInterval(() => this.checkAssets(), 500);
}
/**
* Check if required assets are loaded
* @returns {boolean} - True if all required assets are loaded
*/
checkAssets() {
// Check for required assets
const hasFloorTile = !!assetLoader.getAsset('floorTile');
const hasWallTileNE = !!assetLoader.getAsset('wallTileNE');
const hasWallTileNW = !!assetLoader.getAsset('wallTileNW');
// Update assets ready state
this.assetsReady = hasFloorTile && hasWallTileNE && hasWallTileNW;
// Log when assets are ready
if (this.assetsReady) {
debug('RENDERER', 'Isometric renderer assets loaded');
clearInterval(this.checkAssetsInterval);
}
return this.assetsReady;
}
/**
* Render a floor tile at the specified isometric position
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderFloorTile(ctx, isoX, isoY, tileWidth, tileHeight) {
const floorTile = assetLoader.getAsset('floorTile');
if (floorTile) {
// Add a small overlap factor to close gaps between tiles
const overlapFactor = 1.30; // 30% larger to ensure overlap
// Draw floor tile centered on grid position with overlap
ctx.drawImage(
floorTile,
isoX - (tileWidth * overlapFactor) / 2,
isoY - (tileHeight * overlapFactor) / 2,
tileWidth * overlapFactor,
tileHeight * overlapFactor
);
} else {
// Fallback to drawn floor tile if image isn't loaded yet
this.renderBasicFloorTile(ctx, isoX, isoY, tileWidth, tileHeight);
}
}
/**
* Render a basic floor tile (fallback when image not loaded)
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderBasicFloorTile(ctx, isoX, isoY, tileWidth, tileHeight) {
// Create a floor tile path (diamond shape)
ctx.beginPath();
ctx.moveTo(isoX, isoY - tileHeight / 2); // Top point
ctx.lineTo(isoX + tileWidth / 2, isoY); // Right point
ctx.lineTo(isoX, isoY + tileHeight / 2); // Bottom point
ctx.lineTo(isoX - tileWidth / 2, isoY); // Left point
ctx.closePath();
// Fill with a darker base color
ctx.fillStyle = '#333333';
ctx.fill();
// Add grid lines with a subtle cyberpunk glow
ctx.strokeStyle = '#00ffcc44'; // Cyan with transparency
ctx.lineWidth = 1;
ctx.stroke();
// Add a small marker at the center for reference
ctx.fillStyle = '#555555';
ctx.fillRect(isoX - 2, isoY - 2, 4, 4);
}
/**
* Render a wall tile at the north edge
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderNorthWall(ctx, isoX, isoY, tileWidth, tileHeight) {
// Get wall tile from asset loader
const wallTile = assetLoader.getAsset('wallTileNE');
const wallHeight = tileHeight * 2; // Make walls twice as tall
// Use overlap factor for consistent sizing
const overlapFactor = .92;
if (wallTile) {
// Draw wall tile with increased size
ctx.drawImage(
wallTile,
isoX - (tileWidth * overlapFactor) / 2,
isoY - (wallHeight * overlapFactor) / 2, // Position higher to account for wall height
tileWidth * overlapFactor,
wallHeight * overlapFactor
);
} else {
// Fallback to drawn wall if image isn't loaded yet
this.renderBasicWall(ctx, isoX, isoY, tileWidth, tileHeight, 'north');
}
}
/**
* Render a wall tile at the west edge
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderWestWall(ctx, isoX, isoY, tileWidth, tileHeight) {
// Get wall tile from asset loader
const wallTile = assetLoader.getAsset('wallTileNW');
const wallHeight = tileHeight * 2; // Make walls twice as tall
// Use overlap factor for consistent sizing
const overlapFactor = .92;
if (wallTile) {
// Draw wall tile with increased size
ctx.drawImage(
wallTile,
isoX - (tileWidth * overlapFactor) / 2,
isoY - (wallHeight * overlapFactor) / 2, // Position higher to account for wall height
tileWidth * overlapFactor,
wallHeight * overlapFactor
);
} else {
// Fallback to drawn wall if image isn't loaded yet
this.renderBasicWall(ctx, isoX, isoY, tileWidth, tileHeight, 'west');
}
}
/**
* Render a basic wall (fallback when image not loaded)
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
* @param {string} direction - Wall direction ('north' or 'west')
*/
renderBasicWall(ctx, isoX, isoY, tileWidth, tileHeight, direction) {
const wallHeight = 40; // Height of walls in pixels
// Get wall base color and highlight color
const wallBaseColor = '#222255'; // Dark blue base
const wallHighlightColor = '#00ffcc'; // Cyan highlight
// Draw the top face of the wall
ctx.beginPath();
ctx.moveTo(isoX, isoY - tileHeight / 2); // Top point
ctx.lineTo(isoX + tileWidth / 2, isoY); // Right point
ctx.lineTo(isoX, isoY + tileHeight / 2); // Bottom point
ctx.lineTo(isoX - tileWidth / 2, isoY); // Left point
ctx.closePath();
// Fill with wall color
ctx.fillStyle = wallBaseColor;
ctx.fill();
// Add grid lines with a bright highlight
ctx.strokeStyle = `${wallHighlightColor}88`;
ctx.lineWidth = 2;
ctx.stroke();
// Draw the vertical face of the wall
ctx.beginPath();
if (direction === 'north') {
// North wall - left side drawn
ctx.moveTo(isoX - tileWidth / 2, isoY); // Left corner
ctx.lineTo(isoX, isoY + tileHeight / 2); // Bottom corner
ctx.lineTo(isoX, isoY + tileHeight / 2 - wallHeight); // Bottom corner raised
ctx.lineTo(isoX - tileWidth / 2, isoY - wallHeight); // Left corner raised
// Fill with a slightly lighter shade
ctx.fillStyle = this.adjustBrightness(wallBaseColor, 10);
} else {
// West wall - right side drawn
ctx.moveTo(isoX + tileWidth / 2, isoY); // Right corner
ctx.lineTo(isoX, isoY + tileHeight / 2); // Bottom corner
ctx.lineTo(isoX, isoY + tileHeight / 2 - wallHeight); // Bottom corner raised
ctx.lineTo(isoX + tileWidth / 2, isoY - wallHeight); // Right corner raised
// Fill with a slightly lighter shade
ctx.fillStyle = this.adjustBrightness(wallBaseColor, 20);
}
ctx.closePath();
ctx.fill();
// Add glow effect
ctx.strokeStyle = `${wallHighlightColor}66`;
ctx.lineWidth = 1.5;
ctx.stroke();
}
/**
* Render a doorway at the specified position
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - X position in isometric space
* @param {number} isoY - Y position in isometric space
* @param {number} tileWidth - Width of a tile
* @param {number} tileHeight - Height of a tile
* @param {string} direction - Direction of the door ('NE' or 'NW')
* @param {boolean} isOpen - Whether the door is open
* @param {boolean} doubleHeight - Whether to render a multi-height door
*/
renderDoorway(ctx, isoX, isoY, tileWidth, tileHeight, direction, isOpen = false, doubleHeight = false, currentSceneId = '') {
// Block west wall doors (NW direction) to implement complete west wall door removal
if (direction === 'NW') {
console.log('West wall door rendering blocked - NW doors have been completely removed');
return;
}
// Debug door state for other doors that are still allowed
console.log(`Rendering door: direction=${direction}, isOpen=${isOpen}`);
// Calculate wall height for consistent dimensions - increased for better visibility
const wallHeight = tileHeight * 6.5; // Increased height for better door visibility
const overlapFactor = .9; // Increased from 2.0 to make door larger and overlap walls
const verticalOffset = doubleHeight ? -tileHeight * 0.85 : -3; // Added slight upward shift
// Store screen coordinates for use with Coming Soon labels
const screenX = isoX;
const screenY = isoY + verticalOffset;
// Check if we need to render a Coming Soon label
// This direct approach ensures wall doorways in the startRoom show Coming Soon labels
if (currentSceneId === 'startRoom') {
console.log('DOORWAY-DEBUG: Wall doorway in startRoom at', screenX, screenY);
// Only proceed if we have the doorway manager available
if (window.doorwayManager) {
// Call after a short delay to ensure the door is rendered first
setTimeout(() => {
window.doorwayManager.renderComingSoonOverDoor(ctx, screenX, screenY - 20);
}, 100);
}
}
// Use the closed door asset as the base (we know this works)
const doorAssetKey = direction === 'NE' ? 'doorTileNE' : 'doorTileNW';
const doorTile = assetLoader.getAsset(doorAssetKey);
if (doorTile) {
// Draw the base door with increased size to ensure it's visible over walls
// Save context to apply special rendering properties for doors
ctx.save();
// Apply a slight shadow to help door stand out from background wall
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.shadowBlur = 8;
ctx.shadowOffsetY = 2;
// Draw the door with enhanced visibility and slight position adjustment
ctx.drawImage(
doorTile,
isoX - (tileWidth * overlapFactor) / 2,
isoY - (wallHeight * overlapFactor) / 2 + verticalOffset - 5, // Move up slightly
tileWidth * overlapFactor,
wallHeight * overlapFactor
);
ctx.restore();
// If the door should be open, draw a special indicator
if (isOpen) {
// Draw a very distinctive open door indication
ctx.save();
// Draw a bright opening in the door
ctx.fillStyle = 'rgba(0, 255, 255, 0.7)'; // Cyan for open doors
// Draw the door opening as a rectangle
const openingWidth = tileWidth * 0.6;
const openingHeight = wallHeight * 0.7;
ctx.fillRect(
isoX - openingWidth/2,
isoY - openingHeight/2 + verticalOffset,
openingWidth,
openingHeight
);
// Add a text label for clarity during debugging
ctx.fillStyle = 'white';
ctx.font = 'bold 16px Arial';
ctx.textAlign = 'center';
ctx.fillText('OPEN', isoX, isoY + verticalOffset);
ctx.restore();
}
} else {
// Fallback rendering if door assets aren't available
ctx.save();
ctx.fillStyle = isOpen ? 'rgba(0, 200, 255, 0.7)' : 'rgba(200, 100, 0, 0.7)';
ctx.fillRect(
isoX - tileWidth / 2,
isoY - tileHeight + verticalOffset,
tileWidth,
tileHeight * 2
);
// Text indicator
ctx.fillStyle = 'white';
ctx.font = 'bold 14px Arial';
ctx.textAlign = 'center';
ctx.fillText(isOpen ? 'OPEN' : 'CLOSED', isoX, isoY + verticalOffset);
ctx.restore();
}
}
/**
* Render a fallback door when door assets aren't available
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
* @param {string} direction - Direction of the door ('NE' or 'NW')
* @param {boolean} isOpen - Whether the door is open
* @param {boolean} doubleHeight - Whether to render a multi-height door
*/
renderFallbackDoor(ctx, isoX, isoY, tileWidth, tileHeight, direction, isOpen, doubleHeight = false) {
const wallHeight = tileHeight * 3.75; // Back to 2-wall-tile height
const doorColor = '#444466'; // Darker blue-gray
const doorHighlightColor = '#00ffcc'; // Cyan highlight
// Position door in the middle of the 3-row wall
const verticalOffset = doubleHeight ? -tileHeight * 0.85 : 0;
// Draw the appropriate wall first (as a base)
if (direction === 'NE') {
// For triple-height, draw a custom taller wall
if (doubleHeight) {
// Draw a taller north wall
this.renderNorthWallDouble(ctx, isoX, isoY, tileWidth, tileHeight);
} else {
this.renderBasicWall(ctx, isoX, isoY, tileWidth, tileHeight, 'north');
}
} else {
// For triple-height, draw a custom taller wall
if (doubleHeight) {
// Draw a taller west wall
this.renderWestWallDouble(ctx, isoX, isoY, tileWidth, tileHeight);
} else {
this.renderBasicWall(ctx, isoX, isoY, tileWidth, tileHeight, 'west');
}
}
// Now draw a doorway opening on top of the wall
const doorWidth = tileWidth * 0.6;
const doorHeightPixels = wallHeight * 0.7;
// Door vertical position adjustment for proper placement
const doorYOffset = tileHeight * 0.1 + verticalOffset;
// Create door shape based on direction
ctx.beginPath();
if (direction === 'NE') {
// NE door - on north wall (left face)
if (isOpen) {
// Door is open - draw it ajar
ctx.fillStyle = '#000000aa'; // Dark shadow for open doorway
ctx.fillRect(
isoX - tileWidth * 0.3,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.6,
doorHeightPixels * 0.8
);
} else {
// Draw closed door
ctx.fillStyle = doorColor;
ctx.fillRect(
isoX - tileWidth * 0.3,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.6,
doorHeightPixels * 0.8
);
// Door frame
ctx.strokeStyle = doorHighlightColor;
ctx.lineWidth = 2;
ctx.strokeRect(
isoX - tileWidth * 0.3,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.6,
doorHeightPixels * 0.8
);
// Door handle
ctx.fillStyle = doorHighlightColor;
ctx.beginPath();
ctx.arc(
isoX - tileWidth * 0.2,
isoY + doorYOffset,
3,
0,
Math.PI * 2
);
ctx.fill();
}
} else {
// NW door - on west wall (right face)
if (isOpen) {
// Door is open - draw it ajar
ctx.fillStyle = '#000000aa'; // Dark shadow for open doorway
ctx.fillRect(
isoX + tileWidth * 0.1,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.5,
doorHeightPixels * 0.8
);
} else {
// Draw closed door
ctx.fillStyle = doorColor;
ctx.fillRect(
isoX + tileWidth * 0.1,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.5,
doorHeightPixels * 0.8
);
// Door frame
ctx.strokeStyle = doorHighlightColor;
ctx.lineWidth = 2;
ctx.strokeRect(
isoX + tileWidth * 0.1,
isoY - doorHeightPixels * 0.4 + doorYOffset,
doorWidth * 0.5,
doorHeightPixels * 0.8
);
// Door handle
ctx.fillStyle = doorHighlightColor;
ctx.beginPath();
ctx.arc(
isoX + tileWidth * 0.2,
isoY + doorYOffset,
3,
0,
Math.PI * 2
);
ctx.fill();
}
}
// Add glowing doorway effect
ctx.shadowColor = doorHighlightColor;
ctx.shadowBlur = 5;
ctx.beginPath();
ctx.strokeStyle = `${doorHighlightColor}99`;
ctx.lineWidth = 1;
if (direction === 'NE') {
ctx.strokeRect(
isoX - tileWidth * 0.32,
isoY - doorHeightPixels * 0.42 + doorYOffset,
doorWidth * 0.64,
doorHeightPixels * 0.84
);
} else {
ctx.strokeRect(
isoX + tileWidth * 0.08,
isoY - doorHeightPixels * 0.42 + doorYOffset,
doorWidth * 0.54,
doorHeightPixels * 0.84
);
}
ctx.stroke();
// Reset shadow
ctx.shadowBlur = 0;
}
/**
* Render a double-height north wall
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderNorthWallDouble(ctx, isoX, isoY, tileWidth, tileHeight) {
const wallBaseColor = '#222255'; // Dark blue base
const wallHighlightColor = '#00ffcc'; // Cyan highlight
const wallHeight = tileHeight * 5.5; // Taller wall height for 3 rows
const verticalOffset = -tileHeight * 1.2; // Increased offset for triple height
// Draw the top face of the wall (north wall)
ctx.beginPath();
ctx.moveTo(isoX, isoY - tileHeight / 2 + verticalOffset); // Top corner of tile
ctx.lineTo(isoX + tileWidth / 2, isoY + verticalOffset); // Right corner of tile
ctx.lineTo(isoX, isoY + tileHeight / 2 + verticalOffset); // Bottom corner of tile
ctx.lineTo(isoX - tileWidth / 2, isoY + verticalOffset); // Left corner of tile
ctx.closePath();
// Fill with wall color
ctx.fillStyle = wallBaseColor;
ctx.fill();
// Add grid lines with a bright highlight
ctx.strokeStyle = `${wallHighlightColor}88`;
ctx.lineWidth = 2;
ctx.stroke();
// Draw the vertical face of the north wall
ctx.beginPath();
ctx.moveTo(isoX - tileWidth / 2, isoY + verticalOffset); // Left corner
ctx.lineTo(isoX, isoY + tileHeight / 2 + verticalOffset); // Bottom corner
ctx.lineTo(isoX, isoY + tileHeight / 2 - wallHeight + verticalOffset); // Bottom corner raised
ctx.lineTo(isoX - tileWidth / 2, isoY - wallHeight + verticalOffset); // Left corner raised
ctx.closePath();
// Fill with a slightly lighter shade
ctx.fillStyle = this.adjustBrightness(wallBaseColor, 10);
ctx.fill();
// Add glow effect
ctx.strokeStyle = `${wallHighlightColor}66`;
ctx.lineWidth = 1.5;
ctx.stroke();
}
/**
* Render a double-height west wall
* @param {CanvasRenderingContext2D} ctx - Canvas rendering context
* @param {number} isoX - Isometric X position
* @param {number} isoY - Isometric Y position
* @param {number} tileWidth - Width of the tile
* @param {number} tileHeight - Height of the tile
*/
renderWestWallDouble(ctx, isoX, isoY, tileWidth, tileHeight) {
const wallBaseColor = '#222255'; // Dark blue base
const wallHighlightColor = '#00ffcc'; // Cyan highlight
const wallHeight = tileHeight * 5.5; // Taller wall height for 3 rows
const verticalOffset = -tileHeight * 1.2; // Increased offset for triple height
// Draw the top face of the wall (west wall)
ctx.beginPath();
ctx.moveTo(isoX, isoY - tileHeight / 2 + verticalOffset); // Top corner of tile
ctx.lineTo(isoX + tileWidth / 2, isoY + verticalOffset); // Right corner of tile
ctx.lineTo(isoX, isoY + tileHeight / 2 + verticalOffset); // Bottom corner of tile
ctx.lineTo(isoX - tileWidth / 2, isoY + verticalOffset); // Left corner of tile
ctx.closePath();
// Fill with wall color
ctx.fillStyle = wallBaseColor;
ctx.fill();
// Add grid lines with a bright highlight
ctx.strokeStyle = `${wallHighlightColor}88`;
ctx.lineWidth = 2;
ctx.stroke();
// Draw the vertical face of the west wall
ctx.beginPath();
ctx.moveTo(isoX + tileWidth / 2, isoY + verticalOffset); // Right corner
ctx.lineTo(isoX, isoY + tileHeight / 2 + verticalOffset); // Bottom corner
ctx.lineTo(isoX, isoY + tileHeight / 2 - wallHeight + verticalOffset); // Bottom corner raised
ctx.lineTo(isoX + tileWidth / 2, isoY - wallHeight + verticalOffset); // Right corner raised
ctx.closePath();
// Fill with a slightly lighter shade
ctx.fillStyle = this.adjustBrightness(wallBaseColor, 20);
ctx.fill();
// Add glow effect
ctx.strokeStyle = `${wallHighlightColor}66`;
ctx.lineWidth = 1.5;
ctx.stroke();
}
/**
* Utility to adjust color brightness
* @param {string} color - Base color in hex format (#RRGGBB)
* @param {number} percent - Percent to adjust brightness (-100 to 100)
* @returns {string} - Adjusted color
*/
adjustBrightness(color, percent) {
const num = parseInt(color.replace('#', ''), 16);
const r = Math.min(255, Math.max(0, (num >> 16) + percent));
const g = Math.min(255, Math.max(0, ((num >> 8) & 0x00FF) + percent));
const b = Math.min(255, Math.max(0, (num & 0x0000FF) + percent));
return '#' + (b | (g << 8) | (r << 16)).toString(16).padStart(6, '0');
}
}
// Create a singleton instance
const isometricRenderer = new IsometricRenderer();
export { isometricRenderer, IsometricRenderer };