feat: Add lava element with dynamic colors and interactions
This commit is contained in:
parent
d6d874ab99
commit
c858da4c3e
@ -19,6 +19,7 @@
|
||||
<button id="seed-btn">Seed</button>
|
||||
<button id="tree-seed-btn">Tree Seed</button>
|
||||
<button id="fire-btn">Fire</button>
|
||||
<button id="lava-btn">Lava</button>
|
||||
<button id="eraser-btn">Eraser</button>
|
||||
</div>
|
||||
<div class="navigation">
|
||||
|
116
script.js
116
script.js
@ -14,6 +14,7 @@ const SEED_COLOR = '#654321';
|
||||
const FLOWER_COLORS = ['#FF0000', '#FFFF00', '#FF00FF', '#FFA500', '#FFFFFF', '#00FFFF'];
|
||||
const LEAF_COLOR = '#228B22';
|
||||
const FIRE_COLORS = ['#FF0000', '#FF3300', '#FF6600', '#FF9900', '#FFCC00', '#FFFF00'];
|
||||
const LAVA_COLORS = ['#FF0000', '#FF3300', '#FF4500', '#FF6600', '#FF8C00'];
|
||||
|
||||
// Element types
|
||||
const EMPTY = 0;
|
||||
@ -30,6 +31,7 @@ const FLOWER = 10;
|
||||
const TREE_SEED = 11;
|
||||
const LEAF = 12;
|
||||
const FIRE = 13;
|
||||
const LAVA = 14;
|
||||
|
||||
// Flammable materials
|
||||
const FLAMMABLE_MATERIALS = [GRASS, WOOD, SEED, GRASS_BLADE, FLOWER, TREE_SEED, LEAF];
|
||||
@ -71,6 +73,7 @@ window.onload = function() {
|
||||
document.getElementById('seed-btn').addEventListener('click', () => setTool(SEED));
|
||||
document.getElementById('tree-seed-btn').addEventListener('click', () => setTool(TREE_SEED));
|
||||
document.getElementById('fire-btn').addEventListener('click', () => setTool(FIRE));
|
||||
document.getElementById('lava-btn').addEventListener('click', () => setTool(LAVA));
|
||||
document.getElementById('eraser-btn').addEventListener('click', () => setTool(EMPTY));
|
||||
|
||||
// Navigation controls
|
||||
@ -125,6 +128,8 @@ function setTool(tool) {
|
||||
document.getElementById('tree-seed-btn').classList.add('active');
|
||||
} else if (tool === FIRE) {
|
||||
document.getElementById('fire-btn').classList.add('active');
|
||||
} else if (tool === LAVA) {
|
||||
document.getElementById('lava-btn').classList.add('active');
|
||||
} else if (tool === EMPTY) {
|
||||
document.getElementById('eraser-btn').classList.add('active');
|
||||
}
|
||||
@ -439,6 +444,8 @@ function updatePhysics() {
|
||||
updateTreeSeed(worldX, worldY);
|
||||
} else if (type === FIRE) {
|
||||
updateFire(worldX, worldY);
|
||||
} else if (type === LAVA) {
|
||||
updateLava(worldX, worldY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -820,7 +827,7 @@ function updateWater(x, y) {
|
||||
}
|
||||
}
|
||||
|
||||
// Water extinguishes fire
|
||||
// Water extinguishes fire and turns lava into stone
|
||||
const directions = [
|
||||
{dx: -1, dy: 0}, {dx: 1, dy: 0},
|
||||
{dx: 0, dy: -1}, {dx: 0, dy: 1},
|
||||
@ -832,6 +839,13 @@ function updateWater(x, y) {
|
||||
if (getPixel(x + dir.dx, y + dir.dy) === FIRE) {
|
||||
setPixel(x + dir.dx, y + dir.dy, EMPTY);
|
||||
removeMetadata(x + dir.dx, y + dir.dy);
|
||||
} else if (getPixel(x + dir.dx, y + dir.dy) === LAVA) {
|
||||
// Water turns lava into stone
|
||||
setPixel(x + dir.dx, y + dir.dy, STONE);
|
||||
removeMetadata(x + dir.dx, y + dir.dy);
|
||||
// Water is consumed in the process
|
||||
setPixel(x, y, EMPTY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -907,6 +921,101 @@ function updateFire(x, y) {
|
||||
}
|
||||
}
|
||||
|
||||
// Add lava update function
|
||||
function updateLava(x, y) {
|
||||
const metadata = getMetadata(x, y);
|
||||
|
||||
if (!metadata) {
|
||||
// Initialize metadata if it doesn't exist
|
||||
setMetadata(x, y, {
|
||||
colorIndex: Math.floor(Math.random() * LAVA_COLORS.length)
|
||||
});
|
||||
} else {
|
||||
// Randomly change color for flowing effect
|
||||
if (Math.random() < 0.1) {
|
||||
metadata.colorIndex = Math.floor(Math.random() * LAVA_COLORS.length);
|
||||
setMetadata(x, y, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// Lava moves slower than water
|
||||
if (Math.random() < 0.7) {
|
||||
// Try to move down
|
||||
if (getPixel(x, y + 1) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x, y + 1, LAVA);
|
||||
moveMetadata(x, y, x, y + 1);
|
||||
}
|
||||
// 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, LAVA);
|
||||
moveMetadata(x, y, x - 1, y + 1);
|
||||
}
|
||||
else if (getPixel(x + 1, y + 1) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x + 1, y + 1, LAVA);
|
||||
moveMetadata(x, y, x + 1, y + 1);
|
||||
}
|
||||
// Try to spread horizontally (slower than water)
|
||||
else if (Math.random() < 0.3) {
|
||||
// Randomly choose direction first
|
||||
const goLeft = Math.random() > 0.5;
|
||||
|
||||
if (goLeft && getPixel(x - 1, y) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x - 1, y, LAVA);
|
||||
moveMetadata(x, y, x - 1, y);
|
||||
} else if (!goLeft && getPixel(x + 1, y) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x + 1, y, LAVA);
|
||||
moveMetadata(x, y, x + 1, y);
|
||||
}
|
||||
// Try the other direction if first failed
|
||||
else if (!goLeft && getPixel(x - 1, y) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x - 1, y, LAVA);
|
||||
moveMetadata(x, y, x - 1, y);
|
||||
} else if (goLeft && getPixel(x + 1, y) === EMPTY) {
|
||||
setPixel(x, y, EMPTY);
|
||||
setPixel(x + 1, y, LAVA);
|
||||
moveMetadata(x, y, x + 1, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lava sets nearby flammable materials on fire
|
||||
const directions = [
|
||||
{dx: -1, dy: 0}, {dx: 1, dy: 0},
|
||||
{dx: 0, dy: -1}, {dx: 0, dy: 1},
|
||||
{dx: -1, dy: -1}, {dx: 1, dy: -1},
|
||||
{dx: -1, dy: 1}, {dx: 1, dy: 1}
|
||||
];
|
||||
|
||||
for (const dir of directions) {
|
||||
const nearbyType = getPixel(x + dir.dx, y + dir.dy);
|
||||
|
||||
// Set flammable materials on fire
|
||||
if (FLAMMABLE_MATERIALS.includes(nearbyType)) {
|
||||
setPixel(x + dir.dx, y + dir.dy, FIRE);
|
||||
setMetadata(x + dir.dx, y + dir.dy, {
|
||||
lifetime: 100 + Math.floor(Math.random() * 100),
|
||||
colorIndex: Math.floor(Math.random() * FIRE_COLORS.length)
|
||||
});
|
||||
}
|
||||
|
||||
// Lava can melt sand into glass (stone)
|
||||
else if (nearbyType === SAND && Math.random() < 0.05) {
|
||||
setPixel(x + dir.dx, y + dir.dy, STONE);
|
||||
}
|
||||
|
||||
// Lava can burn dirt
|
||||
else if (nearbyType === DIRT && Math.random() < 0.02) {
|
||||
setPixel(x + dir.dx, y + dir.dy, EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getVisibleChunks() {
|
||||
const visibleChunks = [];
|
||||
|
||||
@ -1006,6 +1115,11 @@ function render() {
|
||||
const metadata = getMetadata(chunkX * CHUNK_SIZE + x, chunkY * CHUNK_SIZE + y);
|
||||
const colorIndex = metadata ? metadata.colorIndex : 0;
|
||||
ctx.fillStyle = FIRE_COLORS[colorIndex];
|
||||
} else if (type === LAVA) {
|
||||
// Get lava color from metadata
|
||||
const metadata = getMetadata(chunkX * CHUNK_SIZE + x, chunkY * CHUNK_SIZE + y);
|
||||
const colorIndex = metadata ? metadata.colorIndex : 0;
|
||||
ctx.fillStyle = LAVA_COLORS[colorIndex];
|
||||
}
|
||||
|
||||
// Draw the pixel
|
||||
|
Loading…
x
Reference in New Issue
Block a user