Emma Paviota – Generative Landscape

OBBIETTIVO VISIVO:

Piccola scena spaziale animata: la Terra posta al centro, la Luna che le gira intorno e un UFO che attraversa il cielo seguendo un’orbita ampia. Tutto è immerso in un campo stellato che si muove leggermente e reagisce al mouse, così da dare la sensazione di profondità e movimento continuo. A ogni click, inoltre, lo sfondo cambia colore scegliendo una tonalità dalla palette blu/viola.

SCOMPOSIZIONE LOGICA:

  1. Background: utilizzo una variabile dedicata che cambia colore a ogni clic del mouse. Il colore viene scelto casualmente da una palette di tonalità blu/viola, così da mantenere un’atmosfera coerente e spaziale.
  2. Campo stellato: nel setup genero 80 stelle, ognuna con posizione e velocità casuali salvate in un array. Nel draw, le stelle si muovono leggermente e reagiscono alla posizione del mouse tramite map(), creando un effetto di parallasse. Quando escono dallo schermo rientrano dal lato opposto, così il cielo rimane sempre pieno e in movimento.
  3. Pianeti e orbite (Funzione Custom): ho creato la funzione drawPlanet(x, y, size, color) per disegnare Terra e Luna in modo modulare. I dettagli come continenti e crateri sono gestiti dalla funzione drawCrateri().Per il movimento orbitale utilizzo la funzione orbit(cx, cy, r, angle), che restituisce un punto su un cerchio. La uso sia per la Luna (che orbita attorno alla Terra) sia per l’UFO (che orbita attorno a un punto esterno alla canvas).
  4. Interattività: cliccando con il mouse, il colore dello sfondo cambia scegliendo una nuova tonalità dalla palette blu/viola. Questo introduce un elemento di controllo da parte dell’utente e rende la scena più viva, senza alterare la composizione generale.

USO AI:

Ho utilizzato Copilot per chiarire alcuni aspetti tecnici legati alla costruzione della scena. In particolare, mi è stato utile per capire come generare un campo stellare stabile, cioè con stelle che non cambiano posizione a ogni frame ma vengono create una sola volta nel setup e poi aggiornate nel draw. Un altro punto su cui l’AI mi ha aiutata è stata la gestione delle orbite: grazie a un confronto ho capito come strutturare una funzione orbit() riutilizzabile per calcolare la posizione di oggetti che si muovono lungo un cerchio.

//dichiaro le variabili
let moonAngle = 0;
let ufoAngle = 0;
let stars = [];
let sfondoColor;
let palette = [‘#000727’, ‘#0A0F5F’, ‘#1B1F8A’, ‘#3A2FA3’, ‘#5A3FBF’, ‘#7A4FE0’, ‘#A06BFF’];

//funzione per disegnare un pianeta generico – terra, luna, marte
function drawPlanet(x, y, size, color) {
noStroke();
fill(color);
ellipseMode(CENTER);
ellipse(x, y, size, size);
}

//funzione per creare i creteri/contineti dei pianeti
function drawCrateri(x,y,w,h,color){
noStroke();
fill(color);
ellipseMode(CENTER);
ellipse(x, y, w, h);

}

//inizializzo il campo stellare creando 80 stelle con posizione e velocità casuali.Ogni stella è rappresentata come un oggetto con coordinate (x, y) e una velocità orizzontale diversa, così da ottenere un movimento vario e naturale. La struttura modulare permette di gestire facilmente la parallasse e l’interazione con il mouse.
function setupStars() {
for (let i = 0; i < 80; i++) {
stars.push({
x: random(width),
y: random(height),
speed: random(0.1, 0.5)
});
}
}

//la funzione aggiorna e disegna tutte le stelle sullo sfondo. Ogni stella si muove secondo la propria velocità naturale e reagisce anche alla posizione del mouse tramite map(). Le stelle che escono dai bordi rientrano dal lato opposto, così da mantenere un flusso continuo e fluido.
function drawStars() {
noStroke();
fill(255);

//creare un movimento controllato dal mouse
let offsetX = map(mouseX, 0, width, -0.5, 0.5);
let offsetY = map(mouseY, 0, height, -0.5, 0.5);

for (let s of stars) {
circle(s.x, s.y, 2);

//movimento naturale + effetto mouse
s.x += s.speed + offsetX;
s.y += offsetY * 0.7; // più morbido in verticale

//stelle ricompaiono da sinistra
if (s.x > width) {
s.x = 0;
s.y = random(height);
}

//stelle ricompaiono da destra
if (s.x < 0) {
s.x = width;
s.y = random(height);
}

//stelle ricompaiono dall’alto
if (s.y < 0) {
s.y = height;
s.x = random(width);
}

//stelle ricompaiono dal basso
if (s.y > height) {
s.y = 0;
s.x = random(width);
}
}
}

//la funzione mi permette di fare orbitare i pianeti intorno ad un punto. per realizzare questa funzione mi sono fatta aiutare da Copilot.
function orbit(centroX, centroY, radius, angle) {
return {
x: centroX + cos(angle) * radius,
y: centroY + sin(angle) * radius
};
}

//definisco la funzione per la quale ad ogni click lo sfondo cambia colore, il colore varia in base alla palette dichiarata precedentemente
function mousePressed() {
sfondoColor = color(random(palette));
}

function setup() {
createCanvas(400, 400);

//specifico che eventuali rotazioni verranno indicate in gradi e non in p greco
angleMode(DEGREES);
setupStars();
sfondoColor = color(‘#000727’);

}

function draw() {
background(sfondoColor);

//costruisco la scena partendo dalle stelle
drawStars();

//creo delle coordinate che si riferiscono al centro della terra per facilitare la ripetizione.
let terraX = width/2;
let terraY = height/2;

//determino la posizione della Luna usando la funzione orbit(), dichiarata prima, che restituisce un punto su un cerchio dato un centro, un raggio e un angolo. il centro dell’orbita coincide con la Terra, mentre il raggio di 120 definisce la distanza costante della Luna. a ogni frame aumento moonAngle di 0.5 per far avanzare la Luna lungo la sua traiettoria in modo fluido.
let moonOrbit = orbit(terraX, terraY, 120, moonAngle);
moonAngle ++;

//per la posizione dell’ufo ho seguito lo stesso ragionamento della Luna, questa volta però il centro coincide con un punto fuori dalla canvas
let ufoOrbit = orbit(terraX, 0, 400, ufoAngle);
ufoAngle += 0.3;

//richiamo la funzione per la creazione dei pianeti
drawPlanet(terraX, terraY, 100, ‘#00AEFF’); // Terra

//richiamo la funzione per la creazione di creteri/continenti
drawCrateri(170,208,24,32,’#009331′);
drawCrateri(200,170,34,27,’#009331′);

//utilizzo push() e pop() per isolare la rotazione
push();
translate(width/2, height/2);
rotate(25);
drawCrateri(29,0,35,55,’#009331′);
pop();

//richiamo la funzione per la creazione dei pianeti
drawPlanet(moonOrbit.x, moonOrbit.y, 38, ‘#D9D9D9’); // Luna

//utilizzo push() e pop() per isolare la rotazione
push();
translate(moonOrbit.x, moonOrbit.y);
rotate(-25);
drawCrateri(-9, 6, 13.4, 14.89, ‘#848484’);
pop();

//utilizzo push() e pop() per isolare la rotazione
push();
translate(moonOrbit.x, moonOrbit.y);
rotate(-25);
drawCrateri(9, -5, 9, 10, ‘#848484’);
pop();

//realizzo l’ufo
push();
translate(ufoOrbit.x, ufoOrbit.y);
noStroke(); //ovale inferiore
fill(‘#A0A0A0’);
ellipse(0, 0, 80, 25);
fill(‘#D0FFFA’); //ovale superiore
ellipse(0, -10, 40, 20);
fill(‘#FFE066’); //luci ufo
ellipse(-25, 8, 10, 10);
ellipse(0, 10, 10, 10);
ellipse(25, 8, 10, 10);

pop();

}

Commenti

Lascia un commento