|
32 | 32 | generateTileNumber, |
33 | 33 | generateThiefTile |
34 | 34 | } from '$lib/SpriteGenerators'; |
35 | | - import { compareWorlds, getClosestPoint, getTwoClosestPoints } from './mapUtils'; |
| 35 | + import { getClosestPoint, getTwoClosestPoints } from './mapUtils'; |
36 | 36 | import * as honeycombGrid from 'honeycomb-grid'; |
37 | 37 | import type { Grid as HoneycombGrid } from 'honeycomb-grid'; |
38 | 38 | const { defineHex, Grid, Orientation } = honeycombGrid; |
39 | 39 |
|
40 | 40 | let container: HTMLDivElement | undefined; |
| 41 | + let parentElement: HTMLElement | null = null; |
41 | 42 |
|
42 | 43 | const hexSize = 200; |
43 | 44 | const tileHeight = 348; |
44 | 45 | const tileWidth = 400; |
45 | 46 | const lineWidth = 14; |
| 47 | + const tilePath = '/img/tilesets/'; |
| 48 | + const tileStyle = 'realistic'; |
| 49 | + const assetsToLoad = [ |
| 50 | + // Tiles |
| 51 | + `${tilePath}${tileStyle}/clay.png`, |
| 52 | + `${tilePath}${tileStyle}/desert.png`, |
| 53 | + `${tilePath}${tileStyle}/grain.png`, |
| 54 | + `${tilePath}${tileStyle}/wood.png`, |
| 55 | + `${tilePath}${tileStyle}/stone.png`, |
| 56 | + `${tilePath}${tileStyle}/wool.png`, |
| 57 | + `${tilePath}${tileStyle}/ocean.png`, |
| 58 | + // Pieces |
| 59 | + '/img/pieces/house.png', |
| 60 | + '/img/pieces/city.png', |
| 61 | + '/img/pieces/thief.png', |
| 62 | + // Special |
| 63 | + `${tilePath}shared/scorch-with-thief.png`, |
| 64 | + // Harbors |
| 65 | + `${tilePath}${tileStyle}/woodharbor.png`, |
| 66 | + `${tilePath}${tileStyle}/woolharbor.png`, |
| 67 | + `${tilePath}${tileStyle}/grainharbor.png`, |
| 68 | + `${tilePath}${tileStyle}/clayharbor.png`, |
| 69 | + `${tilePath}${tileStyle}/stoneharbor.png`, |
| 70 | + `${tilePath}${tileStyle}/threetooneharbor.png`, |
| 71 | + // Numbers |
| 72 | + '/img/numbers/2.png', |
| 73 | + '/img/numbers/3.png', |
| 74 | + '/img/numbers/4.png', |
| 75 | + '/img/numbers/5.png', |
| 76 | + '/img/numbers/6.png', |
| 77 | + '/img/numbers/8.png', |
| 78 | + '/img/numbers/9.png', |
| 79 | + '/img/numbers/10.png', |
| 80 | + '/img/numbers/11.png', |
| 81 | + '/img/numbers/12.png' |
| 82 | + ]; |
46 | 83 |
|
47 | 84 | let app: Application | undefined; |
48 | 85 | let worldContainer: Container | undefined; |
|
78 | 115 |
|
79 | 116 | // Store event handlers for cleanup |
80 | 117 | let wheelHandler: ((event: WheelEvent) => void) | undefined; |
| 118 | + let assetsLoaded = false; |
| 119 | + let latestWorld: World | undefined; |
| 120 | + let loadingPromise: Promise<void> | undefined; |
81 | 121 |
|
82 | 122 | const currentPlayer: Player | undefined = $derived( |
83 | 123 | gameState.world?.players.find((player: Player) => player.name === gameState.playerName) |
84 | 124 | ); |
85 | 125 |
|
86 | 126 | $effect(() => { |
87 | | - drawMap(gameState.world); |
| 127 | + updateMap(gameState.world); |
88 | 128 | }); |
89 | 129 |
|
90 | 130 | $effect(() => { |
|
114 | 154 | return; |
115 | 155 | } |
116 | 156 |
|
117 | | - height = container.clientHeight / (window.devicePixelRatio || 1); |
118 | | - width = container.clientWidth / (window.devicePixelRatio || 1); |
| 157 | + const target = parentElement ?? container; |
| 158 | + const ratio = window.devicePixelRatio || 1; |
| 159 | + height = target.clientHeight / ratio; |
| 160 | + width = target.clientWidth / ratio; |
| 161 | + container.style.width = `${target.clientWidth}px`; |
| 162 | + container.style.height = `${target.clientHeight}px`; |
119 | 163 | app.renderer.resize(width, height); |
120 | 164 | }; |
121 | 165 |
|
|
317 | 361 | }); |
318 | 362 | }; |
319 | 363 |
|
320 | | - const drawMap = (newWorld: World | undefined) => { |
| 364 | + const drawMap = (newWorld: World) => { |
321 | 365 | if (!newWorld) { |
322 | 366 | return; |
323 | 367 | } |
|
380 | 424 | pieceGraphics.addChild(pieceContainer); |
381 | 425 | }; |
382 | 426 |
|
| 427 | + const updateMap = (newWorld: World | undefined) => { |
| 428 | + if (!newWorld) { |
| 429 | + return; |
| 430 | + } |
| 431 | +
|
| 432 | + latestWorld = newWorld; |
| 433 | + if (!assetsLoaded) { |
| 434 | + void ensureAssetsLoaded(); |
| 435 | + return; |
| 436 | + } |
| 437 | +
|
| 438 | + drawMap(newWorld); |
| 439 | + }; |
| 440 | +
|
| 441 | + const ensureAssetsLoaded = async () => { |
| 442 | + if (assetsLoaded) { |
| 443 | + return; |
| 444 | + } |
| 445 | +
|
| 446 | + if (!loadingPromise) { |
| 447 | + loadingPromise = Assets.load(assetsToLoad) |
| 448 | + .then(() => { |
| 449 | + assetsLoaded = true; |
| 450 | + if (latestWorld) { |
| 451 | + drawMap(latestWorld); |
| 452 | + } |
| 453 | + }) |
| 454 | + .catch((error) => { |
| 455 | + console.error('Failed to load assets:', error); |
| 456 | + }); |
| 457 | + } |
| 458 | +
|
| 459 | + await loadingPromise; |
| 460 | + }; |
| 461 | +
|
383 | 462 | const setupCanvas = async () => { |
384 | 463 | if (!container) return; |
385 | 464 |
|
386 | | - height = container.clientHeight / (window.devicePixelRatio || 1); |
387 | | - width = container.clientWidth / (window.devicePixelRatio || 1); |
388 | | -
|
389 | | - // Preload all assets for PixiJS v8 |
390 | | - const tilePath = '/img/tilesets/'; |
391 | | - const tileStyle = 'realistic'; |
392 | | - const assetsToLoad = [ |
393 | | - // Tiles |
394 | | - `${tilePath}${tileStyle}/clay.png`, |
395 | | - `${tilePath}${tileStyle}/desert.png`, |
396 | | - `${tilePath}${tileStyle}/grain.png`, |
397 | | - `${tilePath}${tileStyle}/wood.png`, |
398 | | - `${tilePath}${tileStyle}/stone.png`, |
399 | | - `${tilePath}${tileStyle}/wool.png`, |
400 | | - `${tilePath}${tileStyle}/ocean.png`, |
401 | | - // Pieces |
402 | | - '/img/pieces/house.png', |
403 | | - '/img/pieces/city.png', |
404 | | - '/img/pieces/thief.png', |
405 | | - // Special |
406 | | - `${tilePath}shared/scorch-with-thief.png`, |
407 | | - // Harbors |
408 | | - `${tilePath}${tileStyle}/woodharbor.png`, |
409 | | - `${tilePath}${tileStyle}/woolharbor.png`, |
410 | | - `${tilePath}${tileStyle}/grainharbor.png`, |
411 | | - `${tilePath}${tileStyle}/clayharbor.png`, |
412 | | - `${tilePath}${tileStyle}/stoneharbor.png`, |
413 | | - `${tilePath}${tileStyle}/threetooneharbor.png`, |
414 | | - // Numbers |
415 | | - '/img/numbers/2.png', |
416 | | - '/img/numbers/3.png', |
417 | | - '/img/numbers/4.png', |
418 | | - '/img/numbers/5.png', |
419 | | - '/img/numbers/6.png', |
420 | | - '/img/numbers/8.png', |
421 | | - '/img/numbers/9.png', |
422 | | - '/img/numbers/10.png', |
423 | | - '/img/numbers/11.png', |
424 | | - '/img/numbers/12.png' |
425 | | - ]; |
426 | | -
|
427 | | - // Load all assets |
428 | | - try { |
429 | | - console.log('Loading assets...'); |
430 | | - await Assets.load(assetsToLoad); |
431 | | - console.log('Assets loaded successfully'); |
432 | | - } catch (error) { |
433 | | - console.error('Failed to load assets:', error); |
434 | | - } |
| 465 | + parentElement = container.parentElement; |
| 466 | + const target = parentElement ?? container; |
| 467 | + const ratio = window.devicePixelRatio || 1; |
| 468 | + height = target.clientHeight / ratio; |
| 469 | + width = target.clientWidth / ratio; |
| 470 | + container.style.width = `${target.clientWidth}px`; |
| 471 | + container.style.height = `${target.clientHeight}px`; |
| 472 | +
|
| 473 | + await ensureAssetsLoaded(); |
435 | 474 |
|
436 | 475 | const appInstance = new Application(); |
437 | 476 |
|
|
583 | 622 | }); |
584 | 623 | </script> |
585 | 624 |
|
586 | | -<div bind:this={container} class="h-full w-full bg-[#03518b]"></div> |
| 625 | +<div bind:this={container} class="h-full w-full flex-1 bg-[#03518b]"></div> |
0 commit comments