Números pseudoaleatórios

Você já sabe que o computador não consegue criar números verdadeiramente aleatórios sozinho, certo? O que fazemos é usar mecanismos matemáticos que nos geram sequências de números que parecem aleatórias. É o que chamamos de números pseudoaleatórios.

Na maioria das linguagens temos como criar um "sorteador" de números e fazer uso deles, porque isso nos ajuda muito para simulações computacionais. No nosso contexto isso é importante porque nossos sketches costumam ser simulações de coisas naturais/reais, para interação e arte.

Random no p5.js

Como tudo no Processing, a ideia é facilitar a vida de quem está usando a ferramenta para criar peças artísticas e visuais. Por isso temos uma maneira simples de fazer uso de números pseudoaleatórios no p5.js.

A função que dá números aleatórios no p5.js se chama random . Você pode conferir sua documentação clicando aqui.

Ao chamar a função, você pode passar um número ou um intervalo, fazendo com que se crie um número entre os números pedidos.

random(100) // Um número aleatório entre 0 e 100
random(0, 100) // Um número aleatório entre 0 e 100
random(1, 20) // Um número aleatório entre 1 e 20

Como podemos fazer uso disso em nossos sketches?

Vamos desenhar um círculo no nosso canvas para começar a entender o uso destes números.

let x, y;
function setup() {
    createCanvas(400, 400);
    x = width / 2;
    y = height / 2;
}

function draw() {
    background(245);
    circle(x, y, 100);
}

O que está acontecendo nesse sketch?

  1. Temos duas variáveis importantes, que determinam a posição (x, y) do centro do círculo.

  2. No setup, que executa apenas uma vez, determinamos a posição em que o círculo será desenhado.

  3. Ficamos desenhado o círculo no mesmo local, sem alterar (x, y).

Já que estamos decidindo o ponto do centro do círculo, podemos fazer isso usando números pseudoaleatórios! Vamos alterar um pouco o sketch:

Dessa maneira, nosso sketch agora determinar a posição do círculo uma vez, ao executar o setup. Por isso, cada vez que executarmos o sketch, o círculo é desenhado em um lugar diferente!

Perceba que usamos a função random() diretamente no sketch, é parte dos comandos disponíveis pela biblioteca do p5.js, como circle , line , etc.

Como fazer para que a posição do círculo fique sempre "dentro" do canvas? Precisamos fazer com que o centro do círculo esteja sempre até no máximoo raio do círculo. Pense em um "quadrado interno":

Quais são os valores que queremos sortear? Para x, é entre raio e largura - raio , para y, será entre raio e altura - raio .

Assim, nosso sketch pode ficar dessa maneira:

Veja só! Cada vez que executamos o círculo ainda é desenhado em um lugar aleatório, mas sempre inteiramente dentro do canvas. Quer ver isso melhor? Podemos tirar o background do draw e colocá-lo no setup , colocando a mudança de x e y para dentro do draw. Desse jeito, todo círculo continua no canvas e conseguimos ver que nunca há um desenhado "fora" de lá.

Nossa animação que vai e volta

Vamos colocar um pouco de random no nosso sketch que faz a bola ir e voltar.

Como fazer para que a cor atribuída ao bater nas bordas seja decidida de maneira aleatória?

Random Walk

Para essa seção precisamos usar um comando que ainda não vimos: o point. Uma das funções mais usadas no p5.js é o point . Quando usado ele desenha exatamente o que diz no nome: um ponto. Não é comum começarmos conhecendo o ponto porque fica até difícil de vê-lo desenhado no canvas.

Para aumentar um pouco e melhorar a visualização, podemos usar a função strokeWeight:

Queremos fazer esse ponto andar pela tela. Para começar, podemos criar a mesma "anatomia" do sketch que faz a bolinha andar. Só que ao invés de usar um circle , usamos um point .

Antes de continuar, pare para pensar em como esse sketch vai ser parecer quando for executado. Pense frame a frame.

Uma descrição de como você poderia pensar, lendo o código:

  1. Temos duas variáveis, x e y. Isso significa que vamos controlar a posição do desenho usando esses dois valores

  2. Começamos ambas as variáveis como zero. Ou seja, o que for controlado com isso começará a ser desenhado no ponto (0, 0)

  3. O draw tem a função background . O desenho o tempo todo terá sua "folha" "apagada" por uma cor, nesse caso um branco meio acinzentado, porque só tem um valor sendo passado para a função (que determina escala de cinza).

  4. Atualizamos o x e o y durante o draw , que é executado várias vezes por segundo. Então, em cada frame, o valor de cada um deles vai aumentar em 1. Se começa em (0,0), vai para (1, 1) ,depois (2, 2), (3, 3) e assim por diante.

  5. Desenhamos um ponto usando as coordenadas x e y. Como ambos os valores estão aumentando de maneira igual, o ponto estará se movendo na diagonal... Como o x está aumentando, ele anda para a direita e como o y está aumentando, ele vai para baixo. Logo, vai animar na diagonal da esquerda para a direita, de cima pra baixo.!

Maravilha!

Para ver o "caminho" que o ponto fez, podemos fazer a mesma coisa que fizemos para verificar que os círculos não "saiam" do canvas: jogar o background para dentro do setup.

Nossa! Mas parece que o sketch está desenhando uma linha infinita, não é? Isso é porque estamos desenhando um ponto após o outro, resultando neste efeito.

Como podemos fazer para que esse caminho seja um pouco mais interessante? Vamos usar aleatoriedade!

O que precisamos mudar para que o caminho do ponto seja "aleatório"? Podemos pensar em "parar" o tempo por um instante. O que fazer quando o ponto estiver em um pixel específico?

Cada passo do ponto será decidido entre quatro opções, certo? Podemos fazer isso usando o random !

Mas antes, vamos entender o que essa função nos traz de valores. Pense no seguinte sketch:

Quando executamos, temos alguns valores retornados. Exemplos:

  • 3.14209827372

  • 2.01982737371

  • 1.09128737732

E assim por diante. O fato é que o random nos retorna valores reais entre os que pedimos. Então entre 0 e 4, podem vir muitos números. No nosso caso queremos decidir entre quatro opções. O ideal é conseguirmos fazer algo que nos dê 0, 1, 2 ou 3, por exemplo.

Para isso, podemos usar um comando que tira as casas decimais e pega a parte inteira do número, no javascript: floor . Essa função é baseada no operador matemático chão , que busca a menor parte inteira de um número. Usamos dessa maneira:

Agora temos quatro opções! Podemos pensar da seguinte maneira:

  • Se a opção for 0, aumento o x em 1

  • Se a opção for 1, diminuo o x em 1

  • Se a opção for 2, aumento o y em 1

  • Se a opção for 3, diminuo o y em 1

Como fazer isso virar código no nosso sketch?

Wow! 🎉 Fizemos um ponto ser mostrado e decidir sua direção para cada passo! Esse é nosso primeiro random walker.

Nosso random walker por enquanto decide entre quatro opções. Isso significa que ele ainda não dá um passo na diagonal. Por enquanto ainda estamos só no cenário de quatro possibilidades, mas queremos o de oito.

Como podemos fazê-lo andar na diagonal?

Poderíamos fazer então 8 opções? Já que quatro funcionaram, fazemos as 8 e então consideramos os aumentos de x e y para cada opção.

Ou podemos pensar de maneira mais eficiente. Temos três opções para cada um, certo?

  • No eixo x o ponto pode ficar parado, ir para esquerda ou para a direita. O x pode ser somado com 0 , 1 ou -1 .

  • No eixo y o ponto pode ficar parado, ir para cima ou para a baixo. O y pode ser somado com 0 , 1 ou -1 .

Dessa maneira, poderíamos fazer o seguinte:

Pronto! Assim, em um passo podemos adicionar tanto x quanto y , por exemplo, fazendo o ponto ir para baixo e para a direita, andando na diagonal.

Mas nesse caso poderíamos ir um pouco além. Podemos sair do uso do floor e usar o valor original de random, para obter um número entre -1 e 1, que é o que queremos! Mesmo que seja um valor real (não inteiro), não tem problema, adiciona um pouco mais de aleatoriedade ainda.

Assim, nosso código final de random walker fica:

Parabéns! Você completou nossa seção de números pseudoaleatórios em p5.js!

Desafio

Tente fazer um random walker que tende a ir mais para a direita do que para a esquerda. Como podemos trabalhar com "chances" usando os números aleatórios?

Atualizado