gpt4 book ai didi

javascript - 创建描述点的离散分布的颜色渐变

转载 作者:行者123 更新时间:2023-12-02 14:58:23 25 4
gpt4 key购买 nike

我正在制作一张渲染游戏对象位置的 map (Project Zomboid 僵尸):

zombies

当用户缩小时,单个点不再有用。相反,我想使用红色渐变来渲染僵尸在某个区域上的分布。我尝试对每个渲染像素遍历所有僵尸,并根据到僵尸的距离平方和进行倒数着色。结果:

image description

这太模糊了。此外,结果更多地受到远离点的僵尸的影响 - 我需要更多地受到靠近点的僵尸的影响。所以这只是数学。这是我使用的代码:

var h = canvas.height;
var w = canvas.width;
// To loop over more than 1 pixel (performance)
var tileSize = 10;
var halfRadius = Math.floor(tileSize/2);
var time = performance.now();
// "Squared" because we didnt unsquare it
function distanceSquared(A, B) {
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
// Loop for every x,y pixel (or region of pixels)
for(var y=0; y<h; y+=tileSize) {
for(var x=0; x<w; x+=tileSize) {
// Time security - stop rendering after 1 second
if(performance.now()-time>1000) {
x=w;y=h;break;
}
// Convert relative canvas offset to absolute point on the map
var point = canvasPixeltoImagePixel(x, y);
// For every zombie add sqrt(distance from this point to zombie)
var distancesRoot = 0;
// Loop over the zombies
var zombieCoords;
for(var i=0; i<zombies_length; i++) {
// Get single zombie coordinates as {x:0, y:0}
if((coords=zombies[i].pixel)==null)
coords = zombies[i].pixel = tileToPixel(zombies[i].coordinates[0], zombies[i].coordinates[1], drawer);
// square root is a) slow and b) probably not what I want anyway
var dist = distanceSquared(coords, point);
distancesRoot+=dist;
}
// The higher the sum of distances is, the more intensive should the color be
var style = 'rgba(255,0,0,'+300000000/distancesRoot+')';
// Kill the console immediatelly
//console.log(style);
// Maybe we should sample and cache the transparency styles since there's limited ammount of colors?
ctx.fillStyle = style;
ctx.fillRect(x-halfRadius,y-halfRadius,tileSize,tileSize);
}
}

我对如何做到这一点的理论解释非常满意,不过如果你用一些要点制作简单的 Canvas 示例,那就太棒了。

最佳答案

这是热图的示例。它基本上是点上的梯度球体,然后通过热坡道增加不透明度。聚集在一起的球体越多,颜色越纯,可以显示为具有适当渐变的放大区域。

更新

我清理了一些变量并将 zeeks 放入动画循环中。有一个 fps 计数器可以查看它的性能。渐变圆可能很昂贵。如果我们缩小热图的规模,我们可能可以做更大的世界。它看起来不会那么平滑,但计算速度会快得多。

更新2

热图现在具有可调节的比例,并且正如预测的那样,我们的 fps 有所增加。

if (typeof app === "undefined") {
var app = {};
}

app.zeeks = 200;
app.w = 600;
app.h = 400;
app.circleSize = 50;
app.scale = 0.25;

init();

function init() {
app.can = document.getElementById('can');
app.ctx = can.getContext('2d');
app.can.height = app.h;
app.can.width = app.w;
app.radius = Math.floor(app.circleSize / 2);

app.z = genZ(app.zeeks, app.w, app.h);
app.flip = false;

// Make temporary layer once.
app.layer = document.createElement('canvas');
app.layerCtx = app.layer.getContext('2d');
app.layer.width = Math.floor(app.w * app.scale);
app.layer.height = Math.floor(app.h * app.scale);

// Make the gradient canvas once.
var sCircle = Math.floor(app.circleSize * app.scale);
app.radius = Math.floor(sCircle / 2);
app.gCan = genGradientCircle(sCircle);
app.ramp = genRamp();

// fps counter
app.frames = 0;
app.fps = "- fps";
app.fpsInterval = setInterval(calcFps, 1000);

// start animation
ani();
flicker();
}

function calcFps() {
app.fps = app.frames + " fps";
app.frames = 0;
}

// animation loop
function ani() {
app.frames++;
var ctx = app.ctx;
var w = app.w;
var h = app.h;
moveZ();
//ctx.clearRect(0, 0, w, h);
ctx.fillStyle = "#006600";
ctx.fillRect(0, 0, w, h);
if (app.flip) {
drawZ2();
drawZ();
} else {
drawZ2();
}
ctx.fillStyle = "#FFFF00";
ctx.fillText(app.fps, 10, 10);
requestAnimationFrame(ani);
}

function flicker() {

app.flip = !app.flip;
if (app.flip) {
setTimeout(flicker, 500);
} else {
setTimeout(flicker, 5000);
}

}

function genGradientCircle(size) {
// gradient image
var gCan = document.createElement('canvas');
gCan.width = gCan.height = size;
var gCtx = gCan.getContext('2d');
var radius = Math.floor(size / 2);
var grad = gCtx.createRadialGradient(radius, radius, radius, radius, radius, 0);
grad.addColorStop(1, "rgba(255,255,255,.65)");
grad.addColorStop(0, "rgba(255,255,255,0)");
gCtx.fillStyle = grad;
gCtx.fillRect(0, 0, gCan.width, gCan.height);
return gCan;
}

function genRamp() {
// Create heat gradient
var heat = document.createElement('canvas');
var hCtx = heat.getContext('2d');
heat.width = 256;
heat.height = 5;
var linGrad = hCtx.createLinearGradient(0, 0, heat.width, heat.height);
linGrad.addColorStop(1, "rgba(255,0,0,.75)");
linGrad.addColorStop(0.5, "rgba(255,255,0,.03)");
linGrad.addColorStop(0, "rgba(255,255,0,0)");
hCtx.fillStyle = linGrad;
hCtx.fillRect(0, 0, heat.width, heat.height);

// create ramp from gradient
var ramp = [];
var imageData = hCtx.getImageData(0, 0, heat.width, 1);
var d = imageData.data;
for (var x = 0; x < heat.width; x++) {
var i = x * 4;
ramp[x] = [d[i], d[i + 1], d[i + 2], d[i + 3]];
}

return ramp;
}

function genZ(n, w, h) {
var a = [];
for (var i = 0; i < n; i++) {
a[i] = [
Math.floor(Math.random() * w),
Math.floor(Math.random() * h),
Math.floor(Math.random() * 3) - 1,
Math.floor(Math.random() * 3) - 1
];
}
return a;
}

function moveZ() {
var w = app.w
var h = app.h;
var z = app.z;
for (var i = 0; i < z.length; i++) {
var s = z[i];
s[0] += s[2];
s[1] += s[3];
if (s[0] > w || s[0] < 0) s[2] *= -1;
if (s[1] > w || s[1] < 0) s[3] *= -1;
}
}

function drawZ() {
var ctx = app.ctx;
var z = app.z;
ctx.fillStyle = "#FFFF00";
for (var i = 0; i < z.length; i++) {
ctx.fillRect(z[i][0] - 2, z[i][1] - 2, 4, 4);
}
}

function drawZ2() {
var ctx = app.ctx;
var layer = app.layer;
var layerCtx = app.layerCtx;
var gCan = app.gCan;
var z = app.z;
var radius = app.radius;

// render gradients at coords onto layer
for (var i = 0; i < z.length; i++) {
var x = Math.floor((z[i][0] * app.scale) - radius);
var y = Math.floor((z[i][1] * app.scale) - radius);
layerCtx.drawImage(gCan, x, y);
}

// adjust layer for heat ramp
var ramp = app.ramp;

// apply ramp to layer
var imageData = layerCtx.getImageData(0, 0, layer.width, layer.height);

d = imageData.data;
for (var i = 0; i < d.length; i += 4) {
if (d[i + 3] != 0) {
var c = ramp[d[i + 3]];
d[i] = c[0];
d[i + 1] = c[1];
d[i + 2] = c[2];
d[i + 3] = c[3];
}
}

layerCtx.putImageData(imageData, 0, 0);

// draw layer on world
ctx.drawImage(layer, 0, 0, layer.width, layer.height, 0, 0, app.w, app.h);
}
<canvas id="can" width="600" height="400"></canvas>

关于javascript - 创建描述点的离散分布的颜色渐变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35607921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com