fix: Add missing dirtyChunks
variable and update rendering logic
This commit is contained in:
parent
60a1757ab1
commit
15fb106246
@ -4,29 +4,37 @@ function updateSand(x, y) {
|
|||||||
if (getPixel(x, y + 1) === EMPTY) {
|
if (getPixel(x, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x, y + 1, SAND);
|
setPixel(x, y + 1, SAND);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Try to move down-left or down-right
|
// Try to move down-left or down-right
|
||||||
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x - 1, y + 1, SAND);
|
setPixel(x - 1, y + 1, SAND);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x + 1, y + 1, SAND);
|
setPixel(x + 1, y + 1, SAND);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Sand can displace water
|
// Sand can displace water
|
||||||
else if (getPixel(x, y + 1) === WATER) {
|
else if (getPixel(x, y + 1) === WATER) {
|
||||||
setPixel(x, y, WATER);
|
setPixel(x, y, WATER);
|
||||||
setPixel(x, y + 1, SAND);
|
setPixel(x, y + 1, SAND);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWater(x, y) {
|
function updateWater(x, y) {
|
||||||
|
let modified = false;
|
||||||
|
|
||||||
// Update water color dynamically
|
// Update water color dynamically
|
||||||
const metadata = getMetadata(x, y);
|
const metadata = getMetadata(x, y);
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
if (metadata.waterColorTimer === undefined) {
|
if (metadata.waterColorTimer === undefined) {
|
||||||
metadata.waterColorTimer = 0;
|
metadata.waterColorTimer = 0;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.waterColorTimer++;
|
metadata.waterColorTimer++;
|
||||||
@ -35,6 +43,7 @@ function updateWater(x, y) {
|
|||||||
if (metadata.waterColorTimer > 20 && Math.random() < 0.1) {
|
if (metadata.waterColorTimer > 20 && Math.random() < 0.1) {
|
||||||
metadata.colorIndex = Math.floor(Math.random() * 10);
|
metadata.colorIndex = Math.floor(Math.random() * 10);
|
||||||
metadata.waterColorTimer = 0;
|
metadata.waterColorTimer = 0;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMetadata(x, y, metadata);
|
setMetadata(x, y, metadata);
|
||||||
@ -45,17 +54,20 @@ function updateWater(x, y) {
|
|||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x, y + 1, WATER);
|
setPixel(x, y + 1, WATER);
|
||||||
moveMetadata(x, y, x, y + 1);
|
moveMetadata(x, y, x, y + 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Try to move down-left or down-right
|
// Try to move down-left or down-right
|
||||||
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x - 1, y + 1, WATER);
|
setPixel(x - 1, y + 1, WATER);
|
||||||
moveMetadata(x, y, x - 1, y + 1);
|
moveMetadata(x, y, x - 1, y + 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x + 1, y + 1, WATER);
|
setPixel(x + 1, y + 1, WATER);
|
||||||
moveMetadata(x, y, x + 1, y + 1);
|
moveMetadata(x, y, x + 1, y + 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Try to spread horizontally
|
// Try to spread horizontally
|
||||||
else {
|
else {
|
||||||
@ -67,21 +79,25 @@ function updateWater(x, y) {
|
|||||||
if (goLeft && getPixel(x - 1, y) === EMPTY) {
|
if (goLeft && getPixel(x - 1, y) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x - 1, y, WATER);
|
setPixel(x - 1, y, WATER);
|
||||||
moved = true;
|
moveMetadata(x, y, x - 1, y);
|
||||||
|
return true;
|
||||||
} else if (!goLeft && getPixel(x + 1, y) === EMPTY) {
|
} else if (!goLeft && getPixel(x + 1, y) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x + 1, y, WATER);
|
setPixel(x + 1, y, WATER);
|
||||||
moved = true;
|
moveMetadata(x, y, x + 1, y);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Try the other direction if first failed
|
// Try the other direction if first failed
|
||||||
else if (!goLeft && getPixel(x - 1, y) === EMPTY) {
|
else if (!goLeft && getPixel(x - 1, y) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x - 1, y, WATER);
|
setPixel(x - 1, y, WATER);
|
||||||
moved = true;
|
moveMetadata(x, y, x - 1, y);
|
||||||
|
return true;
|
||||||
} else if (goLeft && getPixel(x + 1, y) === EMPTY) {
|
} else if (goLeft && getPixel(x + 1, y) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x + 1, y, WATER);
|
setPixel(x + 1, y, WATER);
|
||||||
moved = true;
|
moveMetadata(x, y, x + 1, y);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,15 +113,18 @@ function updateWater(x, y) {
|
|||||||
if (getPixel(x + dir.dx, y + dir.dy) === FIRE) {
|
if (getPixel(x + dir.dx, y + dir.dy) === FIRE) {
|
||||||
setPixel(x + dir.dx, y + dir.dy, EMPTY);
|
setPixel(x + dir.dx, y + dir.dy, EMPTY);
|
||||||
removeMetadata(x + dir.dx, y + dir.dy);
|
removeMetadata(x + dir.dx, y + dir.dy);
|
||||||
|
return true;
|
||||||
} else if (getPixel(x + dir.dx, y + dir.dy) === LAVA) {
|
} else if (getPixel(x + dir.dx, y + dir.dy) === LAVA) {
|
||||||
// Water turns lava into stone
|
// Water turns lava into stone
|
||||||
setPixel(x + dir.dx, y + dir.dy, STONE);
|
setPixel(x + dir.dx, y + dir.dy, STONE);
|
||||||
removeMetadata(x + dir.dx, y + dir.dy);
|
removeMetadata(x + dir.dx, y + dir.dy);
|
||||||
// Water is consumed in the process
|
// Water is consumed in the process
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDirt(x, y) {
|
function updateDirt(x, y) {
|
||||||
@ -113,25 +132,30 @@ function updateDirt(x, y) {
|
|||||||
if (getPixel(x, y + 1) === EMPTY) {
|
if (getPixel(x, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x, y + 1, DIRT);
|
setPixel(x, y + 1, DIRT);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Try to move down-left or down-right
|
// Try to move down-left or down-right
|
||||||
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
else if (getPixel(x - 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x - 1, y + 1, DIRT);
|
setPixel(x - 1, y + 1, DIRT);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
||||||
setPixel(x, y, EMPTY);
|
setPixel(x, y, EMPTY);
|
||||||
setPixel(x + 1, y + 1, DIRT);
|
setPixel(x + 1, y + 1, DIRT);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Dirt can displace water
|
// Dirt can displace water
|
||||||
else if (getPixel(x, y + 1) === WATER) {
|
else if (getPixel(x, y + 1) === WATER) {
|
||||||
setPixel(x, y, WATER);
|
setPixel(x, y, WATER);
|
||||||
setPixel(x, y + 1, DIRT);
|
setPixel(x, y + 1, DIRT);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dirt can turn into grass if exposed to air above
|
// Dirt can turn into grass if exposed to air above
|
||||||
if (getPixel(x, y - 1) === EMPTY && Math.random() < 0.001) {
|
if (getPixel(x, y - 1) === EMPTY && Math.random() < 0.001) {
|
||||||
setPixel(x, y, GRASS);
|
setPixel(x, y, GRASS);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dirt can randomly spawn seeds if exposed to air above
|
// Dirt can randomly spawn seeds if exposed to air above
|
||||||
@ -140,12 +164,17 @@ function updateDirt(x, y) {
|
|||||||
const seedRoll = Math.random();
|
const seedRoll = Math.random();
|
||||||
if (seedRoll < 0.0002) { // Grass blade seed (most common)
|
if (seedRoll < 0.0002) { // Grass blade seed (most common)
|
||||||
setPixel(x, y - 1, SEED);
|
setPixel(x, y - 1, SEED);
|
||||||
|
return true;
|
||||||
} else if (seedRoll < 0.00025) { // Flower seed (less common)
|
} else if (seedRoll < 0.00025) { // Flower seed (less common)
|
||||||
setPixel(x, y - 1, SEED);
|
setPixel(x, y - 1, SEED);
|
||||||
// Mark this seed as a flower seed (will be handled in updateSeed)
|
// Mark this seed as a flower seed (will be handled in updateSeed)
|
||||||
setMetadata(x, y - 1, { type: 'flower' });
|
setMetadata(x, y - 1, { type: 'flower' });
|
||||||
|
return true;
|
||||||
} else if (seedRoll < 0.00026) { // Tree seed (rare)
|
} else if (seedRoll < 0.00026) { // Tree seed (rare)
|
||||||
setPixel(x, y - 1, TREE_SEED);
|
setPixel(x, y - 1, TREE_SEED);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ function simulationLoop(timestamp) {
|
|||||||
fps = Math.round(1000 / deltaTime);
|
fps = Math.round(1000 / deltaTime);
|
||||||
document.getElementById('fps').textContent = `FPS: ${fps}`;
|
document.getElementById('fps').textContent = `FPS: ${fps}`;
|
||||||
|
|
||||||
// Update physics
|
// Update physics with timestamp for rate limiting
|
||||||
updatePhysics();
|
updatePhysics(timestamp);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
render();
|
render();
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
// Physics simulation functions
|
// Physics simulation functions
|
||||||
function updatePhysics() {
|
function updatePhysics(timestamp) {
|
||||||
|
// Check if we should update physics based on the update rate
|
||||||
|
if (timestamp && lastPhysicsTime && timestamp - lastPhysicsTime < physicsUpdateRate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPhysicsTime = timestamp || 0;
|
||||||
|
|
||||||
// Get visible chunks
|
// Get visible chunks
|
||||||
const visibleChunks = getVisibleChunks();
|
const visibleChunks = getVisibleChunks();
|
||||||
|
|
||||||
@ -12,6 +19,7 @@ function updatePhysics() {
|
|||||||
if (!isVisible) continue;
|
if (!isVisible) continue;
|
||||||
|
|
||||||
const chunk = getOrCreateChunk(chunkX, chunkY);
|
const chunk = getOrCreateChunk(chunkX, chunkY);
|
||||||
|
let chunkModified = false;
|
||||||
|
|
||||||
// Process from bottom to top, right to left for correct gravity simulation
|
// Process from bottom to top, right to left for correct gravity simulation
|
||||||
for (let y = CHUNK_SIZE - 1; y >= 0; y--) {
|
for (let y = CHUNK_SIZE - 1; y >= 0; y--) {
|
||||||
@ -29,28 +37,42 @@ function updatePhysics() {
|
|||||||
const worldX = chunkX * CHUNK_SIZE + x;
|
const worldX = chunkX * CHUNK_SIZE + x;
|
||||||
const worldY = chunkY * CHUNK_SIZE + y;
|
const worldY = chunkY * CHUNK_SIZE + y;
|
||||||
|
|
||||||
if (type === SAND) {
|
// Use a lookup table for faster element updates
|
||||||
updateSand(worldX, worldY);
|
const updateFunctions = {
|
||||||
} else if (type === WATER) {
|
[SAND]: updateSand,
|
||||||
updateWater(worldX, worldY);
|
[WATER]: updateWater,
|
||||||
} else if (type === DIRT) {
|
[DIRT]: updateDirt,
|
||||||
updateDirt(worldX, worldY);
|
[GRASS]: updateGrass,
|
||||||
} else if (type === GRASS) {
|
[SEED]: updateSeed,
|
||||||
updateGrass(worldX, worldY);
|
[GRASS_BLADE]: updateGrassBlade,
|
||||||
} else if (type === SEED) {
|
[FLOWER]: updateFlower,
|
||||||
updateSeed(worldX, worldY);
|
[TREE_SEED]: updateTreeSeed,
|
||||||
} else if (type === GRASS_BLADE) {
|
[FIRE]: updateFire,
|
||||||
updateGrassBlade(worldX, worldY);
|
[LAVA]: updateLava
|
||||||
} else if (type === FLOWER) {
|
};
|
||||||
updateFlower(worldX, worldY);
|
|
||||||
} else if (type === TREE_SEED) {
|
const updateFunction = updateFunctions[type];
|
||||||
updateTreeSeed(worldX, worldY);
|
if (updateFunction) {
|
||||||
} else if (type === FIRE) {
|
const wasModified = updateFunction(worldX, worldY);
|
||||||
updateFire(worldX, worldY);
|
if (wasModified) {
|
||||||
} else if (type === LAVA) {
|
chunkModified = true;
|
||||||
updateLava(worldX, worldY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark chunk as dirty if it was modified
|
||||||
|
if (chunkModified) {
|
||||||
|
dirtyChunks.add(getChunkKey(chunkX, chunkY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adaptive physics rate based on FPS
|
||||||
|
if (fps < 30 && physicsUpdateRate < 32) {
|
||||||
|
// If FPS is low, update physics less frequently
|
||||||
|
physicsUpdateRate = Math.min(32, physicsUpdateRate + 2);
|
||||||
|
} else if (fps > 50 && physicsUpdateRate > 16) {
|
||||||
|
// If FPS is high, update physics more frequently
|
||||||
|
physicsUpdateRate = Math.max(16, physicsUpdateRate - 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
20
js/world.js
20
js/world.js
@ -6,12 +6,19 @@ let worldOffsetYBeforeDrag = 0;
|
|||||||
let chunks = new Map(); // Map to store chunks with key "x,y"
|
let chunks = new Map(); // Map to store chunks with key "x,y"
|
||||||
let metadata = new Map(); // Map to store metadata for pixels
|
let metadata = new Map(); // Map to store metadata for pixels
|
||||||
let generatedChunks = new Set(); // Set to track which chunks have been generated
|
let generatedChunks = new Set(); // Set to track which chunks have been generated
|
||||||
|
let dirtyChunks = new Set(); // Set to track which chunks need rendering
|
||||||
|
let lastPhysicsTime = 0; // Last time physics was updated
|
||||||
|
let physicsUpdateRate = 16; // Update physics every 16ms (approx 60fps)
|
||||||
|
let worldMoved = false; // Track if the world has moved for rendering
|
||||||
|
|
||||||
function moveWorld(dx, dy) {
|
function moveWorld(dx, dy) {
|
||||||
worldOffsetX += dx;
|
worldOffsetX += dx;
|
||||||
worldOffsetY += dy;
|
worldOffsetY += dy;
|
||||||
updateCoordinatesDisplay();
|
updateCoordinatesDisplay();
|
||||||
|
|
||||||
|
// Mark that the world has moved for rendering
|
||||||
|
worldMoved = true;
|
||||||
|
|
||||||
// Generate terrain for chunks around the current view
|
// Generate terrain for chunks around the current view
|
||||||
generateChunksAroundPlayer();
|
generateChunksAroundPlayer();
|
||||||
}
|
}
|
||||||
@ -383,8 +390,13 @@ function setPixel(worldX, worldY, type) {
|
|||||||
const chunk = getOrCreateChunk(chunkX, chunkY);
|
const chunk = getOrCreateChunk(chunkX, chunkY);
|
||||||
const index = localY * CHUNK_SIZE + localX;
|
const index = localY * CHUNK_SIZE + localX;
|
||||||
|
|
||||||
|
// Only update if the pixel type is changing
|
||||||
|
if (chunk[index] !== type) {
|
||||||
chunk[index] = type;
|
chunk[index] = type;
|
||||||
|
|
||||||
|
// Mark chunk as dirty for rendering
|
||||||
|
dirtyChunks.add(getChunkKey(chunkX, chunkY));
|
||||||
|
|
||||||
// Assign random color index for natural elements
|
// Assign random color index for natural elements
|
||||||
if (type === DIRT || type === GRASS || type === STONE || type === WOOD || type === LEAF) {
|
if (type === DIRT || type === GRASS || type === STONE || type === WOOD || type === LEAF) {
|
||||||
const colorIndex = Math.floor(Math.random() * 10);
|
const colorIndex = Math.floor(Math.random() * 10);
|
||||||
@ -411,6 +423,7 @@ function setPixel(worldX, worldY, type) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getPixel(worldX, worldY) {
|
function getPixel(worldX, worldY) {
|
||||||
const { chunkX, chunkY, localX, localY } = getChunkCoordinates(worldX, worldY);
|
const { chunkX, chunkY, localX, localY } = getChunkCoordinates(worldX, worldY);
|
||||||
@ -448,6 +461,13 @@ function moveMetadata(fromX, fromY, toX, toY) {
|
|||||||
if (data) {
|
if (data) {
|
||||||
setMetadata(toX, toY, data);
|
setMetadata(toX, toY, data);
|
||||||
removeMetadata(fromX, fromY);
|
removeMetadata(fromX, fromY);
|
||||||
|
|
||||||
|
// Mark chunks as dirty for rendering
|
||||||
|
const { chunkX: fromChunkX, chunkY: fromChunkY } = getChunkCoordinates(fromX, fromY);
|
||||||
|
const { chunkX: toChunkX, chunkY: toChunkY } = getChunkCoordinates(toX, toY);
|
||||||
|
|
||||||
|
dirtyChunks.add(getChunkKey(fromChunkX, fromChunkY));
|
||||||
|
dirtyChunks.add(getChunkKey(toChunkX, toChunkY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user