SandGame/fire.js

92 lines
No EOL
3.1 KiB
JavaScript

import { grid, cols, rows } from './state.js';
import { config } from './config.js';
import { move } from './actions.js';
import { createCell } from './physics.js';
import { explode } from './explosive.js';
const dxs = [0, 0, -1, 1];
const dys = [1, -1, 0, 0];
export function updateFire(x, y, cell) {
if (cell.lifespan === undefined) {
cell.lifespan = Math.floor(Math.random() * 20) + 10;
cell.maxLife = cell.lifespan;
}
cell.lifespan--;
// Color shift as fire cools: yellow -> orange -> ember red
const lifeRatio = cell.lifespan / (cell.maxLife || 25);
if (lifeRatio > 0.6) {
cell.u32Color = 0xFF70F0FF; // Bright yellow-white (ABGR)
} else if (lifeRatio > 0.3) {
cell.u32Color = 0xFF0080FF; // Intense flame orange
} else {
cell.u32Color = 0xFF0025D0; // Deep ember red
}
// Death / decay -> spawn smoke
if (cell.lifespan <= 0 || Math.random() < config.fire.burnChance) {
if (Math.random() < 0.65) {
grid[x][y] = createCell('smoke');
} else {
grid[x][y] = null;
}
return;
}
// Extinguish if suffocated by solid matter
let airNeighbor = false;
for (let i = 0; i < 4; i++) {
const nx = x + dxs[i];
const ny = y + dys[i];
if (nx >= 0 && nx < cols && ny >= 0 && ny < rows) {
const n = grid[nx][ny];
if (!n || n.type === 'steam' || n.type === 'smoke') {
airNeighbor = true;
break;
}
}
}
if (!airNeighbor && Math.random() < 0.2) {
grid[x][y] = null;
return;
}
// Spread to flammable neighbors
for (let i = 0; i < 4; i++) {
const nx = x + dxs[i];
const ny = y + dys[i];
if (nx >= 0 && nx < cols && ny >= 0 && ny < rows) {
const n = grid[nx][ny];
if (n) {
const nt = n.type;
if (nt === 'water' || nt === 'ice') {
grid[x][y] = null; // Fire extinguished
grid[nx][ny] = createCell('steam');
return;
} else if (nt === 'explosive') {
explode(nx, ny);
return;
} else if (nt === 'oil') {
grid[nx][ny] = createCell('fire');
} else if (nt === 'plant' && Math.random() < config.plant.burnChance) {
grid[nx][ny] = createCell('fire');
} else if (nt === 'grass' && Math.random() < config.grass.burnChance) {
grid[nx][ny] = createCell('fire');
} else if (nt === 'wood' && Math.random() < config.wood.burnChance) {
grid[nx][ny] = createCell('fire');
}
}
}
}
// Rise / flicker randomly upwards
const dx = Math.floor(Math.random() * 3) - 1;
const dy = -Math.floor(Math.random() * 2); // Rise: 0 or -1
const nx = x + dx;
const ny = y + dy;
if (nx >= 0 && nx < cols && ny >= 0 && ny < rows && !grid[nx][ny]) {
move(x, y, nx, ny);
}
}