feat: Add new materials (dirt, stone, grass, wood) with unique behaviors
This commit is contained in:
parent
a6f0baf02c
commit
6ad564eea0
@ -12,6 +12,10 @@
|
|||||||
<div class="tools">
|
<div class="tools">
|
||||||
<button id="sand-btn" class="active">Sand</button>
|
<button id="sand-btn" class="active">Sand</button>
|
||||||
<button id="water-btn">Water</button>
|
<button id="water-btn">Water</button>
|
||||||
|
<button id="dirt-btn">Dirt</button>
|
||||||
|
<button id="stone-btn">Stone</button>
|
||||||
|
<button id="grass-btn">Grass</button>
|
||||||
|
<button id="wood-btn">Wood</button>
|
||||||
<button id="eraser-btn">Eraser</button>
|
<button id="eraser-btn">Eraser</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
|
99
script.js
99
script.js
@ -6,12 +6,20 @@ const WATER_SPREAD = 3;
|
|||||||
const SAND_COLOR = '#e6c588';
|
const SAND_COLOR = '#e6c588';
|
||||||
const WATER_COLOR = '#4a80f5';
|
const WATER_COLOR = '#4a80f5';
|
||||||
const WALL_COLOR = '#888888';
|
const WALL_COLOR = '#888888';
|
||||||
|
const DIRT_COLOR = '#8B4513';
|
||||||
|
const STONE_COLOR = '#A9A9A9';
|
||||||
|
const GRASS_COLOR = '#7CFC00';
|
||||||
|
const WOOD_COLOR = '#8B5A2B';
|
||||||
|
|
||||||
// Element types
|
// Element types
|
||||||
const EMPTY = 0;
|
const EMPTY = 0;
|
||||||
const SAND = 1;
|
const SAND = 1;
|
||||||
const WATER = 2;
|
const WATER = 2;
|
||||||
const WALL = 3;
|
const WALL = 3;
|
||||||
|
const DIRT = 4;
|
||||||
|
const STONE = 5;
|
||||||
|
const GRASS = 6;
|
||||||
|
const WOOD = 7;
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
let canvas, ctx;
|
let canvas, ctx;
|
||||||
@ -41,6 +49,10 @@ window.onload = function() {
|
|||||||
// Tool selection
|
// Tool selection
|
||||||
document.getElementById('sand-btn').addEventListener('click', () => setTool(SAND));
|
document.getElementById('sand-btn').addEventListener('click', () => setTool(SAND));
|
||||||
document.getElementById('water-btn').addEventListener('click', () => setTool(WATER));
|
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));
|
document.getElementById('eraser-btn').addEventListener('click', () => setTool(EMPTY));
|
||||||
|
|
||||||
// Navigation controls
|
// Navigation controls
|
||||||
@ -81,6 +93,14 @@ function setTool(tool) {
|
|||||||
document.getElementById('sand-btn').classList.add('active');
|
document.getElementById('sand-btn').classList.add('active');
|
||||||
} else if (tool === WATER) {
|
} else if (tool === WATER) {
|
||||||
document.getElementById('water-btn').classList.add('active');
|
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) {
|
} else if (tool === EMPTY) {
|
||||||
document.getElementById('eraser-btn').classList.add('active');
|
document.getElementById('eraser-btn').classList.add('active');
|
||||||
}
|
}
|
||||||
@ -317,7 +337,7 @@ function updatePhysics() {
|
|||||||
const index = y * CHUNK_SIZE + x;
|
const index = y * CHUNK_SIZE + x;
|
||||||
const type = chunk[index];
|
const type = chunk[index];
|
||||||
|
|
||||||
if (type === EMPTY) continue;
|
if (type === EMPTY || type === STONE || type === WOOD) continue;
|
||||||
|
|
||||||
const worldX = chunkX * CHUNK_SIZE + x;
|
const worldX = chunkX * CHUNK_SIZE + x;
|
||||||
const worldY = chunkY * CHUNK_SIZE + y;
|
const worldY = chunkY * CHUNK_SIZE + y;
|
||||||
@ -326,6 +346,10 @@ function updatePhysics() {
|
|||||||
updateSand(worldX, worldY);
|
updateSand(worldX, worldY);
|
||||||
} else if (type === WATER) {
|
} else if (type === WATER) {
|
||||||
updateWater(worldX, worldY);
|
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) {
|
function updateWater(x, y) {
|
||||||
// Try to move down
|
// Try to move down
|
||||||
if (getPixel(x, y + 1) === EMPTY) {
|
if (getPixel(x, y + 1) === EMPTY) {
|
||||||
@ -472,6 +561,14 @@ function render() {
|
|||||||
ctx.fillStyle = WATER_COLOR;
|
ctx.fillStyle = WATER_COLOR;
|
||||||
} else if (type === WALL) {
|
} else if (type === WALL) {
|
||||||
ctx.fillStyle = WALL_COLOR;
|
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
|
// Draw the pixel
|
||||||
|
Loading…
x
Reference in New Issue
Block a user