Le processus génératif, retour sur les classes et le temps

Il est parfois utile de revoir ses bases et quoi de mieux qu’une fin d’année pour cela.
Durant cet exercice nous verrons comment réaliser un grand nombres de variations d’une même idée à l’aide du processus génératif.

Cet exercice nous permettra également de revoir les bases suivantes :

  • Création et utilisation des classes
  • Gestion du temps via un timer
  • Utilisation de coordonnées polaires

Définition du sketch 0

Notre skecth 0 sera la base de nos nombreuses variations. Il se traduit par un idée simple autour de laquelle nous pourrons facilement travailler.

Pour cela nous allons nous inspirer du travail de Joshua Nimoy et GMunk réalisé pour le film Tron Legacy et plus précisément l’arrière plan de la scène des « jeux ». Durant cette scène nous pouvons observer des feux d’artifices en arrière plan, ceux-ci présentent toutes les similitudes d’un feu d’artifice normal (étincelles, explosions, physique…) mais ont aussi la particularité d’être géométrique et ceux afin d’accentuer le fait que l’ensemble se passeau cœur d’un programme informatique.
Pour ce faire Joshua Nimoy a travaillé de nombreuses formes tel que les solides de planton comme l’icosaèdre ou le dodécaèdre.

Sur cette même idée nous allons réaliser un « feu d’artifice » géométrique. Notre skecth présentera un élément au comportement simple. Ce dernier effectuera en un temps déterminé un trajet. Lorsque son temps sera écoulé, ce dernier se stoppera et « explosera », laissant apparaître de nouveaux éléments ayant le même comportement et répartis sur un cercle.

expo

Pour réaliser cela nous aurons besoins d’un objet « Point » ayant un comportement défini et un certains nombre de variables.
Nous souhaitons que notre objet effectue un trajet vertical durant un temps donné avant que ce dernier ne s’arrête et « explose » en créant de nouveaux objets identiques à lui même. Enfin, afin que ces nouveaux points soit placés sur un cercle de centre « point explosé » nous aurons besoins de travailler en coordonnées polaires (cf cours trigonométrie).
Notre objet peut se décomposer de la manière suivante :

  • Variables
    • Positions x, y
    • Angle « theta »
    • Rayon « radius »
    • Vitesse du Rayon « vRadius » (cette variable nous permettra de déplacer notre Objet)
    • Valeur booléenne « vie » (Tant que le temps de vie de l’objet sera supérieur à 0 alors son état vie sera vrai)
    • Valeur booléenne « exploded » (Tant que notre objet n’aura pas explosé et engendré de nouveaux objets, alors son état exploded sera faux)
    • Taille « taille » de notre dessin
    • Valeur de margeX et margeY afin de positionner notre dessin sur la scène
    • Un objet Timer permettant de décompter la vie de l’objet
  • Méthodes
    • Methode « run » contrôlant l’ensemble des méthodes de l’objet
    • Methode « UpdateRadius » faisant parcourir ou non un chemin à l’objet en fonction de son état de vie
    • Méthode « displayPoint » affichant une ellipse à la position de l’objet
    • Méthode « displayLine » affichant une ligne depuis l’objet et son origine
  • Constructeur
    • Définitions du rayon, de l’angle et des marges
    • Initialisation des variables

Une fois l’ensemble de éléments composant notre objet défini, nous pouvons concevoir sa classe.
NB : Ici nous utilisons un timer afin de calculer le temps de vie de notre objet. Il ne faudra donc pas oublier d’inclure ce dernier dans notre sketch. Celui-ci est disponible ici

Nous allons désormais définir nos méthodes en commençant par la méthode permettant à notre objet de se mouvoir.
Notre objet possède un temps de vie durant lequel nous souhaitons qu’il se déplace. Lorsque ce temps de vie est épuisé notre objet devra s’arrêter. Pour cela nous allons créer une méthode « updateRadius » interrogeant le timer de notre objet. Il en résultera deux états :

  • Le timer est fini : Alors notre état de vie passe en faux
  • Le timer n’est pas fini : Alors nous incrémentons notre rayons de sa vitesse et mettons à jour les coordonnées de notre objet

Nous réaliserons ensuite deux méthodes permettant de dessiner notre objet ainsi que son parcours

Enfin nous assemblons l’ensemble des ces méthodes dans une méthode contrôleur

Nous venons alors de créer notre classe Point

Nous pouvons donc attaquer la seconde partie de notre sketch permettant d’appeler et afficher nos objets.
Nous savons que nous aurons besoins de dessiner un nombre encore non-défini d’objets Point.
Nous souhaitons aussi que nos objets explosent en créant un certains nombre de point. Nous définirons tout cela dans notre « setup ».

Afin de pouvoir recréer un nouveau « feu d’artifice » quand bon nous semble, nous allons créer un méthode « mousePressed » permettant de vider notre tableau et de re-initialiser nos variables.

Enfin dans notre méthode « draw » nous allons appeler, créer et afficher nos objets. Pour cela nous allons décomposer notre méthode en plusieurs parties

  • Une boucle for() nous permettant de parcourir notre tableau de points et à l’intérieur de laquelle nous effectuerons plusieurs taches
    • Appeler la méthode run() contrôlant nos objets
    • Interroger l’état de vie et d’explosion de notre objet
      • Si notre objet a fini son état de vie (vie == false) et n’a pas explosé (exploded == false) : alors nous créons de nouveaux objets dont l’origine sera la position de l’objet explosant. Enfin nous passerons l’état « exploded » de l’objet explosant en vrai

Si nous effectuons un « run » de notre skecth nous remarquons que nous obtenons l’effet souhaité, cependant notre sketch se met rapidement à ralentir puis se bloque. Cela s’explique par le fait que ce dernier effectue un calcul infini que la mémoire de l’ordinateur ne pourra supporter.

expo-bug

Si nous reprenons notre concept, nous remarquons que notre tableau d’objets augmente de manière exponentielle.
En effet chaque point, une fois sa vie terminée, explose en un nombre de points défini, par exemple 4.
Ainsi à chaque explosion (ou cycle) nous obtenons le calcul suivant : 1^4^4^4^4… soit : 4^nbDeCycle ou : mesPoints.size() = nbNewPts^nbDeCycle

Afin d’éviter à notre sketch de s’étendre à l’infini nous allons donc définir un nombre maximal de cycles auxquel notre tableau de points aura droit. Pour ce faire nous allons devoir compter les cycles de notre tableau, or nous disposons de 2 valeurs dans l’équation suivante : mesPoints.size() = nbNewPts^nbDeCycle soit mesPoints.size() et nbNewPts.

Pour calculer le nombre de cycles de notre tableau nous allons faire appel à une fonction bien pratique en Maths, la fonction logarithme népérien. En effet, en Maths, nous savons que log(a^x) = N ou a^N = x. Cela se note aussi de la manière suivante :
logNeperien

Nous pourrons alors traduire cela dans processing à l’aide des méthodes round() permettant de calculer un nombre arrondi et de la méthode log() permettant de calculer une valeur logarithmique. Ainsi nous aurons :

Il ne nous reste donc plus qu’à reporter cela dans notre sketch et de définir un nombre maximum de cycle pour notre tableau. Enfin dans notre méthode draw nous autorisons nos objets à se créer que si le nombre de cycle actuel n’est pas supérieur au nombre de cycle maximal. Nous rajoutons donc deux nouvelle variables :
cycle et limiteCycle. Notre « draw » se composera alors de la manière suivante :

Nous venons donc de terminer notre sketch 0, base de notre travail génératif.

ixd_processusgeneratif_00

Processus génératif

Nous venons de réaliser notre sketch 0, base de notre travail. Nous allons maintenant nous interroger sur comment réaliser des variations de cette idée. Pour cela rien de plus simple, ils nous suffit de nous interroger sur les variables, méthodes ou dessins que nous pouvons modifier afin de créer de nouveau sketch. C’est la base du processus génératif, prendre une idée et en réaliser de nombreuses variations en cherchant de nouvelles voies. Nous pouvons procéder de différentes manières :

  • En changeant des variables existantes
  • En changeant/rajoutant des comportements
  • en rajouter des objet dans la composition
  • En travaillant le design (composition, couleur, formes…)

Voici quelques pistes permettant des modifications possible afin de réaliser de nouveaux éléments

  • Afficher uniquement les objets points
  • Afficher uniquement les lignes des objets points
  • Dessiner les liaisons entre les objets point lorsque leur distance est inférieur à une valeur définie
  • Changer la forme des objets point
  • Définir une durée de vie aléatoire pour chaque objet
  • Définir une durée de vie aléatoire pour chaque cycle
  • Définir une durée de vie se décrémentant à chaque cycle
  • Définir une durée de vie se s’incrémentant à chaque cycle
  • Définir la vitesse des objet en aléatoire
  • Effectuer une rotation selon un angle défini ou en bruit perlin durant la course de l’objet
  • Positionner les nouveau objet sur un arc de cercle de 180°, 30°….
  • Dessiner en 3D
  • Ne dessiner les objet ou les ligne un cycle sur deux
  • Dessiner uniquement les objet pair et les ligne impaire
  • Incrémenter l’axe Z à chaque cycle
  • Si la durée de vie de l’objet est fini, il explose puis repart dans une autre direction aléatoire ou défini
  • Varier la taille des objets en fonction de leur distance les séparant du centre
  • … à vous de trouver la suite

Il est donc aisé, à partir d’une idée simple, de générer un grand nombre de variation de cette même idée.

L’ensemble des sources des visuels ci-dessus sont à retrouver dans le dossier DigitalLab – Revision sur gitHub

Une réflexion au sujet de « Le processus génératif, retour sur les classes et le temps »

Les commentaires sont fermés.