perf: Optimize chunk rendering and generation by skipping off-screen chunks
This commit is contained in:
parent
c7735b8578
commit
4c96226d05
62
js/world.js
62
js/world.js
@ -454,15 +454,35 @@ function moveMetadata(fromX, fromY, toX, toY) {
|
|||||||
function getVisibleChunks() {
|
function getVisibleChunks() {
|
||||||
const visibleChunks = [];
|
const visibleChunks = [];
|
||||||
|
|
||||||
// Calculate visible chunk range
|
// Calculate visible chunk range (chunks that might be visible on screen)
|
||||||
const startChunkX = Math.floor(worldOffsetX / CHUNK_SIZE) - 1;
|
const startChunkX = Math.floor(worldOffsetX / CHUNK_SIZE) - 1;
|
||||||
const endChunkX = Math.ceil((worldOffsetX + canvas.width / PIXEL_SIZE) / CHUNK_SIZE) + 1;
|
const endChunkX = Math.ceil((worldOffsetX + canvas.width / PIXEL_SIZE) / CHUNK_SIZE) + 1;
|
||||||
const startChunkY = Math.floor(worldOffsetY / CHUNK_SIZE) - 1;
|
const startChunkY = Math.floor(worldOffsetY / CHUNK_SIZE) - 1;
|
||||||
const endChunkY = Math.ceil((worldOffsetY + canvas.height / PIXEL_SIZE) / CHUNK_SIZE) + 1;
|
const endChunkY = Math.ceil((worldOffsetY + canvas.height / PIXEL_SIZE) / CHUNK_SIZE) + 1;
|
||||||
|
|
||||||
|
// Calculate the exact visible area in world coordinates
|
||||||
|
const visibleStartX = worldOffsetX;
|
||||||
|
const visibleEndX = worldOffsetX + canvas.width / PIXEL_SIZE;
|
||||||
|
const visibleStartY = worldOffsetY;
|
||||||
|
const visibleEndY = worldOffsetY + canvas.height / PIXEL_SIZE;
|
||||||
|
|
||||||
for (let chunkY = startChunkY; chunkY < endChunkY; chunkY++) {
|
for (let chunkY = startChunkY; chunkY < endChunkY; chunkY++) {
|
||||||
for (let chunkX = startChunkX; chunkX < endChunkX; chunkX++) {
|
for (let chunkX = startChunkX; chunkX < endChunkX; chunkX++) {
|
||||||
visibleChunks.push({ chunkX, chunkY });
|
// Calculate chunk boundaries in world coordinates
|
||||||
|
const chunkWorldStartX = chunkX * CHUNK_SIZE;
|
||||||
|
const chunkWorldEndX = (chunkX + 1) * CHUNK_SIZE;
|
||||||
|
const chunkWorldStartY = chunkY * CHUNK_SIZE;
|
||||||
|
const chunkWorldEndY = (chunkY + 1) * CHUNK_SIZE;
|
||||||
|
|
||||||
|
// Check if this chunk is actually visible in the viewport
|
||||||
|
const isVisible = !(
|
||||||
|
chunkWorldEndX < visibleStartX ||
|
||||||
|
chunkWorldStartX > visibleEndX ||
|
||||||
|
chunkWorldEndY < visibleStartY ||
|
||||||
|
chunkWorldStartY > visibleEndY
|
||||||
|
);
|
||||||
|
|
||||||
|
visibleChunks.push({ chunkX, chunkY, isVisible });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,19 +494,53 @@ function generateChunksAroundPlayer() {
|
|||||||
const centerChunkY = Math.floor(worldOffsetY / CHUNK_SIZE);
|
const centerChunkY = Math.floor(worldOffsetY / CHUNK_SIZE);
|
||||||
const radius = 3; // Generate chunks within 3 chunks of the player
|
const radius = 3; // Generate chunks within 3 chunks of the player
|
||||||
|
|
||||||
// Always generate the stone layer at y = 1
|
// Get visible chunks to prioritize their generation
|
||||||
|
const visibleChunks = getVisibleChunks();
|
||||||
|
const visibleChunkKeys = new Set(visibleChunks.map(chunk => getChunkKey(chunk.chunkX, chunk.chunkY)));
|
||||||
|
|
||||||
|
// Always generate the stone layer at y = 1 for visible chunks first
|
||||||
for (let dx = -radius; dx <= radius; dx++) {
|
for (let dx = -radius; dx <= radius; dx++) {
|
||||||
const chunkX = centerChunkX + dx;
|
const chunkX = centerChunkX + dx;
|
||||||
const chunkY = 1; // The chunk at y = 1 (moved from y = -1)
|
const chunkY = 1; // The chunk at y = 1 (moved from y = -1)
|
||||||
|
const key = getChunkKey(chunkX, chunkY);
|
||||||
|
|
||||||
|
// Prioritize visible chunks
|
||||||
|
if (visibleChunkKeys.has(key)) {
|
||||||
getOrCreateChunk(chunkX, chunkY);
|
getOrCreateChunk(chunkX, chunkY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate chunks in a square around the player
|
// Generate visible chunks first
|
||||||
|
for (const { chunkX, chunkY, isVisible } of visibleChunks) {
|
||||||
|
if (isVisible) {
|
||||||
|
getOrCreateChunk(chunkX, chunkY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then generate non-visible chunks within the radius (with lower priority)
|
||||||
|
// Always generate the stone layer at y = 1 for remaining chunks
|
||||||
|
for (let dx = -radius; dx <= radius; dx++) {
|
||||||
|
const chunkX = centerChunkX + dx;
|
||||||
|
const chunkY = 1;
|
||||||
|
const key = getChunkKey(chunkX, chunkY);
|
||||||
|
|
||||||
|
// Skip if already generated
|
||||||
|
if (!visibleChunkKeys.has(key)) {
|
||||||
|
getOrCreateChunk(chunkX, chunkY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate remaining chunks in a square around the player
|
||||||
for (let dy = -radius; dy <= radius; dy++) {
|
for (let dy = -radius; dy <= radius; dy++) {
|
||||||
for (let dx = -radius; dx <= radius; dx++) {
|
for (let dx = -radius; dx <= radius; dx++) {
|
||||||
const chunkX = centerChunkX + dx;
|
const chunkX = centerChunkX + dx;
|
||||||
const chunkY = centerChunkY + dy;
|
const chunkY = centerChunkY + dy;
|
||||||
|
const key = getChunkKey(chunkX, chunkY);
|
||||||
|
|
||||||
|
// Skip if already generated
|
||||||
|
if (!visibleChunkKeys.has(key)) {
|
||||||
getOrCreateChunk(chunkX, chunkY);
|
getOrCreateChunk(chunkX, chunkY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user