sounds
This commit is contained in:
parent
c6ba3e38a2
commit
37087d08a7
189 changed files with 12864 additions and 9589 deletions
184
js/world_spatial_budget.js
Normal file
184
js/world_spatial_budget.js
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
"use strict";
|
||||
|
||||
(function (global) {
|
||||
const World = global.World;
|
||||
if (!World) throw new Error("World is not available for mixin: world_spatial_budget.js");
|
||||
Object.defineProperties(World.prototype, Object.getOwnPropertyDescriptors({
|
||||
performanceLevel() {
|
||||
if (window.TarinaiPerformance) return window.TarinaiPerformance.level || 0;
|
||||
const fps = typeof window !== "undefined" ? Number(window.__tarinaiFps || 0) : 60;
|
||||
if (!fps || !Number.isFinite(fps)) return 0;
|
||||
if (fps < 22) return 3;
|
||||
if (fps < 34) return 2;
|
||||
if (fps < 48) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
performanceQuality() {
|
||||
return window.TarinaiPerformance?.quality?.(this) || { level: this.performanceLevel(), antStride: 1, effectLimit: CONFIG.effectLimit ?? 96 };
|
||||
},
|
||||
|
||||
grassLoadLevel() {
|
||||
const grass = this.itemCounts?.grass || 0;
|
||||
const perf = this.performanceLevel();
|
||||
if (perf >= 3 || grass >= 180) return 3;
|
||||
if (perf >= 2 || grass >= 120) return 2;
|
||||
if (perf >= 1 || grass >= 72) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
grassUpdateFactor() {
|
||||
return [1.0, 1.35, 1.85, 2.45][this.grassLoadLevel()] || 1.0;
|
||||
},
|
||||
|
||||
sortedDrawList() {
|
||||
if (!this.drawList) this.drawList = [];
|
||||
const antCount = (this.ants || []).filter(a => a && !a.dead).length;
|
||||
const tarinaiCount = (this.tarinai || []).filter(t => t && !t.dead).length;
|
||||
if (this.drawListDirty || this.drawList.length !== tarinaiCount + antCount) {
|
||||
this.drawList.length = 0;
|
||||
for (const t of this.tarinai || []) if (t && !t.dead) this.drawList.push(t);
|
||||
for (const a of this.ants || []) if (a && !a.dead) this.drawList.push(a);
|
||||
this.drawList.sort((a, b) => (a.y || 0) - (b.y || 0));
|
||||
this.drawListDirty = false;
|
||||
}
|
||||
return this.drawList;
|
||||
},
|
||||
|
||||
nearbyItems(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.itemCells, x, y, radius, this.spatialItemScratch, precise);
|
||||
},
|
||||
|
||||
nearbyTarinai(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.tarinaiCells, x, y, radius, this.spatialTarinaiScratch, precise);
|
||||
},
|
||||
|
||||
nearbyAnts(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.antCells, x, y, radius, this.spatialAntScratch, precise);
|
||||
},
|
||||
|
||||
nearbyObstacles(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.obstacleCells, x, y, radius, this.spatialObstacleScratch, precise);
|
||||
},
|
||||
|
||||
nearbyFood(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.foodCells, x, y, radius, this.spatialFoodScratch, precise);
|
||||
},
|
||||
|
||||
nearbyHazards(x, y, radius, precise = false) {
|
||||
return this.spatial.nearby(this.spatial.hazardCells, x, y, radius, this.spatialHazardScratch, precise);
|
||||
},
|
||||
|
||||
rebuildSpatial(force = false) {
|
||||
this.spatial.rebuild(this.items, this.tarinai, this.ants || []);
|
||||
this.spatialDirty = false;
|
||||
this.spatialVersion = (this.spatialVersion || 0) + 1;
|
||||
},
|
||||
|
||||
updateItemCounts() {
|
||||
const counts = this.itemCounts;
|
||||
for (const key of Object.keys(counts)) counts[key] = 0;
|
||||
for (const it of this.items) counts[it.type] = (counts[it.type] || 0) + 1;
|
||||
},
|
||||
|
||||
updateEffectCounts() {
|
||||
const counts = this.effectCounts;
|
||||
for (const key of Object.keys(counts)) counts[key] = 0;
|
||||
for (const ef of this.effects) counts[ef.type] = (counts[ef.type] || 0) + 1;
|
||||
},
|
||||
|
||||
compactItems() {
|
||||
this.enforceItemBudget();
|
||||
const before = this.items.length;
|
||||
let write = 0;
|
||||
for (let read = 0; read < this.items.length; read++) {
|
||||
const it = this.items[read];
|
||||
if (it.type === "mirror") continue;
|
||||
if (!it.dead) this.items[write++] = it;
|
||||
}
|
||||
this.items.length = write;
|
||||
const changed = before !== this.items.length;
|
||||
if (changed) {
|
||||
this.markSpatialDirty?.("compact-items");
|
||||
this.markTerrainDirty?.("compact-items");
|
||||
}
|
||||
return changed;
|
||||
},
|
||||
|
||||
enforceItemBudget() {
|
||||
const pruneOldest = (type, limit) => {
|
||||
if (!Number.isFinite(limit) || limit < 0) return;
|
||||
let count = 0;
|
||||
for (const it of this.items) if (it.type === type && !it.dead) count += 1;
|
||||
if (count <= limit) return;
|
||||
const victims = this.items
|
||||
.filter(it => it.type === type && !it.dead)
|
||||
.sort((a, b) => (b.age || 0) - (a.age || 0))
|
||||
.slice(0, count - limit);
|
||||
for (const it of victims) it.amount = 0;
|
||||
};
|
||||
pruneOldest("zunchi", CONFIG.zunchiLimit ?? 56);
|
||||
pruneOldest("trace", CONFIG.traceLimit ?? 64);
|
||||
pruneOldest("splat", CONFIG.splatLimit ?? 48);
|
||||
pruneOldest("grass", this.grassLimit ? this.grassLimit() : (CONFIG.grassLimit ?? 96));
|
||||
const fenceLimit = this.fenceLimit ? this.fenceLimit() : (CONFIG.fenceLimit ?? 72);
|
||||
const liveFences = this.liveFenceCount ? this.liveFenceCount() : 0;
|
||||
if (liveFences > fenceLimit) {
|
||||
const victims = this.items
|
||||
.filter(it => this.isFenceType?.(it.type) && !it.dead)
|
||||
.sort((a, b) => (b.age || 0) - (a.age || 0))
|
||||
.slice(0, liveFences - fenceLimit);
|
||||
for (const it of victims) it.amount = 0;
|
||||
}
|
||||
|
||||
const limit = CONFIG.itemLimit ?? Infinity;
|
||||
if (!Number.isFinite(limit) || this.items.length <= limit) return;
|
||||
const priority = { trace: 1, splat: 2, zunchi: 3, water: 4, grass: 5, sweet: 6, firecracker: 7, fence_v: 8, fence_h: 8 };
|
||||
const removable = this.items
|
||||
.filter(it => !it.dead && (priority[it.type] || 99) < 99)
|
||||
.sort((a, b) => (priority[a.type] || 99) - (priority[b.type] || 99) || (b.age || 0) - (a.age || 0));
|
||||
let extra = this.items.length - limit;
|
||||
for (const it of removable) {
|
||||
if (extra <= 0) break;
|
||||
it.amount = 0;
|
||||
extra -= 1;
|
||||
}
|
||||
},
|
||||
|
||||
compactEffects() {
|
||||
const limit = this.performanceQuality?.().effectLimit ?? CONFIG.effectLimit ?? 96;
|
||||
if (Number.isFinite(limit) && this.effects.length > limit) {
|
||||
this.effects.sort((a, b) => (a.life / Math.max(a.maxLife || 1, 0.001)) - (b.life / Math.max(b.maxLife || 1, 0.001)));
|
||||
const remove = this.effects.length - limit;
|
||||
for (let i = 0; i < remove; i++) this.effects[i].life = 0;
|
||||
}
|
||||
let write = 0;
|
||||
for (let read = 0; read < this.effects.length; read++) {
|
||||
const ef = this.effects[read];
|
||||
if (!ef.dead) this.effects[write++] = ef;
|
||||
}
|
||||
this.effects.length = write;
|
||||
},
|
||||
|
||||
compactTarinai() {
|
||||
let write = 0;
|
||||
for (let read = 0; read < this.tarinai.length; read++) {
|
||||
const t = this.tarinai[read];
|
||||
if (!t.dead) this.tarinai[write++] = t;
|
||||
}
|
||||
if (this.tarinai.length !== write) this.drawListDirty = true;
|
||||
this.tarinai.length = write;
|
||||
},
|
||||
|
||||
compactAnts() {
|
||||
if (!this.ants) this.ants = [];
|
||||
let write = 0;
|
||||
for (let read = 0; read < this.ants.length; read++) {
|
||||
const a = this.ants[read];
|
||||
if (a && !a.dead) this.ants[write++] = a;
|
||||
}
|
||||
if (this.ants.length !== write) this.drawListDirty = true;
|
||||
this.ants.length = write;
|
||||
}
|
||||
}));
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
Loading…
Add table
Add a link
Reference in a new issue