进化算法,实时渲染于 Node.js
Source: Dev.to
请提供您希望翻译的具体文本内容(文章正文),我将为您翻译成简体中文并保留原有的格式、Markdown 语法以及代码块和链接。谢谢!
介绍
强化学习、进化算法以及任何让计算机 看见 的技术,都是最让人视觉上满足的课题之一。实时观看事物学习的过程永远不会让人感到厌倦。
本文其实只是一个借口,用来展示我为 Node.js 构建的一个小型图形渲染器:tessera.js。
说实话,我想不出比进化算法的 hello world 更好的演示了:一堆随机颜色在变异,慢慢进化到目标颜色。
如果你是图形编程新手,别担心——数字世界中 所有视觉 的基本单元其实非常简单。我在这里做了介绍:
Graphics 101: A Node.js Renderer
寻找目标颜色
安装 tessera
npm i tessera.js@latest
启动渲染器
import { loadRenderer, PixelBuffer, ShapeDrawer } from "tessera.js";
const { Renderer } = loadRenderer();
const renderer = new Renderer();
if (!renderer.initialize(1200, 800, "Evolution Algos Hello World")) {
console.error("failed to init renderer");
process.exit(1);
}
renderer.targetFPS = 60;
const canvas = new PixelBuffer(renderer, 1200, 800);
参数与基因组(“物种”)
// Target color we're evolving toward
const TARGET = { r: 120, g: 80, b: 150 };
/**
* Genome = full DNA
* Genotype = specific gene values
* Phenotype = what we actually see
*
* Here: genome is just RGB.
*/
class Genome {
constructor(r = null, g = null, b = null) {
this.r = r ?? Math.floor(Math.random() * 256);
this.g = g ?? Math.floor(Math.random() * 256);
this.b = b ?? Math.floor(Math.random() * 256);
this.fitness = 0;
}
}
const MUTATION_RATE = 0.3; // more chaos
const ELITE_COUNT = 5; // more stability
const POP_SIZE = 150; // slower but more thorough
let population = Array.from({ length: POP_SIZE }, () => new Genome());
let generation = 0;
let bestEver = null;
核心进化算法
// Fitness: lower distance = better
function evaluateFitness(genome) {
const dr = genome.r - TARGET.r;
const dg = genome.g - TARGET.g;
const db = genome.b - TARGET.b;
genome.fitness = Math.sqrt(dr * dr + dg * dg + db * db);
}
// Tournament selection
function selectParent(pop) {
const tournamentSize = 3;
let best = pop[Math.floor(Math.random() * pop.length)];
for (let i = 1; i a.fitness - b.fitness);
if (!bestEver || population[0].fitness {
const x = gridX + (i % cols) * (cellSize + 5);
const y = gridY + Math.floor(i / cols) * (cellSize + 5);
ShapeDrawer.fillRect(canvas, x, y, cellSize, cellSize,
g.r, g.g, g.b, 255);
});
canvas.upload();
}
renderer.onRender(() => {
canvas.draw(0, 0);
renderer.drawText("TARGET", { x: 50, y: 30 }, 16, { r: 1, g: 1, b: 1, a: 1 });
renderer.drawText("BEST NOW", { x: 250, y: 30 }, 16, { r: 1, g: 1, b: 1, a: 1 });
renderer.drawText("BEST EVER",{ x: 450, y: 30 }, 16, { r: 1, g: 1, b: 1, a: 1 });
const best = population[0];
// ... (additional rendering logic can go here)
});
renderer.drawText(
`Gen: ${generation} | Fitness: ${best.fitness.toFixed(2)} | RGB: (${best.r}, ${best.g}, ${best.b})`,
{ x: 50, y: 650 },
16,
{ r: 1, g: 1, b: 1, a: 1 }
);
循环
let frameCount = 0;
const FRAME_DELAY = 60;
evolve();
function Loop() {
frameCount++;
renderer.input.GetInput();
if (frameCount % FRAME_DELAY === 0) {
evolve();
}
render();
if (renderer.step()) {
setImmediate(Loop);
} else {
renderer.shutdown();
}
}
Loop();
在大约 100 行代码(不算样板代码)中,我们已经实现了一个 完整动画的进化算法,并在 Node.js 中运行。
如果你对图形编程感兴趣,我还有更多内容即将推出。
查看仓库:
https://github.com/sklyt/render – 给它加星并浏览示例,如果这类东西是你的兴趣所在的话。
