diff --git a/index.html b/index.html
index 91b17fb..823ae6e 100644
--- a/index.html
+++ b/index.html
@@ -12,6 +12,10 @@
+
+
+
+
diff --git a/script.js b/script.js
index 14a98e6..bb67325 100644
--- a/script.js
+++ b/script.js
@@ -6,12 +6,20 @@ const WATER_SPREAD = 3;
const SAND_COLOR = '#e6c588';
const WATER_COLOR = '#4a80f5';
const WALL_COLOR = '#888888';
+const DIRT_COLOR = '#8B4513';
+const STONE_COLOR = '#A9A9A9';
+const GRASS_COLOR = '#7CFC00';
+const WOOD_COLOR = '#8B5A2B';
// Element types
const EMPTY = 0;
const SAND = 1;
const WATER = 2;
const WALL = 3;
+const DIRT = 4;
+const STONE = 5;
+const GRASS = 6;
+const WOOD = 7;
// Global variables
let canvas, ctx;
@@ -41,6 +49,10 @@ window.onload = function() {
// Tool selection
document.getElementById('sand-btn').addEventListener('click', () => setTool(SAND));
document.getElementById('water-btn').addEventListener('click', () => setTool(WATER));
+ document.getElementById('dirt-btn').addEventListener('click', () => setTool(DIRT));
+ document.getElementById('stone-btn').addEventListener('click', () => setTool(STONE));
+ document.getElementById('grass-btn').addEventListener('click', () => setTool(GRASS));
+ document.getElementById('wood-btn').addEventListener('click', () => setTool(WOOD));
document.getElementById('eraser-btn').addEventListener('click', () => setTool(EMPTY));
// Navigation controls
@@ -81,6 +93,14 @@ function setTool(tool) {
document.getElementById('sand-btn').classList.add('active');
} else if (tool === WATER) {
document.getElementById('water-btn').classList.add('active');
+ } else if (tool === DIRT) {
+ document.getElementById('dirt-btn').classList.add('active');
+ } else if (tool === STONE) {
+ document.getElementById('stone-btn').classList.add('active');
+ } else if (tool === GRASS) {
+ document.getElementById('grass-btn').classList.add('active');
+ } else if (tool === WOOD) {
+ document.getElementById('wood-btn').classList.add('active');
} else if (tool === EMPTY) {
document.getElementById('eraser-btn').classList.add('active');
}
@@ -317,7 +337,7 @@ function updatePhysics() {
const index = y * CHUNK_SIZE + x;
const type = chunk[index];
- if (type === EMPTY) continue;
+ if (type === EMPTY || type === STONE || type === WOOD) continue;
const worldX = chunkX * CHUNK_SIZE + x;
const worldY = chunkY * CHUNK_SIZE + y;
@@ -326,6 +346,10 @@ function updatePhysics() {
updateSand(worldX, worldY);
} else if (type === WATER) {
updateWater(worldX, worldY);
+ } else if (type === DIRT) {
+ updateDirt(worldX, worldY);
+ } else if (type === GRASS) {
+ updateGrass(worldX, worldY);
}
}
}
@@ -354,6 +378,71 @@ function updateSand(x, y) {
}
}
+function updateDirt(x, y) {
+ // Try to move down
+ if (getPixel(x, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x, y + 1, DIRT);
+ }
+ // Try to move down-left or down-right
+ else if (getPixel(x - 1, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x - 1, y + 1, DIRT);
+ }
+ else if (getPixel(x + 1, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x + 1, y + 1, DIRT);
+ }
+ // Dirt can displace water
+ else if (getPixel(x, y + 1) === WATER) {
+ setPixel(x, y, WATER);
+ setPixel(x, y + 1, DIRT);
+ }
+
+ // Dirt can turn into grass if exposed to air above
+ if (getPixel(x, y - 1) === EMPTY && Math.random() < 0.001) {
+ setPixel(x, y, GRASS);
+ }
+}
+
+function updateGrass(x, y) {
+ // Grass behaves like dirt for physics
+ if (getPixel(x, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x, y + 1, GRASS);
+ }
+ else if (getPixel(x - 1, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x - 1, y + 1, GRASS);
+ }
+ else if (getPixel(x + 1, y + 1) === EMPTY) {
+ setPixel(x, y, EMPTY);
+ setPixel(x + 1, y + 1, GRASS);
+ }
+ else if (getPixel(x, y + 1) === WATER) {
+ setPixel(x, y, WATER);
+ setPixel(x, y + 1, GRASS);
+ }
+
+ // Grass can spread to nearby dirt
+ if (Math.random() < 0.0005) {
+ const directions = [
+ {dx: -1, dy: 0}, {dx: 1, dy: 0},
+ {dx: 0, dy: -1}, {dx: 0, dy: 1}
+ ];
+
+ const dir = directions[Math.floor(Math.random() * directions.length)];
+ if (getPixel(x + dir.dx, y + dir.dy) === DIRT) {
+ setPixel(x + dir.dx, y + dir.dy, GRASS);
+ }
+ }
+
+ // Grass dies if covered (no air above)
+ if (getPixel(x, y - 1) !== EMPTY && Math.random() < 0.05) {
+ setPixel(x, y, DIRT);
+ }
+}
+
function updateWater(x, y) {
// Try to move down
if (getPixel(x, y + 1) === EMPTY) {
@@ -472,6 +561,14 @@ function render() {
ctx.fillStyle = WATER_COLOR;
} else if (type === WALL) {
ctx.fillStyle = WALL_COLOR;
+ } else if (type === DIRT) {
+ ctx.fillStyle = DIRT_COLOR;
+ } else if (type === STONE) {
+ ctx.fillStyle = STONE_COLOR;
+ } else if (type === GRASS) {
+ ctx.fillStyle = GRASS_COLOR;
+ } else if (type === WOOD) {
+ ctx.fillStyle = WOOD_COLOR;
}
// Draw the pixel