Pular para o conteúdo
murad.guide

Programação Criativa

Capítulo 22

Enxame leve

2 min de leitura 362 palavras 1 gravura

Alinhamento: média das velocidades dos vizinhos próximos. Demo própria, texto novo.

Trabalhe sobre uma cópia da pasta inicio do exemplo correspondente. Leia, digite, mude uma coisa, preveja, recarregue e confira. A referência completa fica na raiz da pasta do exemplo, no pacote anexo.

O que você pratica

Enxame leve

Nuvem alinhando

Pontos tendem a apontar igual aos vizinhos.

Erro comum: calcular vizinhos com custo alto demais — aqui N é pequeno.

align

Complete a regra de alinhamento.

if (o !== me && p5.Vector.dist(me.pos, o.pos) < 50) { avg.add(o.vel); n++; }

Pare e experimente. Sem coesão/separação ainda — de propósito.

Extensão

Depois você pode somar separação se quiser.

Não publique exercícios com dados reais. Conteúdo fictício de Recife.

Como o exemplo desta etapa funciona

A referência desta etapa reúne index.html, sketch.js, styles.css. Abra o resultado pronto, localize o trecho que produz enxame leve e só então compare com inicio. Os dois diretórios são independentes: você pode errar, restaurar e repetir sem buscar arquivos de outro capítulo.

Leitura do resultado

Observe primeiro o que permanece parado e o que responde a uma ação. Depois altere um único número, cor, coordenada ou condição. Antes de recarregar, escreva o efeito esperado. Essa previsão separa uma mudança compreendida de uma tentativa ao acaso.

Diagnóstico guiado

Se a cena sumir, confira a primeira mensagem do Console e o caminho dos arquivos. Em SVG, revise viewBox, atributos e ordem das formas. Em p5.js, confirme a biblioteca local e se setup e draw foram escritos corretamente. Em Canvas ou WebGL, verifique o contexto e os limites numéricos antes de mudar outra coisa.

Critério de avanço

Avance quando conseguir descrever a cena, modificar um parâmetro com previsão e restaurar a referência sem copiar arquivos de uma etapa posterior.

Atividades

  1. n==0 retorna?
  2. setMag(2) na média?
  3. Wrap em x?

Respostas comentadas

Só abra depois de tentar.

Atividade 1. Vetor zero — sem força.

Atividade 2. Normaliza a velocidade desejada.

Atividade 3. Sim, reaparece do outro lado.

Exemplo deste capítulo: pacote de exemplos/22-enxame/.

O arquivo completo

Referência do exemplo 22-enxame, reproduzida aqui para que você possa conferir sem sair da página.

index.html

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Enxame — Laboratório da Luz</title>
  <link rel="stylesheet" href="styles.css">

</head>
<body>
  <a class="skip" href="#conteudo">Ir ao conteúdo</a>
  <header>
    <p class="tag">Laboratório da Luz · Recife</p>
    <h1>Enxame</h1>
  </header>
  <main id="conteudo">
<p class="dica">Alinhamento: média das velocidades vizinhas.</p>
<div class="stage" id="canvas-host"></div>
<p class="dica">Se o desenho não aparecer ao abrir o arquivo direto, sirva <code>curso/</code> em 127.0.0.1.</p>
  </main>
  <footer>
    <p>Conteúdo fictício para estudo local. Não publique dados reais.</p>
  </footer>
  <script src="../../lib/p5.min.js"></script>
  <script src="sketch.js"></script>
</body>
</html>

sketch.js

const boids = [];
function setup() {
  createCanvas(520, 300).parent("canvas-host");
  for (let i = 0; i < 40; i++) {
    boids.push({ pos: createVector(random(width), random(height)), vel: p5.Vector.random2D() });
  }
}
function align(me) {
  let avg = createVector(), n = 0;
  for (const o of boids) {
    if (o !== me && p5.Vector.dist(me.pos, o.pos) < 50) { avg.add(o.vel); n++; }
  }
  if (n > 0) { avg.div(n).setMag(2); return p5.Vector.sub(avg, me.vel).limit(0.05); }
  return createVector();
}
function draw() {
  background(15, 26, 34);
  for (const b of boids) {
    b.vel.add(align(b));
    b.pos.add(b.vel);
    if (b.pos.x < 0) b.pos.x = width;
    if (b.pos.x > width) b.pos.x = 0;
    if (b.pos.y < 0) b.pos.y = height;
    if (b.pos.y > height) b.pos.y = 0;
    stroke(110, 198, 201);
    strokeWeight(3);
    point(b.pos.x, b.pos.y);
  }
}