refactor: Spread game code into modular files for better maintainability
This commit reorganizes the game's source code into multiple files within a `js/` directory, creating a more modular and maintainable structure. The changes include:
- Created separate files for different game components:
- `constants.js`: Game constants and element types
- `world.js`: World management functions
- `terrain.js`: Terrain generation logic
- `physics.js`: Physics simulation
- `render.js`: Rendering functions
- `input.js`: Input handling
- `main.js`: Main game initialization and loop
- Element-specific files in `js/elements/`:
- `basic.js`: Sand, water, dirt behaviors
- `plants.js`: Grass, seeds, flowers
- `trees.js`: Tree growth and leaf generation
- `fire.js`: Fire and lava behaviors
- Updated `index.html` to load modules in the correct order
- Removed the monolithic `script.js`
The modular approach improves code readability, makes future extensions easier, and separates concerns more effectively.
This commit is contained in:
128
js/world.js
Normal file
128
js/world.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user