所以我有一个函数,它应该模仿代表位置的2D数组的火焰的增长和传播。 这是它的工作原理:
findingNeighbors
找到a的邻居像素
像素强度增加,强度增加。到目前为止,该功能有效,但它非常线性,并且不像我想的那样工作。我以为它会以更放射的方式传播。我不确定我做错了什么。我希望它看起来像真火蔓延。我想要一个更径向的随机增长模式。
所以我的问题是我该如何对函数进行随机化以显示火势从一个点传播而不会影响性能?寻找邻居的函数应该随机一点吗?
下面包含可运行代码
function simulateFire() {
for (let y = 0; y < mainGrid.length; y++) {
for (let x = 0; x < mainGrid[y].length; x++) {
let intensity = mainGrid[y][x];
if (intensity >= 10 && intensity < 40) {
findingNeighbors(y, x);
$(`#cell_${y}_${x}`).empty().addClass(`i-${intensity}`).html(intensity);
}
}
}
}
function findingNeighbors(i, j) {
let rowLimit = mainGrid.length - 1;
let columnLimit = mainGrid[0].length - 1;
for (let x = Math.max(0, i - 1); x <= Math.min(i + 1, rowLimit); x++) {
for (let y = Math.max(0, j - 1); y <= Math.min(j + 1, columnLimit); y++) {
if (x !== i || y !== j) {
increaseIntensity(y, x);
}
}
}
}
function increaseIntensity (y,x) {
if (mainGrid[y][x] === 0 ) {
mainGrid[y][x] = 10;
} else if (mainGrid[y][x] > 9 && mainGrid[y][x] < 40) {
mainGrid[y][x]++;
}
}
let mainGrid = Array(200).fill().map(() => Array(200).fill(0)); // 200 x 200
$(document).ready(() => {
let fireInterval;
startFire(1, 1); // start fire at location (1,1)
addTable(mainGrid, 'table');
$('#start-btn').on('click', () => {
fireInterval = setInterval(() => {
simulateFire();
}, 500);
});
$('#stop-btn').on('click', () => {
clearInterval(fireInterval);
})
});
function increaseIntensity(y, x) {
if (mainGrid[y][x] === 0) {
mainGrid[y][x] = 10;
} else if (mainGrid[y][x] > 9 && mainGrid[y][x] < 40) {
mainGrid[y][x]++;
}
}
function addTable(dataArray, id) {
$(`#${id}`)
.empty()
.append(`<table id="scene-arr-table" style="border-collapse:collapse;"></table>`);
dataArray.forEach((el, r) => {
let row = $(`<tr></tr>`);
$(`#scene-arr-table`).append(row);
el.forEach((el, c) => {
$(row).append(`<td id="cell_${r}_${c}">${el}</td>`)
});
});
}
function startFire(y, x) {
mainGrid[y][x] = 10; // intensity starts at 10
}
function simulateFire() {
for (let y = 0; y < mainGrid.length; y++) {
for (let x = 0; x < mainGrid[y].length; x++) {
let intensity = mainGrid[y][x];
if (intensity >= 10 && intensity < 40) {
findingNeighbors(y, x);
$(`#cell_${y}_${x}`).empty().addClass(`i-${intensity}`).html(intensity);
}
}
}
}
function findingNeighbors(i, j) {
let rowLimit = mainGrid.length - 1;
let columnLimit = mainGrid[0].length - 1;
for (let x = Math.max(0, i - 1); x <= Math.min(i + 1, rowLimit); x++) {
for (let y = Math.max(0, j - 1); y <= Math.min(j + 1, columnLimit); y++) {
if (x !== i || y !== j) {
increaseIntensity(y, x);
}
}
}
}
&#13;
.i-0 {
background: transparent;
}
.i-10 {
background: red;
}
.i-11 {
background: rgba(255, 0, 0, 0.9);
}
.i-12 {
background: rgba(255, 0, 0, 0.8);
}
.i-13 {
background: rgba(255, 0, 0, 0.7);
}
.i-14 {
background: rgba(255, 0, 0, 0.6);
}
.i-15 {
background: rgba(255, 0, 0, 0.5);
}
.i-16 {
background: rgba(255, 0, 0, 0.4);
}
.i-17 {
background: rgba(255, 0, 0, 0.3);
}
.i-18 {
background: rgba(255, 0, 0, 0.2);
}
.i-19 {
background: rgba(255, 0, 0, 0.1);
}
.i-20 {
background: red;
}
.i-21 {
background: red;
}
.i-22 {
background: red;
}
.i-23 {
background: red;
}
.i-24 {
background: red;
}
.i-25 {
background: red;
}
.i-26 {
background: red;
}
.i-27 {
background: red;
}
.i-28 {
background: red;
}
.i-29 {
background: red;
}
.i-30 {
background: red;
}
.i-31 {
background: #e60404;
}
.i-32 {
background: #cd0808;
}
.i-33 {
background: #b40c0c;
}
.i-34 {
background: #9b1010;
}
.i-35 {
background: #821414;
}
.i-36 {
background: #691818;
}
.i-37 {
background: #501c1c;
}
.i-38 {
background: #372020;
}
.i-39 {
background: #1e2424;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<button id="start-btn" type="button">START SIM</button>
<button id="stop-btn" type="button">STOP SIM</button>
<div id="table" style="font-size:2px;">
</div>
</body>
</html>
&#13;
答案 0 :(得分:1)
使其更不规则的一种方法是为其添加一些随机性。将increaseIntensity(x,y)
替换为随机参数,可能使用非线性滤波器和反距离。
increaseIntensity(x, y, sqrt(rand(0.,1.)) / ((x-i) * (x-i) + (y-j) * (y-j))
另一种方法是使用内核过滤器。你现在所拥有的类似于一个3x3滤波器,所有值都是1.我会尝试使用5x5滤波器,外部像素值减少一些。这应该给它一个更径向的外观。您需要增加过滤器尺寸以提高防火墙的质量。通过这种方式,您还可以在某个方向上构建具有更高值的滤波器,从而产生风影响的幻觉。
在这两种情况下,请确保您不要在同一帧中重复使用新值,否则您的火力会在某个方向上消失。
为了提高性能,请检查GPU计算支持。这些类型的操作(内核)得到了很好的支持并且非常快。