render optimize

master
Denis Ranneft 1 month ago
parent d9d8e72933
commit 0d6a82e0e1

File diff suppressed because it is too large Load Diff

@ -37,6 +37,8 @@ export interface WorldPoint {
type SpritePoolEntry = {
sprite: Sprite;
textureKey: string;
worldX?: number;
worldY?: number;
};
const TERRAIN_SEAM_BLEED_SCALE = 1.002;
@ -101,6 +103,10 @@ export class GameRenderer {
private _objectSpritePool = new Map<string, SpritePoolEntry>();
private _tileSpriteFreeList: Sprite[] = [];
private _objectSpriteFreeList: Sprite[] = [];
private _usedTileSprites = new Set<string>();
private _usedObjectSprites = new Set<string>();
private _emptySpriteSet = new Set<string>();
private _groundTerrainCache = new Map<string, string>();
private _buildingSpritePool = new Map<string, SpritePoolEntry>();
private _characterSpritePool = new Map<string, SpritePoolEntry>();
private _npcSpritePool = new Map<string, SpritePoolEntry>();
@ -321,6 +327,8 @@ export class GameRenderer {
textureKey: string,
texture: SpritePoolEntry['sprite']['texture'],
layer: Container,
worldX?: number,
worldY?: number,
freeList?: Sprite[],
): SpritePoolEntry {
let entry = pool.get(poolKey);
@ -332,7 +340,7 @@ export class GameRenderer {
sprite.anchor.set(0.5, 1);
sprite.roundPixels = true;
if (!sprite.parent) layer.addChild(sprite);
entry = { sprite, textureKey };
entry = { sprite, textureKey, worldX, worldY };
pool.set(poolKey, entry);
return entry;
}
@ -340,6 +348,10 @@ export class GameRenderer {
entry.sprite.texture = texture;
entry.textureKey = textureKey;
}
if (typeof worldX === 'number' && typeof worldY === 'number') {
entry.worldX = worldX;
entry.worldY = worldY;
}
return entry;
}
@ -359,10 +371,8 @@ export class GameRenderer {
maxFreeListSize: number,
): void {
for (const [key, entry] of pool) {
const sep = key.indexOf(',');
if (sep < 0) continue;
const wx = Number(key.slice(0, sep));
const wy = Number(key.slice(sep + 1));
const wx = entry.worldX ?? Number.NaN;
const wy = entry.worldY ?? Number.NaN;
if (!Number.isFinite(wx) || !Number.isFinite(wy)) continue;
if (wx >= minX && wx <= maxX && wy >= minY && wy <= maxY) continue;
pool.delete(key);
@ -627,8 +637,20 @@ export class GameRenderer {
const hw = TILE_WIDTH / 2;
const hh = TILE_HEIGHT / 2;
const terrainCtx = this._worldTerrainContext;
const usedTileSprites = new Set<string>();
const usedObjectSprites = new Set<string>();
const usedTileSprites = this._usedTileSprites;
const usedObjectSprites = this._usedObjectSprites;
usedTileSprites.clear();
usedObjectSprites.clear();
const terrainCache = this._groundTerrainCache;
terrainCache.clear();
const terrainAt = (wx: number, wy: number): string => {
const key = `${wx},${wy}`;
const cached = terrainCache.get(key);
if (cached) return cached;
const terrain = proceduralTerrain(wx, wy, terrainCtx);
terrainCache.set(key, terrain);
return terrain;
};
// Pass 1: tiles
for (let wx = startX; wx <= endX; wx++) {
@ -640,7 +662,7 @@ export class GameRenderer {
) {
continue;
}
const terrain = proceduralTerrain(wx, wy, terrainCtx);
const terrain = terrainAt(wx, wy);
const dark = (wx + wy) % 2 === 0;
const textureKey = spritesReady ? terrainToTextureKey(terrain) : null;
const texture = textureKey ? this._spriteRegistry.getTexture(textureKey) : null;
@ -654,6 +676,8 @@ export class GameRenderer {
textureKey,
texture,
this._groundSpriteLayer,
wx,
wy,
this._tileSpriteFreeList,
);
entry.sprite.x = iso.x;
@ -705,7 +729,7 @@ export class GameRenderer {
) {
continue;
}
const terrainHere = proceduralTerrain(wx, wy, terrainCtx);
const terrainHere = terrainAt(wx, wy);
const obj = proceduralObject(wx, wy, terrainHere, terrainCtx);
if (!obj) continue;
const variant = tileHash(wx, wy, 999);
@ -720,6 +744,8 @@ export class GameRenderer {
objTextureKey,
objTexture,
this._objectSpriteLayer,
wx,
wy,
this._objectSpriteFreeList,
);
entry.sprite.x = iso.x;
@ -767,8 +793,8 @@ export class GameRenderer {
1800,
);
} else {
this._hideUnusedSprites(this._tileSpritePool, new Set());
this._hideUnusedSprites(this._objectSpritePool, new Set());
this._hideUnusedSprites(this._tileSpritePool, this._emptySpriteSet);
this._hideUnusedSprites(this._objectSpritePool, this._emptySpriteSet);
}
}
@ -1926,7 +1952,7 @@ export class GameRenderer {
for (const lbl of this._npcLabels) {
lbl.visible = false;
}
this._hideUnusedSprites(this._npcSpritePool, new Set());
this._hideUnusedSprites(this._npcSpritePool, this._emptySpriteSet);
}
/**

Loading…
Cancel
Save