sandsim/js/world.js

139 lines
4.6 KiB
JavaScript

// World management functions
let worldOffsetX = 0;
let worldOffsetY = 0;
let worldOffsetXBeforeDrag = 0;
let worldOffsetYBeforeDrag = 0;
let chunks = new Map(); // Map to store chunks with key "x,y"
let metadata = new Map(); // Map to store metadata for pixels
let generatedChunks = new Set(); // Set to track which chunks have been generated
function moveWorld(dx, dy) {
worldOffsetX += dx;
worldOffsetY += dy;
updateCoordinatesDisplay();
// Generate terrain for chunks around the current view
generateChunksAroundPlayer();
}
function updateCoordinatesDisplay() {
const chunkX = Math.floor(worldOffsetX / CHUNK_SIZE);
const chunkY = Math.floor(worldOffsetY / CHUNK_SIZE);
document.getElementById('coords').textContent = `Chunk: ${chunkX},${chunkY} | Offset: ${Math.floor(worldOffsetX)},${Math.floor(worldOffsetY)}`;
}
function getChunkKey(chunkX, chunkY) {
return `${chunkX},${chunkY}`;
}
function getOrCreateChunk(chunkX, chunkY) {
const key = getChunkKey(chunkX, chunkY);
if (!chunks.has(key)) {
// Create a new chunk with empty pixels
const chunkData = new Array(CHUNK_SIZE * CHUNK_SIZE).fill(EMPTY);
// Add floor at the bottom of the world (y = 0 and y = 1)
if (chunkY === 0 || chunkY === 1) {
// Fill the bottom row with walls
for (let x = 0; x < CHUNK_SIZE; x++) {
chunkData[(CHUNK_SIZE - 1) * CHUNK_SIZE + x] = WALL;
}
}
chunks.set(key, chunkData);
}
return chunks.get(key);
}
function getChunkCoordinates(worldX, worldY) {
const chunkX = Math.floor(worldX / CHUNK_SIZE);
const chunkY = Math.floor(worldY / CHUNK_SIZE);
const localX = ((worldX % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE;
const localY = ((worldY % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE;
return { chunkX, chunkY, localX, localY };
}
function setPixel(worldX, worldY, type) {
const { chunkX, chunkY, localX, localY } = getChunkCoordinates(worldX, worldY);
const chunk = getOrCreateChunk(chunkX, chunkY);
const index = localY * CHUNK_SIZE + localX;
chunk[index] = type;
// Assign random color index for natural elements
if (type === DIRT || type === GRASS || type === STONE || type === WOOD || type === LEAF) {
const colorIndex = Math.floor(Math.random() * 10);
setMetadata(worldX, worldY, { ...getMetadata(worldX, worldY) || {}, colorIndex });
}
else if (type === WATER) {
const colorIndex = Math.floor(Math.random() * 10);
setMetadata(worldX, worldY, { ...getMetadata(worldX, worldY) || {}, colorIndex, waterColorTimer: 0 });
}
}
function getPixel(worldX, worldY) {
// Special case: floor at the bottom of the world (first two chunks)
const floorChunkY = Math.floor(worldY / CHUNK_SIZE);
if (worldY % CHUNK_SIZE === CHUNK_SIZE - 1 && (floorChunkY === 0 || floorChunkY === 1)) {
return WALL;
}
const { chunkX, chunkY, localX, localY } = getChunkCoordinates(worldX, worldY);
const key = getChunkKey(chunkX, chunkY);
if (!chunks.has(key)) {
return EMPTY;
}
const chunk = chunks.get(key);
const index = localY * CHUNK_SIZE + localX;
return chunk[index];
}
// Metadata functions to store additional information about pixels
function setMetadata(worldX, worldY, data) {
const key = `${worldX},${worldY}`;
metadata.set(key, data);
}
function getMetadata(worldX, worldY) {
const key = `${worldX},${worldY}`;
return metadata.get(key);
}
function removeMetadata(worldX, worldY) {
const key = `${worldX},${worldY}`;
metadata.delete(key);
}
// Move metadata when a pixel moves
function moveMetadata(fromX, fromY, toX, toY) {
const data = getMetadata(fromX, fromY);
if (data) {
setMetadata(toX, toY, data);
removeMetadata(fromX, fromY);
}
}
function getVisibleChunks() {
const visibleChunks = [];
// Calculate visible chunk range
const startChunkX = Math.floor(worldOffsetX / CHUNK_SIZE) - 1;
const endChunkX = Math.ceil((worldOffsetX + canvas.width / PIXEL_SIZE) / CHUNK_SIZE) + 1;
const startChunkY = Math.floor(worldOffsetY / CHUNK_SIZE) - 1;
const endChunkY = Math.ceil((worldOffsetY + canvas.height / PIXEL_SIZE) / CHUNK_SIZE) + 1;
for (let chunkY = startChunkY; chunkY < endChunkY; chunkY++) {
for (let chunkX = startChunkX; chunkX < endChunkX; chunkX++) {
visibleChunks.push({ chunkX, chunkY });
}
}
return visibleChunks;
}