Étiquette : turtle

Art

Perspective : un paysage Synthwave

Dans le cadre de la 5ème édition du dispositif “Regards de Géomètre”, nous avons décidé dans le thème « Perspective » de produire un paysage synthwave.

Vidéo du projet

Origines de la Synthwave

Avant tout la synthwave est un genre musical électronique ayant émergé dans les années 2000/2010 qui s’inspire d’éléments des années 80. Et c’est justement dans les clips de ces musiques que l’on va retrouver ce type d’image.

Pour en savoir plus nous vous conseillons cette vidéo qui explique brièvement les origines.

Le Projet

Revenons donc au projet. Pour ce projet nous avons donc décidé de produire une image d’un paysage synthwave. Pour cela nous utilisons le module turtle ainsi que le module random, le module turtle est utilisé pour produire l’image est le module random est utilisé pour les étoiles de l’image où la taille et leur position est générée aléatoirement nous avons également utilisé le script permettant d’exporter une image générée par turtle en .png que vous pouvez retrouver ici.

Structure du script

Pour la structure du script nous avons décidé de découper chaque partie de l’image (pavage, fond, étoiles, soleil, ville et montagnes) afin de créer des fonctions et à la fin nous les avons toutes appelées dans un ordre précis pour que les différentes parties de l’image soit dans leur plan respectif.

Analyse du script

Nous allons donc analyser le script.

Commençons par l’appel des modules et la mise en place de turtle.

from turtle import *
from random import randint
# vérification des modules importés
try:
    from PIL import Image
    pillow_installed = True
except:
    print("Oops! - ModuleNotFoundError: No module named 'PIL' - RTFM :")
    print("https://nsi.xyz/py2png")
    pillow_installed = False
titre = "Perspective - Un paysage Synthwave"
title(titre+" | Au lycée, la meilleure spécialité, c'est la spé NSI")
setup(1280, 720) # définit la taille de la fenêtre
colormode(255) # permet l'utilisation de couleurs rgb
speed(0) #Remplaçable par tracer(2) (10x plus rapide) mais si il est utilisé des lignes du pavage peuvent manquer
hideturtle() #dissimule la tortue

On appelle les fonctions turtle, random avec pour random uniquement randint et on utilise une partie du script « exporter une image générée par turtle » pour vérifier que l’utilisateur a bien installé le module PIL et dans le cas contraire un message d’erreur s’affichera et lui donnera un lien pour installer le module et tout ça sans que le script ne s’arrête. Après la vérification on met en place le titre de la fenêtre qui va affiché le rendu ainsi que sa taille. Enfin on définit le type de couleurs utilisées (R,G,B), la vitesse de la tortue, et on dissimule la tortue (c’est plus joli).

Commençons par la première fonction : le fond

def fond():
    penup()
    rciel = 0
    gciel = 0 
    bciel = 0
    hauteur = -360
    goto(-642,-358)
    pendown()
    while hauteur != 360:
        pencolor(round(239 + rciel), round(41 + gciel), round(209 + bciel))
        forward(1280)
        hauteur += 1
        goto(-640, hauteur)
        rciel += (-29/180)
        gciel += (2/45)
        bciel += (7/720)

Pour le fond on aurait pu utiliser une fonction qui crée un rectangle et qui le remplit avec fill_rect, cependant la couleur dans ce cas est uni ce qui ne nous intéresse pas. Nous avons donc produit un script qui fait un fond dégradé qui fait avancer la tortue sur une ligne d’un pixel de large et à la fin de cette ligne la tortue est envoyé grâce à un goto à la ligne d’après et qui ajoute la différence de chaque couleur (rouge,vert et bleu) entre la couleur de début du dégradé et la couleur de fin. Tout ceci est arrondi car turtle n’est pas compatible avec des arguments à virgule (pour la fonction pencolor en tout cas).

Par la suite la fonction qui produit les étoiles a été codée :

def etoile():
    for i in range(90):
        penup()
        goto(randint(-720,720), randint(0,360))
        pendown()
        pencolor(255, 255, 255)
        lcercle = randint(1,3)
        fillcolor('white')
        begin_fill()
        circle(lcercle)
        end_fill()

Pour les étoiles on définit aléatoirement leur position sur la moitié haute de l’image, on les met en blanc, on définit aussi aléatoirement la taille de l’étoile et on créer l’étoile avec sa position, et sa taille en aléatoire puis on refait ce processus 90 fois pour avoir 90 étoiles.

Ensuite nous avons le soleil (Le script affiché n’est qu’une petite partie du script total du soleil car il est très long et qu’il se répète, il est donc inutile de commenter la suite) :

def soleil():
    penup()
    liste1 = [10,7,5,4,3,3,3,3,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,1,2,1,1,1]
    liste2 = [1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0]
    pliste1 = 0
    pliste2 = 0
    rsoleil = 0
    gsoleil = 0
    bsoleil = 0
    lsoleil = 8
    hauteur = 30
    goto(0,30)
    pendown()
    for i in range(15):
        pencolor(round(255 + rsoleil), round(23 + gsoleil), round(226 + bsoleil))
        forward(lsoleil)
        backward(2*lsoleil)
        hauteur += 1
        lsoleil += liste1[pliste1]
        pliste1 += 1
        goto(0, hauteur)
        rsoleil += (0)
        gsoleil += (114/101)
        bsoleil += (-203/202)
    forward(lsoleil)
    backward(2*lsoleil)
    penup()

Pour le soleil nous réutilisons le script du dégradé, cependant nous l’avons modifier pour que le point d’origine de la tortue soit au centre du rectangle et que la longueur de chaque ligne soit défini par une liste (ce qui permet de faire un cercle en prenant les longueur d’un cercle utilisable en pixel art). Pour ce qui est des endroits ou le soleil est coupé la tortue fait le tracé mais on a utilisé la fonction penup() qui fait que la tortue ne dessine plus.

Après nous avons la fonctions des montagnes (Encore une fois le script n’est pas complet car il se répète encore 3 fois après.) :

def montagne():
    #montagne derrière la première
    penup()
    goto(-480,0)
    fillcolor(110, 27, 188)
    begin_fill()
    for i in range(3):
        forward(250)
        left(120)
    end_fill()
    
    goto(-480,0)
    pencolor(51, 210, 246)
    ymontagne = 10
    for i in range(11):
        pendown()
        goto(-355,ymontagne)
        goto(-230,0)
        penup()
        goto(-480,0)
        ymontagne += 20

Pour le script des montagnes nous avons utilisé le script pour faire des triangles équilatéraux retrouvable ici. Et ensuite nous avons utilisé un ‘for i in range’ pour faire des goto enchaîné pour faire les lignes des montagnes.

Ensuite nous avons les fonctions de la ville. Pourquoi les fonctions car il y a une fonction pour chaque bâtiment différent ainsi qu’une fonction finale qui définit l’ordre des bâtiments.

def bat1():
    penup()
    rbat = 0
    gbat = 0 
    bbat = 0
    hauteur = 0
    pendown()
    xturtle, yturtle = pos()
    while hauteur != 72:
        pencolor(round(125 + rbat), round(35 + gbat), round(216 + bbat))
        forward(42)
        hauteur += 1
        goto(xturtle, hauteur)
        rbat += (-5/3)
        gbat += (-7/15)
        bbat += (-72/25)
    forward(42)
    penup()
    right(90)
    forward(72)
    left(90)

Pour le bâtiment 1 il y a un dégradé (toujours le même script) puis on fait que la tortue finisse le bâtiment en bas à droite de ce dernier pour pouvoir enchainer les bâtiments.

fun fact : Au début nous n’avions pas prévu les quelques lignes à la fin pour que la tortue puisse enchaîner les bâtiments sans que les fonctions des bâtiments aient besoin d’être modifiés ce qui nous a amené à avoir tous les bâtiments qui se chevauchaient.

def ville():
    penup()
    goto(-320,0)
    bat3(), bat2(), bat1(), bat4() ,bat3(), bat4(), bat3(), bat2(), bat1(), bat2(), bat1(), bat3(), bat1(), bat4(), bat2(), bat1(), bat3(), bat1(), bat4(), bat3()

Et à la fin on a fait la fonction ville qui appelle dans l’ordre choisi les bâtiments. Le goto permet de définir où commence le premier bâtiment, les autres se mettent juste après le premier sans se chevaucher ni laisser un espace.

Par la suite nous avons le pavage (très long aussi, il sera donc coupé) :

def pavage():
    colormode(255)
    pensize(5)
    speed(0)
    rciel = 0
    gciel = 0 
    bciel = 0
    hauteur = -360
    penup()
    goto(-640,-360)
    pendown()
    while hauteur != 0:
        pencolor(round(15 + rciel), round(4 + gciel), round(76 + bciel))
        forward(1280)
        hauteur += 1
        goto(-640, hauteur)
        rciel += (91/180)
        gciel += (1/36)
        bciel += (7/18)

Pour le début du pavage on retrouve encore le script du dégradé mais avec les couleurs modifiées.

pencolor(229, 123, 240)
    #Lignes au dessus du pavage
    pensize(4),penup(),goto(-640,0),pendown(),goto(640,0),pensize(2),penup(),goto(-640, 0),pendown()
    #lignes gauche
    penup(),goto(-20.00,0),pendown(),goto(-60.00,-360.00),penup(),goto(-60.00,0),pendown(),goto(-180.00,-360.00),penup(),goto(-100.00,0),pendown(),goto(-300.00,-360.00),penup(),goto(-140.00,0),pendown(),goto(-420.00,-360.00),penup(),goto(-180.00,0),pendown(),goto(-540.00,-360.00),penup(),goto(-220.00,0),pendown(),goto(-660.00,-360.00),penup(),goto(-260.00,0),pendown(),goto(-780.00,-360.00),penup(),goto(-300.00,0),pendown(),goto(-900.00,-360.00),penup(),goto(-340.00,0),pendown(),goto(-1020.00,-360.00),penup(),goto(-380.00,0),pendown(),goto(-1140.00,-360.00),penup(),goto(-420.00,0),pendown(),goto(-1260.00,-360.00),penup(),goto(-460.00,0),pendown(),goto(-1380.00,-360.00),penup(),goto(-500.00,0),pendown(),goto(-1500.00,-360.00),penup(),goto(-540.00,0),pendown(),goto(-1620.00,-360.00),penup(),goto(-580.00,0),pendown(),goto(-1740.00,-360.00),penup(),goto(-620.00,0),pendown(),goto(-1760.00,-360.00)
    #lignes droites
    penup(),goto(20,0),pendown(),goto(60.00,-360.00),penup(),goto(60.00,0),pendown(),goto(180.00,-360.00),penup(),goto(100.00,0),pendown(),goto(300.00,-360.00),penup(),goto(140.00,0),pendown(),goto(420.00,-360.00),penup(),goto(180.00,0),pendown(),goto(540.00,-360.00),penup(),goto(220.00,0),pendown(),goto(660.00,-360.00),penup(),goto(260.00,0),pendown(),goto(780.00,-360.00),penup(),goto(300.00,0),pendown(),goto(900.00,-360.00),penup(),goto(340.00,0),pendown(),goto(1020.00,-360.00),penup(),goto(380.00,0),pendown(),goto(1140.00,-360.00),penup(),goto(420.00,0),pendown(),goto(1260.00,-360.00),penup(),goto(460.00,0),pendown(),goto(1380.00,-360.00),penup(),goto(500.00,0),pendown(),goto(1500.00,-360.00),penup(),goto(540.00,0),pendown(),goto(1620.00,-360.00),penup(),goto(580.00,0),pendown(),goto(1740.00,-360.00),penup(),goto(620.00,0),pendown(),goto(1760.00,-360.00)
    #Lignes horizontales
    penup(),goto(-640, -300),pendown(),goto(640, -300),penup(),goto(-640, -240),pendown(),goto(640, -240),penup(),goto(-640, -190),pendown(),goto(640, -190),penup(),goto(-640, -140),pendown(),goto(640, -140),penup(),goto(-640, -100),pendown(),goto(640, -100),penup(),goto(-640, -70),pendown(),goto(640, -70),penup(),goto(-640, -40),pendown(),goto(640, -40),penup(),goto(-640, -15),pendown(),goto(640, -15),

On a par la suite énormément de goto afin de faire le quadrillage du pavage.

Pour produire l’image finale nous avons les appels des différents fonctions à la fin :

#appel de toutes les fonctions
fond(), etoile(), soleil(), montagne(), ville(), pavage()

Et pour exporter l’image finale en .png il y a la suite du script pour exporter une image générée par turtle en .png utilisé au début du script.

#enregistrement de l'image finale avec vérification des modules importés
image = getcanvas()
nom_du_fichier_sans_extension=titre+"_"+hex(randint(2**30+2**25,2**30+2**25+2**24-1))[2:]
image.postscript(file=nom_du_fichier_sans_extension+".ps", colormode='color')
try:
    psimage = Image.open(nom_du_fichier_sans_extension+".ps")
    psimage.load(scale=2)
    psimage_resized = psimage.resize((1280, 720))
    psimage.save(nom_du_fichier_sans_extension+".png")
    print(nom_du_fichier_sans_extension+".png", psimage.size, "sauvegardé dans le dossier")    
except:
    if not pillow_installed:
        print("Oops! - ModuleNotFoundError: No module named 'PIL' - RTFM :")
        print("https://nsi.xyz/py2png")
    else:
        print("Oops! - 'ghostscript' not installed- RTFM :")
        print("https://nsi.xyz/py2png")
exitonclick()

Le script va donc générer une image en .ps et la convertir en .png avec un nom généré aléatoirement pour éviter que à chaque fois que vous générez une image l’image soit écrasée

Télécharger le .py

L’image finale

Art

Astronomie : Un semblant de liberté

« C’est dur, oui, il a tant cherché sa place dans l’univers : société, nature sauvage, vie luxueuse,… mais rien de tout ça ne lui convenait. Se tournant vers le ciel, c’était peut-être parmi les étoiles que se trouvait sa place… »


Introduction

À l’aide du module Turtle, on va pouvoir créer une image en python, animée ou non.
Aujourd’hui, ce sera alors plutôt un dessin que nous générerons par notre code, de plus, celle-ci sera différente à chaque exécution !
Nous allons alors décortiquer des parties de celui-ci afin de le comprendre, si ce n’est pas déjà le cas ! 😉


Une mise en bouche qui nous prépare

colormode(255)
color(5,9,44)
goto(-640,0)
pensize(1000)
forward(1000)

Ce bloc de code permet de préparer le dessin en y installant un fond bleu nuit rappelant l’espace.
La couleur est définie dans les 2 premières lignes, ensuite on se rend à des coordonnées hors du champ de vision puis on trace un trait très épais.


Des fonctions par-ci, des fonctions par-là

def etoile():
    pensize(2)
    couleur = randint(0,3)
    if couleur == 0:
        color(250, 137, 25)
    else:
        color(247,247,36)
    for _ in range(5):
        forward(10)
        right(144)

Le bloc de code suivant est une fonction, elle nous permet de définir une suite d’instructions qu’on peut utiliser par la suite.
Elle dessine une étoile tout en utilisant un autre module permettant d’utiliser l’aléatoire, à l’aide de celui-ci et de structure conditionnelles, on choisit aléatoirement entre 2 couleurs pour l’étoile.
Puis, on la trace à l’aide d’une boucle bornée. 😵

def position_aleatoire():
    penup()
    x = randint(-640,640)
    y = randint(-320,320)
    goto(x,y)
    pendown()

Cette seconde fonction diffère de la 1ère par son utilité-même : elle permet de choisir une position aléatoire.
La fonction génère aléatoirement des coordonnées dans un intervalle défini, ici, celle de la fenêtre puis elle s’y rend.

for _ in range(42):
    position_aleatoire()
    type_etoile = randint(0,2)
    if type_etoile == 0:
        etoile_2()
    else:
        etoile()

C’est alors que la magie entre en scène, on manipule les fonctions précédemment créées afin de produire un splendide ciel étoilé !
On se rend à un endroit aléatoire grâce à la 2ème fonction puis on dessine une étoile grâce à la 1ère fonction (et une autre produisant un autre type d’étoile), et ceci 42 fois !! 😱


Des éléments de décoration


D’autres éléments constituant l’image proviennent de fonctions, prenons ici l’exemple de la fusée :

def fusee():
    left(55)
    penup()
    goto(-100,-40)
    pendown()
    corps_fusee()
    for i in range(2):
        penup()
        goto(-125+i*275/100*25,-50-i*5/2*20)
        pendown()
        moteur()
    for i in range(2):
        penup()
        goto(-15+i*35*135/100,-65/2+i*50*135/100)
        pendown()
        hublot()
    right(30)
    penup()
    goto(15,125)
    pendown()
    toit()


On peut voir une différence notable avec les fonctions précédentes, cette fonction est elle-même constituée de fonctions : « corps_fusee » ; « moteur » ; « hublot » et « toit ».
Et comme dit plus tôt, on utilise et manipule ces fonctions, par exemple en les utilisant plusieurs fois dans une boucle, en définissant un angle au préalable,… et ça ne s’arrête pas là ! on pourrait très bien utiliser la fonction définissant la fusée afin de lui donner une autre utilité !

C’est alors en usant de fonctions, de boucles et de structures conditionnelles qu’on peut facilement produire une œuvre avec le module Turtle, mais tout cela ne peut se réaliser qu’avec de la pratique, car comme j’ai dit : « C’est en programmant que l’on devient programmeur ».

L’image finale

Télécharger le .py

Art

Musique : Pink Floyd et son album lumineux

Le choix de la pochette d’album « The Dark Side of the Moon » n’a, d’après les membres du groupe, pas de signification précise. Lassés des photographies chargées ou des collages compliqués, ceux-ci cherchaient un visuel simple et facile à retenir. C’est bien le cas puisque 50 ans après, l’image du spectre lumineux se dispersant à travers un prisme est presque toujours associée au groupe Pink Floyd.

Vidéo de présentation du projet

De la physique à la musique

Lors du feuilletage d’un manuel de physique, l’attention du graphiste des Pink Floyd a été retenue par une photographie en noir et blanc d’un prisme à travers lequel se dispersait la lumière. L’idée lui est alors venue de choisir cette image en guise de pochette d’album.

En physique, un spectre lumineux est le résultat de la décomposition de la lumière par un spectroscope. Il permet d’analyser celle ci grâce aux radiations qui la composent.

Cette image n’est pas sans rappeler les éclairages des concerts où des faisceaux lumineux traversent la scène en se modifiant au contact des musiciens, tel le spectre traversant le prisme.

De la musique à la NSI

Nous avons donc décidé de récréer numériquement cette pochette d’album. Pour ce faire, nous avons utilisé le langage python et l’émulateur Thonny.

Tout d’abord, nous avons instauré le fond de couleur noir en utilisant la fonction bgcolor().

Nous avons ensuite tracé le triangle principal en veillant à le placer au centre. Pour cela, nous avons mis pour point d’abscisse de départ la valeur « -100 » afin que la longueur du triangle soit de « 200 ».

Puis, nous nous sommes penchés sur la partie gauche de notre image en commençant par tirer un trait défini par ses points de coordonnées de départ et d’arrivée.

Effet dégradé à l’intérieur du triangle :

Vient ensuite une partie plus complexe : l’élargissement du trait en dégradé, partant de la couleur initiale du trait pour aller vers le noir de l’arrière plan.

Pour cela, le script effectue des traits en allers-retours (grâce à une boucle for), d’un point défini sur le triangle jusqu’au milieu du triangle. Pour chaque trait, l’opacité (a) diminue au fur et à mesure que le trait se rapproche du milieu du triangle. L’opacité est remise à sa valeur initiale (a=255) avant chaque traçage de trait.

turtle.colormode(255)
for i in range(20):
    penup()
    a = 255
    go to(-40, 100)
    for i in range(41):
        turtle.color(a,a,a)
        pendown()
        turtle.forward(1)
        a += -6
    turtle.right(1)

Et voici le résultat:

Réalisation du triangle et du faisceaux lumineux entrant

Création de l’arc en ciel :

Ensuite, en partant d’un point situé sur la bordure droite du triangle, nous avons créé une boucle for permettant de réaliser les traits de couleur à droite, définis par une liste. Pour que les couleurs attendus soient identiques à celle de la pochette d’album originale, nous avons trouvé leur équivalent en hexadécimal grâce au site « Image Color Picker ».

liste = ["#6f597a","#3476b2","#78ab23", "#f9fc49","#e8b30d","#de2b05",]
goto(63 - 10/6, 81)
turtle.right(12)
turtle.pensize(10)
s=5
for i in range(6):
    turtle.color(liste[i%6])
    pendown()
    turtle.forward(355 + 0.1*i)
    penup()
    goto(58 - 10/6*i, 80 + s + 4*i)
    turtle.left(1)
    s+=-1
Script initial avec ajout de l’arc en ciel

Enfin, nous avons reproduit les commandes de lecture, situées dans la partie inferieure de notre rendu visuel, en utilisant encore une fois des boucles for pour créer des formes géométriques telles que des rectangles ou des triangles.

Afin de créer un effet visuel plus esthétique nous avons aussi intégré les fonctions begin_fill() et end_fill() qui permettent de colorer l’intérieur de formes géométriques telles que le « bouton pause » par exemple.

Nous vous proposons la découverte de notre rendu final ci-dessous, j’espère qu’il vous plaira!

Rendu final du script après exécution

Télécharger le .py :

Pour finir, nous vous partageons l’intégralité de notre projet afin que vous puissiez le découvrir plus en détail !

Art

Astronomie : Le Seigneur des Anneaux … d’Uranus

Dans cet article, nous allons vous présenter notre projet sur Uranus, la septième planète du système solaire, que nous avons réalisée grâce au module turtle de python. Pour rédiger le script, nous avons notamment utilisé des fonctions, boucles et instructions conditionnelles.

Présentation et début du projet

La réalisation de ce projet s’inscrit dans le cadre de la 5ème édition du dispositif « Regard de géomètre ». Nos enseignants nous ont donc demandé de réaliser un script en python sur un thème parmi plusieurs qu’ils avaient sélectionnés. Nous avons choisi de faire notre projet sur le thème « Astronomie » car celui-ci nous a aussitôt inspirés. De plus, nous avons une passion commune pour l’astronomie. L’idée nous est donc venue de dessiner la planète Uranus ainsi que ses anneaux (eh oui Uranus possède des anneaux même si ceux-ci sont beaucoup moins imposants que ceux de Saturne 😁) grâce au module turtle de python.

  • Mais avant de coder Uranus, nous avons voulu rajouter un fond noir (le fond d’écran est blanc par défaut) pour symboliser l’espace. Afin de réaliser le fond noir, nous avons augmenté la taille du stylo grace à la fonction pensize() donc en le mettant à une taille égale à 10000. Ensuite nous avons choisi les coordonnées (x, y) du point vers lequel doit se déplacer la tortue (stylo = tortue) : on utilise donc goto(x, y). De plus, il est inutile de préciser la couleur puisque dans ce cas la couleur par défaut est le noir soit exactement la couleur que nous souhaitons obtenir. Enfin, une fois le fond noir réalisé, on réduit la taille du stylo pour que celui-ci ne soit pas trop grand lors de l’exécutions des fonctions suivantes.
  • Ce qui donne le code suivant :
pensize(10000)
goto(100,1)
pensize(5)
  • Ensuite, une fois que le fond noir est codé, il faut passer à la planète Uranus.
  • Dans un premier temps, nous décidons de la dessiner à l’aide de disques dont on augmentera le rayon successivement avec la boucle for i in range(). Mais, chaque fois qu’un disque apparaîtra, il effacera le précédent. Cela n’aurait guère d’importance si nous n’avions pas eu l’idée de faire des disques de couleurs différentes. Ainsi, la couleur finale d’Uranus est celle du dernier disque formé et la planète n’en est pas vraiment une.
  • Nous nous sommes donc rabattus sur les cercles afin de réaliser Uranus. Puis, à force de réfléchir sur le problème et avec un peu de recul, nous avons décidé de partir d’un cercle de rayon 0 puis d’augmenter ce rayon de la valeur de la variable t. En répétant cette action un grand nombre de fois (ici 220 fois) et en faisant en même temps un dégradé de couleur (en réduisant ou en augmentant les valeurs du Rouge et/ou du Vert et/ou du Bleu du code RVB de la couleur initiale par t) on obtient Uranus !
  • Le code python ci-dessous est l’application de ce que nous venons de dire précédemment. Nous allons cependant préciser quelques éléments :
    • Pour définir la fonction uranus, on doit rentrer la valeur du rayon, des coordonnées x et y du point de départ ainsi que définir la couleur du cercle.
    • Ces éléments sont définis après dans la boucle for t in range(220), ainsi que la valeur de la variable t, avant de les définir. Cela permet à la fonction de tracer des cercles de rayons de plus en plus grands.
    • Les éléments présents en dessous de def uranus permettent de positionner la tortue de façon à tracer un cercle.
    • Si vous souhaitez changer la couleur de la planète, vous avez la possibilité de faire un dégradé bleu en remplaçant les valeurs de color = (254 - t, 12 + t, 1 + t) par : color = (40, 221-t, 255).
def uranus(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    circle(rayon)

t = 1
for t in range(220):
    x, y = 50,-200
    radius = 0 + t
    color = (254 - t, 12 + t, 1 + t)
    uranus(radius, x, y, color)

Et voici le résultat (fond noir + fonction uranus) :

Améliorations du projet

Une fois la planète obtenue sur fond noir nous contemplons de manière enthousiaste notre travail. Mais il nous reste toujours les anneaux à faire ! Et c’est là que ça se complique.

  • Pour les anneaux, nous pensions tout d’abord à les faire avec des cercles. Après plusieurs tentatives, il faut se rendre à l’évidence : les anneaux avec les cercles ça ne marche pas ! C’est à ce moment-là que l’un d’entre nous se souvient de la présence, sur la calculatrice NumWorks, dans la rubrique « Fonction », d’une fonction appelée « conique » qui trace des ellipses. La forme de l’ellipse nous semblant similaire à celle des anneaux, nous décidons donc de tracer des ellipses pour les anneaux. Comme nous ne savons pas comment coder une ellipse avec le module turtle de python, nous faisons une recherche sur Internet. Nous tombons alors sur une fonction très simple permettant de tracer une ellipse. Nous l’ajoutons alors au script.
  • Puis, nous remanions le script trouvé sur Internet en reprenant les mêmes principes utilisés précédemment dans la fonction uranus c’est-à-dire en augmentant progressivement la taille du rayon et en faisant un dégradé de couleurs. Pour définir la couleur, nous avons utilisé pencolor() afin que la couleur des anneaux soit autre que noir. Puis nous avons aussi rajouté pensize(5) avant for j in range(30) pour augmenter la taille du tracé. Enfin nous avons changé la valeur de seth() afin que les anneaux soient inclinés vers le bas droit de l’image, ainsi que la valeur de la fonction anneaux() dans le but que ceux-ci soient assez grands pour que la planète se situe bien au milieu.
  • Et comme d’habitude ne pas oublier de définir la variable avant son utilisation (sinon ça ne marche pas😉). Ci-dessous le code python des anneaux ainsi qu’Uranus + ses anneaux.
# Source: https://stacklima.com/dessiner-une-ellipse-a-laide-de-turtle-en-python/
j = 1
def anneaux(rad):
  pensize(5)
  for j in range(30):
    pencolor(255- 5*j, 255- 5*j, 255- 5*j)
    circle(rad + j,90)
    circle(rad//2 + j,90)

seth(-80) 
anneaux(290)

Arrivés à ce stade-là, on aurait pu arrêter. On avait la planète Uranus, ses anneaux et le fond noir. Mais l’image semblait un peu vide, on a donc eu l’idée de rajouter quelque chose en fond d’écran : des étoiles.

  • Pour dessiner les étoiles, c’est assez facile. Si on veut dessiner une étoile à 5 branches on peut dessiner une partie de l’étoile et répéter cette action cinq fois. Tout ceci en utilisant (encore) une fonction, dans laquelle on doit définir la longueur d’un trait, les coordonnées (x, y) du point de départ ainsi que la couleur de l’étoile. Avant de coder la fonction on met la taille du stylo à 5 avec pensize(5) pour remplir l’interieur de l’étoile (il est inutile de le préciser avant puisqu’on l’a déjà mis dans le code du fond noir qui est situé avant la fonction etoiles). On choisit aussi de préférence une longueur assez basse (mais pas trop quand même). 4 est un bon chiffre par exemple.
  • La boucle for i in range(5) permet de dessiner 5 fois deux demi-branches d’étoiles pour obtenir une étoile (il faut faire attention aux mesures d’angles et si l’on tourne à droite ou à gauche). La boucle for i range(210) permet de dessiner 210 étoiles. Dans cette boucle, on définit les coordonnées (x, y) ainsi que la couleur de l’étoile grâce au module randint. Celui-ci permet, pour chaque étoile, de définir des coordonnées aléatoires comprises entre -800 et 800 pour x et -400 et 400 pour y. C’est le même principe pour les couleurs à part que l’on a réduit l’écart entre les nombres pour obtenir comme couleur (toujours de manière aléatoire) du jaune, de l’orange ou des couleurs s’en rapprochant de très près.

Le code python des étoiles :

def etoiles(longueur, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    for i in range(5):
        forward(longueur)
        left(74.2)
        forward(longueur)
        right(146)

for i in range(210):
    x, y = randint(-800, 800), randint(-400, 400)
    longueur = 4
    color = (randint(247, 255), randint(127, 255), randint(0, 12)) 
    etoiles(longueur, x, y, color)

Et le résultat :

Finalisation du projet

Enfin, nous avons pensé à rajouter le plus grand satellite naturel d’Uranus, Titania (à ne pas confondre avec Titan qui lui est le plus grand satellite naturel de Saturne).

  • On s’est dit que rajouter un petit détail supplémentaire pourrait être intéressant. On a tout de suite pensé à rajouter son plus grand satellite naturel. Pour le faire, on a utilisé le même procédé que pour Uranus, à savoir des cercles qui augmentent progressivement de rayon et un dégradé de couleurs. Mais cette fois-ci, pour plus d’originalité, nous avons utilisé des instructions conditionnelles pour faire le dégradé de couleur en fonction de la taille des cercles.
  • On utilise une boucle while cette fois-ci (on aurait pu aussi utiliser une boucle for comme dans les autres fonctions et vice versa). Ici on prend radius (le rayon du cercle) comme variable puis on l’augmente de 1 (avec +=) jusqu’à ce que radius soit égal à 30 : le principe reste donc le même qu’avec une boucle for.
  • Puis, dans la boucle while, on utilise des instructions conditionnelles afin que les cercles soit d’une certaine couleur en fonction de leur taille. Ainsi, la première condition (if) s’applique aux cercles dont le rayon est inférieur ou égal à 28 et dont la couleur sera du marron très clair. La deuxième condition (elif) concerne les cercles ayant un rayon compris entre 28 (non inclus) et 29 (inclus) : la couleur du cercle sera marron clair. A noter que l’on aurait pu remplacer elif radius > 28 and radius <= 29: par elif radius == 29: . Enfin, la troisième et dernière condition (else) concerne tous les cercles dont le rayon va jusqu’à 30 (mais ne concerne pas ceux des précédentes conditions), qui auront donc un couleur marron.
  • Le code et l’image obtenus :
def titania(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    circle(rayon)
    
x, y = -200, 100
radius = 0
while radius <= 30:
    radius += 1
    if radius <= 28:
        color = (167-2, 103-2, 38-1)
    elif radius > 28 and radius <= 29:
        color = (136-2, 66-2, 29)   
    else :
        color = (91-2, 60-2, 17)
    titania(radius, x, y, color)

Au cours de la rédaction de notre script python, nous avons rencontré différents problèmes que nous avons essayé de résoudre.

  • Le problème majeur que nous avons rencontré est le décalage des anneaux et de la planète sur l’image quand d’autres fonctions étaient exécutées avant. De plus, comme la même variable i était utilisée pour chaque fonction cela créait des confusions de même que le positionnement des objets sur l’image. Nous avons donc changé le nom des variables afin que chacune est un nom différent (i, j, t et radius) ce qui explique le nom des variables précédentes. Nous avons aussi ajouté les lignes suivantes entre chaque fonction afin d’éviter toutes confusions et pour remettre les fonctions à jour :
penup()
goto(0,0)
pendown()
  • Nous avons aussi eu des problèmes avec la fonction titania, notamment avec le cercle marron qui se décalait trop vers le haut. Nous avons donc réduit l’intervalle dans lequel il était appliqué pour supprimer ce décalage. Nous avons rencontré d’autres problèmes minimes et sans importance notamment sur les valeurs et la précision de celles-ci, qui peuvent faire varier le rendu.

L’image finale

Voici donc le résultat final ci-dessous une fois que tous les éléments ont été assemblés et les problèmes réglés :

Télécharger le .py

Si vous désirez le télécharger (il en format compressé il faudra donc le décompresser😉). Le script contient un code python permettant de générer une image ainsi que les fonctions permettant de dessiner le fond noir, les étoiles, les anneaux, Uranus et Titania (dans l’ordre) :

Art

Astronomie : La carte du ciel

Depuis la nuit des temps, l’Homme est fasciné par ce qu’il se trouve au-dessus de sa tête à tel point qu’il a créé des cartes pour répertorier ces astres lumineux. Cette fascination pour l’inconnu a perduré au fil des siècles et, grâce aux cartes du ciel, les aventuriers d’hier, d’aujourd’hui et de demain on réussit à se repérer dans l’espace et surtout à rêver comme nous le montre James Michener dans La course aux étoiles.

-Prisonnier ?
-Oui. Les étoiles peu à peu vous happent. Elles vous font changer de perspective, d’une façon radical
Il lui tendit la carte avec respect et lui demanda :
« Avez-vous jamais vus les étoiles ? »

La course aux étoiles, p. 76

Genèse de l’idée

Lors de l’explication du projet, nous avons réfléchi et nous avons tout de suite pensé au domaine de l’astronomie. Au début nous avons pensé que faire une représentation en Pixel Art serait une bonne idée mais après de longues réflexions nous sommes revenus aux bases de l’astronomie et nous avons eu notre idée actuelle ; une carte du ciel de l’hémisphère Nord. C’est ainsi que notre projet a pu débuter…

Développement

Pour commencer nous avions besoin d’un fond dégradé du bleu au noir pour représenter notre beau ciel étoilé. De ce fait nous avons dû chercher comment le réaliser et nous avons trouvé un exemple de code sur Internet et nous avons pu l’adapter à notre manière.

Fond dégradé issu de notre script

Une fois le fond terminé et opérationnel, nous nous sommes concentrés sur la création des étoiles qui composeront notre carte. Ainsi, nous avons défini 3 types d’étoiles :

Les petites étoiles :

def etoilep():
    pensize(1)
    pencolor("white")
    for i in range(150):
        penup()
        x,y = randint(-640,640), randint(-360,360)
        goto(x,y)
        pendown()
        circle(1)


Nous avons positionné les petites étoiles de façon aléatoire grâce à un module python nommé random permettant un meilleur rendu visuel puisqu’elles servent à définir les étoiles les plus lointaines et donc visibles seulement par la NASA, l’ESA et également visibles dans les films de science-fiction tel H2G2.

Les étoiles moyennes :

def etoilen():
    pendown()
    pensize(2)
    pencolor("yellow")
    for i in range(5):
        right(30)
        forward(2)
        right(120)
        forward(2)
        left(78)

Celles-ci servent à constituer les étoiles formant les constellations visibles dans notre hémisphère et donc forment les différentes constellations.

L’étoile polaire :

def etoilepolaire():
    pendown()
    pensize(2)
    pencolor("yellow")
    for i in range(5):
        right(30)
        forward(2)
        right(120)
        forward(2)
        left(78)

L’étoile polaire est une étoile particulière. En effet, sa position dans l’espace ne varie pas et indique globalement le nord. Elle servait notamment aux marins pour se repérer en pleine mer. C’est pour ça que nous l’avons défini aux coordonnées (0 , 0).

Rendu final du script après exécution

Maintenant que nous avons toutes nos étoiles, il faut les positionner !

Donc, pour ce faire, nous avons utilisé une carte du ciel en notre possession et nous avons mesuré à la règle la distance des étoiles par rapport à l’étoile polaire en essayant de les mettre à une certaine échelle pour ne pas sortir du cadre imposé.

Une fois toutes les mesures prises, nous avons créé deux listes, une première avec toutes les coordonnées x (horizontales) et une deuxième avec tous les coordonnés y (verticales) des étoiles formant les constellations. Pour séparer les constellations entre elles nous avons utilisé le mot-clé « None » .

Cependant, celui-ci nous a posé quelques problèmes. En effet, nous avions tout d’abord mis les « None » entre parenthèses (ne nous demandez pas pourquoi on a fait ça, on ne le sait pas nous-mêmes), ce qui nous a posé des problèmes. Après s’être rendu compte de cette erreur, un autre problème est apparu ! Mais nous avons pu la parer puisqu’il suffisait de mettre une condition à ce « None » . S’il apparait on passe au nombre suivant de la liste et s’il n’y est pas on trace !

En parlant de problèmes, nous en avons eu un autre, l’échelle des constellations. En effet, nous nous y sommes pris à trois fois pour avoir la bonne taille, d’abord trop petite, ensuite trop grande, mais à coups mathématiques très compliqués, nous avons réussi à trouver la bonne échelle !

Conclusion

Malgré les quelques difficultés rencontrées nous avons réussi à modéliser, assez grossièrement, nous devons l’admettre, une carte du ciel. Néanmoins, cette esquisse ravira sans aucun doute les amateurs d’astronomie pour sa beauté graphique et les informations données, malgré son imprécision elle reste tout de même assez juste et véridique. Notre projet se prête bien au thème de l’astronomie et nous en sommes fières. Cependant , il peut bien évidemment être amélioré avec un script plus optimisé et un peu plus de constellations.

Et puis, comme disait Léonard de VinciCelui qui s’oriente sur l’étoile ne se retourne pas.

Télécharger le .py

L’image finale

Art

Astronomie : L’amas de trous noirs

« L’amas de trous noirs » est le nom de notre premier projet développé en Python. Notre petit programme vous permettra de profiter d’un magnifique ciel étoilé… avec quelques trous noirs. En effet, ce programme générera pour vous une image d’une beauté à couper le souffle… Enfin, nous espérons !

Introduction

Représenter ce que l’être humain ne peut atteindre est une de ses passions favorites. En effet, nous allons vous présenter notre projet Python se prénommant : L’amas de trous noirs. Effrayant, n’est-ce pas ?

Le résultat final doit ressembler à ceci, mais vous le savez déjà :

Cette image est un des multiples résultats de notre code. Nous y reviendrons plus tard.

Comme vous pouvez le voir, il y a plusieurs éléments sur cette image : des trous noirs, des étoiles et un arrière-plan noir. Commençons par le programme pour former les trous noirs.

Nous avons utilisé le module turtle de python qui permet de dessiner à l’écran. Dans la suite de l’article, nous ferons référence à ce module sous le nom de tortue.

Les trous noirs

Un code non optimisé

C’est la première chose sur laquelle nous avons travaillé. Afin que vous conserviez votre santé mental, nous éviterons de vous montrer le code qui forme cette image :

Si vous le voulez vraiment :

def cercle(rayon, x, y, r=1, v=1, b=1):
    pensize(5)
    while rayon > 372 and r < 254:
        penup()
        goto(x, y - rayon)
        pendown()
        pencolor((r, v, b))
        circle(rayon)
        rayon -= 1
        r += 2
    while rayon > 244 and v < 254:
        penup()
        goto(x, y - rayon)
        pendown()
        pencolor((r, v, b))
        circle(rayon)
        rayon -= 1
        v += 2
    while rayon > 119 and b < 254:
        penup()
        goto(x, y - rayon)
        pendown()
        pencolor((r, v, b))
        circle(rayon)
        rayon -= 1
        b += 2
    while r > 0 and v > 0 and b > 0:
        penup()
        goto(x, y - rayon)
        pendown()
        pensize(2)
        pencolor((r, v, b))
        circle(rayon)
        rayon -= 1
        b -= 16
        v -= 16
        r -= 16


cercle(500, 0, 0)

Ce code ne nous satisfait pas car il a des limites d’utilisations. C’est-à-dire qu’il est impossible de dessiner des trous noirs de n’importe quel diamètre. On a par exemple ce cas où l’on choisi un rayon de 200 :

Ici, on constate que le dégradé n’est pas celui que l’on souhaitait.

Maintenant que nous avons vu un code qui vous pique encore les yeux, nous allons voir une autre version plus optimisée et bien plus flexible.

Un code optimisé

Avant toute chose, nous définissons au début de notre programme colormode(255) qui nous permettra de définir des couleurs au format (r, v, b), r pour rouge, v pour vert et b pour bleu qui sont les trois teintes permettant de composer n’importe quelle couleur.

Ensuite nous définissons notre fonction trou_noir(). Nous allons la découper en plusieurs portions de code afin de vous l’expliquer étape par étape.

  • Première étape : Initialisation de diverses informations.
colormode(255)

def trou_noir(x, y, rayon):
    color(0, 0, 0)
    pensize(5)
    r = -1
    v = -1
    b = -1
    penup()
    goto(x, y - rayon - 20)
    pendown()

Notre fonction aura donc besoin de trois paramètres : les coordonnées x, y et le rayon du trou noir. Nous indiquons que la couleur du stylo sera noir, en raison de l’arrière-plan qui sera noir également. Nous définissons le taille du trait à 5, qui est la valeur la plus basse tout en évitant des artéfacts au niveau du trou noir comme ceci :

Nous définissons trois variables qui, comme leur nom l’indique, seront les variables liées au changement de couleur. Nous les définissons avec une valeur négative, ce qui peut paraitre assez étrange, car les valeurs minimales pour le vert, le rouge ou le bleu sont zéro. Nous vous expliquerons un peu plus bas pourquoi nous faisons cela.

La fonction penup() permet de lever le stylo, la fonction goto() permet de le déplacer. On met en paramètre les coordonnées x et y en paramètre. La fonction pendown() permet elle, de poser le stylo.

Concernant la fonction goto(), elle prend en paramètre les coordonnées x et y, qui représente un point de l’écran. La tortue n’est capable de dessiner un cercle qu’à partir de sa base (le point le plus bas du cercle). Nous souhaitons utiliser le centre géométrique d’un cercle pour les positionner. Nous allons donc décaler la coordonnée y de la distance du rayon. Cela donne le code suivant : goto(x, y - rayon).

Nous avons choisi d’ajouter autour de notre trou noir une zone noire (🥴) de 20 pixels d’épaisseur (cette valeur a été défini de façon arbitraire). Nous verrons par la suite que c’est un choix esthétique, cette marge de 20 pixels se retrouve donc dans l’appel de notre fonction goto() : goto(x, y - rayon - 20).

  • Deuxième étape : Création d’un disque noir.
	begin_fill()
    fillcolor("black")
    circle(rayon + 20)
    end_fill()

Ce disque a été rajouté afin d’améliorer la fonction trou_noir() : en effet, après une première version de la fonction trou noir, nous avons amélioré le rendu graphique en dessinant un premier disque noir sur lequel la tortue dessine le trou noir. Cela apporte deux avantages : produire la marge de 20 pixels autour du trou noir (cf. paragraphe au-dessus) et remplir le centre de notre trou noir. Voyez ainsi :

Ce disque noir sert de transition entre le ciel étoilé (que vous verrons par la suite) et le trou noir en lui-même.

  • Troisième étape : Construction du trou noir (dégradé du rouge vers le blanc).
    while r < 255:
        penup()
        goto(x, y - rayon)
        pendown()
        r += 2
        pencolor((r, 0, 0))
        circle(rayon)
        rayon -= rayon/500

    while v < 255:
        penup()
        goto(x, y - rayon)
        pendown()
        v += 2
        pencolor((r, v, 0))
        circle(rayon)
        rayon -= rayon/500

    while b < 255:
        penup()
        goto(x, y - rayon)
        pendown()
        b += 2
        pencolor((r, v, b))
        circle(rayon)
        rayon -= rayon/500

Ces trois boucles while sont très similaires. Elles servent à créer le dégradé du trou noir. Ce que notre tortue fait est de dessiner un cercle d’une couleur différente à chaque fois que la boucle se répète. La boucle se termine une fois que la variable de la couleur donnée dans la condition while a atteint son maximum, soit 255. A chaque itération, nous incrémentons de 2 chaque variable de couleur, et nous le faisons juste avant de dessiner le cercle. Avec cette incrémentation, il nous faudrait 128 itérations pour arriver à la valeur 256. Cette valeur est donc supérieur à 255, nous avons donc décidé d’initialiser chaque variable de couleur à -1 afin de compenser ce problème. Pour la variable r par exemple, la première fois que notre boucle va s’exécuter, elle va s’incrémenter de 2 ( -1 + 2 = 1 ), puis choisir une couleur pour le stylo : pencolor((r, 0, 0)), puis dessiner le cercle. Lors de la dernière itération, r est égal à 253, donc 253 + 2 = 255, la tortue dessine le cercle avec cette valeur. Nous sortirons ensuite de la boucle. Nous faisons ceci trois fois, pour les trois variables de couleurs.

La dernière ligne qui est intéressant dans l’extrait cité est rayon -= rayon/500. La valeur 500 provient de notre « programme d’essai », celui non optimisé. Nous avons utilisé la proportionnalité par rapport à la valeur trouvée grâce à ce programme. Dans le programme d’essai nous retirions 1 au rayon pour un cercle de rayon 500. Ici nous retirons au rayon le résultat de la division du rayon par 500. Par exemple si le rayon est 500, on retirera 1 ( 500/500 = 1 ), si c’est 250, on retirera 0,5 ( 250/500 = 0,5 ), si c’est 750, on retirera 1,5 ( 750/500 = 1,5 ), etc. Ceci permet de faire des trous noir de la taille que l’on souhaite.

  • Quatrième étape : Dégradé du blanc au noir de finition.
    while r > 0 and v > 0 and b > 0:
        penup()
        goto(x, y - rayon)
        pendown()
        pencolor((r, v, b))
        circle(rayon)
        rayon -= rayon / 500
        b -= 16
        v -= 16
        r -= 16
    pencolor("black")
    circle(rayon)

Cette dernière boucle permet de faire un fort dégradé entre le blanc et le centre du trou noir, qui est… noir (🥴). Elle n’a rien de particulier par rapport à ce que l’on a expliqué plus haut mis à part la valeur forte de la réduction des valeurs des trois variables de couleurs (que l’on décrémente de 16) et également la condition de la boucle qui permet qu’elle s’arrête une fois que la couleur atteinte est le noir.

Les deux dernières lignes de l’extrait permettent d’éviter ce problème :

Les étoiles

Voici le code pour former les étoiles :

def etoile(x, y, branche, longueur, couleur=(255, 230, 0)):
    penup()
    goto(x, y)
    degre_angle = 180 - (360 / (branche * 2))
    begin_fill()
    fillcolor(couleur)
    for i in range(branche):
        forward(longueur)
        right(degre_angle)
    end_fill()

Cette fonction prend en paramètre les coordonnées x et y, le nombre de branche, la longueur des branches (plus précisément la longueur des segments constituants l’étoile) et la couleur (avec une couleur par défaut qui est un jaune-orange qui tend plus vers le jaune). On lève notre stylo, on se positionne de manière à ce que le centre de l’étoile soit les coordonnées données en paramètres et… pas de pendown() ? En effet celui-ci serait inutile pour former les étoiles car nous n’allons pas utiliser la fonction de tracé de ligne mais plutôt utiliser la fonction de remplissage (de couleur) de zone. Ensuite, nous créons une variable degre_angle. Elle est très importante car elle va définir le degré des angles qui vont permettre de former l’étoile. Regardez :

L’étoile est formée de la même manière que l’extrait cité sauf qu’ici le stylo est baissé, et il n’y a pas de couleur de remplissage. Les angles qui nous intéressent sont au bout des branches. Ce sont ces angles là que le programme contrôle.

En A), notre tortue avance. Elle est à une position avec un angle de 0°. L’angle en rouge est égal à 180°. C’est notre 180 dans la formule ! Et (360 / (branche * 2)) est en fait l’angle intérieur. Pour savoir la valeur de cet angle, il faut imaginer l’étoile dans un cercle. La somme de tous les sommets de cette étoile dans un cercle donne 360°. Et dans une étoile, le nombre de sommet est le double du nombre de branche.

Ensuite en B), elle s’oriente de l’angle calculé dans la variable degre_angle. Le trait violet est un trait de construction rajouté pour que le schéma soit plus clair.

Pour finir en C), la tortue avance. Ici on voit bien l’angle formé qui est celui de degre_angle. Le trait en cyan est un trait de construction.

D’une pierre deux coup, nous vous avons expliqué aussi la boucle qui est dans le programme. Avec begin_fill(), fillcolor(couleur) et end_fill() nous remplissons l’intérieur de l’étoile avec la couleur donnée en paramètre.

Le ciel (arrière-plan et étoiles)

Cool ! On a bien avancé. On continue avec cette fois-ci un bon bgcolor("black") qui est censé faire un arrière-plan en noir et… non. Cela ne va pas marcher, nous verrons cela un peu après, une fois le code entièrement présenté. Nous allons donc concevoir une fonction arriere_plan() :

def arriere_plan():
    # .ps est incapable de récupérer le bgcolor() selon internet...
    # Et des barres blanches apparaissent avec ce code dans le .png généré...
    penup()
    goto(-640, 0)
    pendown()
    pensize(900)
    forward(1280)

Il y a un bavard dans le code de ce que je vois, mais il a raison (ou on a tous les deux torts, c’est une éventualité). Encore une fois, nous verrons ceci un peu plus tard. Cette fonction est très simple, elle conçoit simplement un fond noir, en se positionnant le plus à gauche du canvas (zone de dessin) et en traçant un trait de la taille du canvas (le résultat doit avoir une taille de 1280 pixels de largeur par 720 pixels d’hauteur) avec une taille exagérée.

def ciel():
    arriere_plan()
    liste_couleur = [(255, 255, 255), (255, 230, 0)]
    for i in range(0, randint(71, 121)):
        liste_couleur[1] = (255, randint(150, 230), 0)
        etoile(randint(-630, 630), randint(-350, 350), 5, 10, choice(liste_couleur))
    for i in range(0, randint(16, 31)):
        liste_couleur[1] = (255, randint(150, 230), 0)
        etoile(randint(-620, 620), randint(-340, 340), 7, 20, choice(liste_couleur))
    for i in range(0, randint(6, 16)):
        liste_couleur[1] = (255, randint(150, 230), 0)
        etoile(randint(-600, 600), randint(-320, 320), 15, 40, choice(liste_couleur))

Occupons nous maintenant de la fonction ciel(). Nous appelons la fonction arriere_plan() puis le programme dessine des étoiles dans notre ciel. Nous utilisons simplement trois boucles qui dessineront 3 types d’étoiles différentes. En effet grâce aux paramètres branche et longueur, nous pouvons former des étoiles complètements différentes, diversifiant le ciel. Concernant le paramètre couleur, nous avons une liste qui varie à chaque fois que la boucle se répète. C’est plus précisément le second élément qui varie. On modifie aléatoirement la quantité de vert dans la couleur, rendant l’étoile plus ou moins orangée. La fonction choice() permet de choisir un élément aléatoirement parmi une liste donnée en paramètre. Pour finir sur ce bout de code, chaque boucle for génère un nombre aléatoire d’étoile entre deux valeurs précisées (ex : randint(71, 121)). On remarque que les étoiles plus petites apparaissent plus nombreuses.

Voici un rendu de la fonction ciel() :

Taille du canvas : 2560×1080 pixels
Taille du canvas : 1280×720 pixels

On remarque bien le fond généré « artificiellement » dans la première image, et comment cela rend dans les bonnes dimensions.

Assemblement et problèmes

Bien, nous avons notre ciel, plus qu’à rajouter les trous noirs. Nous en ferons trois :

ciel()
trou_noir(randint(-490, -250), randint(-260, 260), randint(50, 150))
trou_noir(randint(100, 250), randint(-260, 260), randint(50, 150))
trou_noir(randint(400, 490), randint(-260, 260), randint(50, 150))

On appelle donc notre fonction ciel() et nous générons trois trous noirs. Ils sont positionnés aléatoirement mais pour éviter une fusion de trou noir, nous les plaçons dans des coordonnées où ils ne peuvent s’entrechoquer. On remarque qu’il y a un décalage de 150 entre chaque plage de coordonnées x. C’est dû à la taille qui est aléatoire entre 50 et 150.

Une fusion de trou noir… C’est très beau, vous ne trouvez pas ?

Nous vous avions proposé un résultat en début d’article, en voici un autre :

Le rendu turtle
Le fichier PNG généré

On remarque diverse imperfection. La plupart provienne d’un problème lors de la conception du fichier postscript et nous n’avons pas trouver comment régler ce problème.

Un autre problème que nous avons eu a été celui-là :

Effectivement, je n’ai plus l’impression de voir un ciel…

Bon, qu’est-ce qui s’est passé ? Lorsque nous avons généré cette image, nous utilisions la fonction bgcolor("black") pour générer le fond noir sauf qu’après une petite recherche sur internet, le fichier postscript ne prend pas en compte cette action, il ne la « voit » pas. Nous avons donc dû changer par la fonction arriere_plan() que nous vous avons expliqué plus haut.

Conclusion

Vous pouvez former des images complètement différentes de ce que l’on a généré simplement en modifiant quelques valeurs ou en rajoutant une boucle for… Vous pouvez faire un ciel beaucoup plus dense, des dégradés plus profonds, des trous noirs plus grands, etc. Nous avons voulu faire un programme qui puisse avec très peu de modification générer des résultats d’une grande diversité.

Télécharger le .py

Si l’envie vous prend de rendre ces personnalisations plus simples d’accès et/ou optimiser notre code, voici un petit cadeau :

L’image finale

Art

Balles et ballons : les ballons du système solaire

Le premier projet de la classe de 1ère NSI est « Regard de géomètre ». Ce projet consiste en la création d’une image basée sur un ou plusieurs thèmes donnés. Pour notre image, on a choisi les thèmes astronomie et balles et ballons. Nous avons voulu représenter le système solaire mais en remplaçant les planètes et le Soleil par des balles et des ballons de différents sports.

Les étapes de création de notre image

Après avoir choisi nos thèmes et décidé de l’illustration que l’on souhaitait faire, nous avons commencé par le fond de notre illustration. Pour cela, on voulait un fond noir avec des étoiles représentées par des points blancs et de tailles différentes placées aléatoirement sur l’image. Cependant, les grosses étoiles à cause de leur couleur blanche, se voyaient trop par rapport aux plus petites. On a alors ajouté une couleur un peu plus grise pour les grosses étoiles mais on a gardé le blanc pour les petites. Pour faire cela, nous avons utilisé une instruction conditionnelle :

import turtle
import random
turtle.speed(0)
for i in range(150):
    turtle.penup()
  turtle.goto(random.randint(-640,640),random.randint(-350,350)) 
    turtle.pencolor("black")
    turtle.pendown()
    a=random.randint(1,5)
    if a&lt;2:
        turtle.begin_fill()
        turtle.fillcolor("white")
        turtle.circle(a)
        turtle.end_fill()
    else:
        turtle.begin_fill()
        turtle.fillcolor("#e1e1df")
        turtle.circle(a)
        turtle.end_fill()

Ce qui donne avec le fond:

Tracé du ciel étoilé

Dans un second temps, nous avons choisi les balles que l’on voulait représenter puis nous les avons tracées chacune séparément pour avoir le rendu le plus fidèle possible. Les balles choisies sont:

  • la balle de tennis
  • le ballon de basket-ball
  • le ballon de rugby
  • la balle de base-ball

A l’origine, on voulait faire le ballon de football plutôt que la balle de base-ball mais le motif de ce ballon est un peu trop complexe à faire et n’apportait que peu d’intérêt pour notre script.

Script pour le tracé du ballon de basket :

import turtle
turtle.bgcolor("black")
turtle.begin_fill()
turtle.fillcolor("coral")
turtle.goto(0,-3)
turtle.circle(98)
turtle.end_fill()
turtle.penup()
turtle.goto(-97,93)
turtle.left(-73)
turtle.pendown()
turtle.pensize(5)
turtle.pencolor("black")
turtle.circle(100,150)
turtle.penup()
turtle.goto(-97,93)
turtle.left(180)
turtle.pendown()
turtle.circle(100,-150)
turtle.penup()
turtle.goto(-97,93)
turtle.right(107)
turtle.pendown()
turtle.forward(186)

Tracé du ballon de basket

Dans la dernière étape de la création de notre image, nous avons regroupé toutes nos créations (fond, balles et ballons) dans un même script et nous avons rajouté certaines fonctionnalités comme les ellipses ou l’effet d’ombre qui vous seront montrés plus loin. Mais, lors de ce regroupement, nous avons fait face à plusieurs problèmes notamment au positionnement des balles et également à leur proportion (un ballon de basket ne peut pas être plus petit qu’une balle de tennis). Pour cela, on a effectué une suite d’essai-erreur jusqu’à ce que le résultat nous plaise.

Rendu final

Les fonctions utilisées dans le script

La première fonction importante de ce script est la fonction « orbite ». Elle consiste en la création d’une « fausse ellipse » à l’aide de 4 arcs de cercles de rayons différents. Cette fonction est plutôt simple mais extrêmement efficace.

def orbite(rayon):
  turtle.seth(-45) 
  for i in range(2):
      turtle.circle(rayon,90)
      turtle.circle(rayon/2,90)
  return()

La deuxième fonction marquante de ce script est la fonction permettant de créer un effet d’ombre sur les balles et ballons ayant une forme circulaire. Pour cela, il faut créer un dégradé de couleur formé à l’aide de cercles de plus en plus petits dont la couleur varie en même temps que le rayon diminue. Cette fonction s’appelle « surface ».

def surface(couleur,rayon,posx,posy):
    r=couleur[0]
    g=couleur[1]
    b=couleur[2]
    turtle.pensize(5)
    for i in range(51):
        turtle.home()
        turtle.goto(posx,posy)
        turtle.pendown()
        if ((r-i*1.5)>=0) and ((g-i*1.5)>=0) and ((b-i*1.5)>=0):
            r1=r-i*1.5; g1=g-i*1.5; b1=b-i*1.5;
        elif ((r-i*1.5)<0): r1=r
        elif ((g-i*1.5)<0): g1=g
        else: b1=b
        turtle.pencolor((r1/255,g1/255,b1/255))
        turtle.circle((100-2*i)*rayon)
        turtle.penup()

Enfin, la dernière fonction est la fonction étoile, elle permet comme son nom l’indique de tracer des étoiles de taille et avec un nombre de branches variables. Elle a pour paramètres le nombre de branches et la longueur des branches.

def etoiles(branches, longueur):
    turtle.begin_fill()
    turtle.fillcolor("white")
    for i in range(branches):
        turtle.forward(longueur)
        turtle.right(180+180/branches)
        turtle.forward(longueur)
        turtle.left(180-180/branches)
    turtle.end_fill()

Malheureusement, cette fonction a un défaut que l’on n’a pas su régler. Lorsque l’on choisit un nombre pair de branches, le nombre n’est pas respecté.

Exemple: lorsque l’on exécute etoiles(6,100). Le nombre de branches n’est pas correct.

Alors que lorsqu’on veut faire une étoile avec un nombre de branches impair, le nombre de branches est respecté.

Exemple: lorsque l’on exécute etoiles(9,100). Le nombre de branches est correct.

Problèmes rencontrés

Lors de la création de notre script, nous avons rencontré plusieurs problèmes comme le positionnement des balles ou encore la proportion des ballons mais également des problèmes qui survenaient lorsqu’on voulait créer une image. Ce problème venait de la commande bgcolor(). Cette fonction consiste à colorier le fond de la toile par la couleur de son choix. Cependant, sur le script nous permettant de créer nos images, le fond n’apparaissait pas. Pour résoudre ce problème, nous avons rajouté au script une boucle faisant des allers-retours sur la toile à l’aide d’un stylo épais permettant de créer manuellement ce fond.

turtle.goto(-760,400)
turtle.pensize(10)
turtle.right(90)
for i in range(75):
    turtle.forward(420*2)
    turtle.left(90)
    turtle.forward(10)
    turtle.left(90)
    turtle.forward(420*2)
    turtle.right(90)
    turtle.forward(10)
    turtle.right(90)

Conclusion sur notre premier projet en NSI

Ce premier projet nous a permis d’approfondir nos connaissances en turtle et de créer notre premier « gros script » de cette année en python en faisant appel à toutes les fonctions vues en cours. Nous aurions pu essayer d’apporter des améliorations avec un peu plus de temps en ajoutant par exemple d’autres balles plus complexes comme la balle de golf.

Télécharger le .py

L’image finale

Art

Jardins : Forêt enneigée

Ce script génère une image aléatoire de forêt enneigée en utilisant deux fractales très connues : l’Arbre de Pythagore et le Flocon de Koch.

Les fractales

Le Flocon de Koch

Le Flocon de Koch utilise une courbe fractale. Une courbe fractale est un dessin composé de segment dont la forme de base va être reproduite à l’infini.

Dans le cas de la courbe de Koch, sur chaque segment, un triangle va être dessiné, et pour chaque niveau, on va rajouter un triangle sur les nouveaux segments.

Pour créer cette courbe, on va utilisé le principe de récursivité, c’est à dire qu’on va appeler dans une fonction python la fonction elle-même.

def cote(longueur,niveau):
    if niveau==0:
        forward(longueur)
    else:
        cote(longueur/3,niveau-1)
        left(60)
        cote(longueur/3,niveau-1)
        right(120)
        cote(longueur/3,niveau-1)
        left(60)
        cote(longueur/3,niveau-1)

On exécute la fonction cotée en définissant la longueur et le niveau de répétition souhaité. Ligne 2, on vérifie que le niveau est égal à 0. S’il ne l’est pas, ligne 5, on rappelle la fonction et cette fois-ci la longueur est divisée par 3 et on enlève 1 au niveau. Ainsi, on répète tant que le niveau n’est pas égal à 0, et quand le niveau est égale à 0, on avance de « longueur ».

En répétant cela plusieurs fois, on obtient la courbe de Koch.

Pour obtenir un flocon, on répète cette courbe trois fois.

def flocon(longueur,niveau,x,y):
    width(1)
    penup()
    goto(x,y)
    pendown()
    for i in range(3):
        cote(longueur,niveau)
        right(120)

Ce code provient de https://www.numworks.com/fr/professeurs/activites-pedagogiques/premiere/flocon/

L’arbre de Pythagore

L’arbre de Pythagore fonctionne de la même manière : la fonction s’appelle elle-même.

def arbre(n,longueur,w,r1,g1,b1,r2,g2,b2):
  if n==0 :
    pencolor(r1,g1,b1)
    forward(longueur)
    backward(longueur)
    pencolor(r2,g2,b2)
  else:
    width(w) 
    forward(longueur/3)
    left(50) 
    arbre(n-1,longueur*2/3,w/1.2,r1,g1,b1,r2,g2,b2)
    right(2*50)
    arbre(n-1,longueur*2/3,w/1.2,r1,g1,b1,r2,g2,b2)
    left(50)
    backward(longueur/3)

Cette fonction prend plusieurs paramètres :

  • le niveau n de répétition
  • la longueur du tronc
  • la largeur w : afin que les arbres éloignés soient plus fins que les arbres au premier plan, on définit la largeur. Plutôt que d’utiliser w-1 (sinon après un certain niveau de répétition la valeur deviendrait négative), on utilise w/1.2 ce qui permet de réduire la valeur sans changer son signe.
  • r1,g1,b1 : qui définissent en RGB la couleur des feuilles.
  • r2,g2,b2 : qui définissent en RGB la couleur du tronc.

Ce code provient de https://my.numworks.com/python/cent20/arbre

Le fond

L’exécution du fond et des montagnes

A chaque exécution le fond va être d’une couleur aléatoire.

color(randint(10,250),255,255)
begin_fill()
goto(-640,700)
pendown()
goto(640,700)
goto(640,-700)
goto(-640,-700)
end_fill()

A chaque fois que nous exécutons le script, le résultat est unique, les montagnes ayant une forme définie auront une couleur aléatoire.

Script d’une des montagnes :

for i in range (10):
    for i in range (5):
        forward(20)
        right(2)
    for i in range (5):
        forward(10)
        left(2)

Cette boucle crée des fragments de cercles collés, qui forment une ondulation.

Les trois montagnes donnent cette image, avec des couleurs uniques à chaque fois.

L’exécution des arbres

On dessine 7 arbres en tout : 2 sur la montagne du fond, 2 sur la montagne du milieu et trois sur la montagne du devant. Chaque arbre a un secteur donné sur sa montagne et il est dessiné dans ce secteur, de façon unique à chaque fois.

Les arbres sur la montagne la plus éloignée sont plus petits, plus fins et plus sombres, cependant chaque arbre est d’une couleur, d’une taille et d’une largeur différentes à chaque exécution.

Voici par exemple l’exécution d’un arbre sur la montagne du fond

penup()
goto(randint(-550,-450),randint(120,160))
pendown()
setheading(90)
color(75,randint(40,50),randint(0,20))
arbre(9,randint(50,90),randint(4,7),randint(130,180),randint(160,180),180,75,randint(40,50),randint(0,20))

L’exécution des flocons

Ensuite on exécute les flocons:

for i in range (randint(30,45)):
    setheading(randint(0,360))
    color(randint(0, 220),randint(110, 240),255)
    begin_fill()
    flocon(randint(20,50),randint(3,5),randint(-639,639),randint(-310,310))
    end_fill()

A chaque exécution, le nombre de flocons est différent. Chaque flocon est orienté différemment , à une couleur, une taille, un niveau de répétition, et un emplacement différent.

L’image finale

Télécharger le .py

Si vous voulez l’essayer, vous trouverez le script ci-dessous, cependant faites attention, chaque arbre prend relativement longtemps à s’exécuter, ajouté aux flocons, le script prend environ 1h30 à s’exécuter.

Art

Pendules : Une horloge analogique

Une horloge analogique… Qu’est-ce cela peut bien être… Eh bien, c’est tout simplement une horloge avec des aiguilles ! Ainsi, ce programme vous permettra, grâce à Turtle, d’afficher une horloge analogique…

Introduction

La spécificité de cette horloge, est que celle-ci est dynamique. C’est-à-dire que les aiguilles bougent en fonction de l’heure réel. Sinon cela serait trop facile, il suffirait seulement de dessiner un cercle pour le cadran, et des segments pour les aiguilles, et c’est fini. Heureusement, ce n’est pas le cas.

Quelques fonctions

Pour afficher l’heure réel, il faut d’abord récupérer l’heure réel… Pour cela, j’utilise la fonction time.strftime(), à partir du module time, je récupère une donnée de la date actuelle, en l’occurrence j’ai besoin de 3 données : l’heure, la minute, et la seconde. Voici donc une fonction que j’ai codé qui m’a permis de récupérer une de ces 3 données :

def get_time(u):
    match u:
        case "h":
            return int(strftime("%I"))
        case "m":
            return int(strftime("%M"))
        case "s":
            return int(strftime("%S"))

Ici, j’ai utilisé la déclaration match, qui permet, entre autres, de comparer la valeur d’une variable, ici la variable u (pour unité). Par exemple, en appelant la fonction suivante get_time("h"), elle me renvoi la valeur de l’heure actuelle, à l’heure où j’écris cet article, il est exactement 01:44 donc en appelant la fonction maintenant, elle me renverrait la valeur 1.
À savoir qu’utiliser la déclaration match n’est absolument pas obligatoire, j’aurais très bien pu utiliser une structure conditionnelle traditionnelle avec les déclarations if, elif, et else.

Désormais, j’ai besoin d’afficher le cadran de l’horloge, pour cela, rien de plus simple :

def draw_clock(x, y, rayon):
    travel(x, y-rayon)
    pencolor((0,)*3)
    fillcolor((255,)*3)
    begin_fill()
    circle(rayon)
    end_fill()
    travel(x, y-rayon+10)
    fillcolor(7, 24, 31)
    begin_fill()
    circle(rayon-10)
    end_fill()
    travel(x, y-5)
    fillcolor(85, 91, 92)
    begin_fill()
    circle(5)
    end_fill()
    penup()
    goto(x, y)
    setheading(90)
    pencolor((255,)*3)
    for i in range(60):
        forward(rayon-(25 if i%5 == 0 else 15))
        pendown()
        forward(25 if i%5 == 0 else 15)
        penup()
        goto(x, y)
        right(6)

C’est une fonction plutôt simple, bien qu’elle soit assez lourde. On dessine des cercles, et on fait les marquages des minutes et des heures. J’ai dans cette fonction, utilisé une autre fonction qui ne vient pas des modules importés, la fonction travel() (pour voyager). J’aime beaucoup cette fonction car elle est extrêmement simple, et permet d’économiser quelques lignes :

def travel(x, y):
    penup()
    goto(x, y)
    pendown()

En fait, c’est tout simplement l’équivalent d’un goto(), mais sans laisser les traces du pinceau ! Voici donc le cadran, il est fixe :

J’ai également voulu ajouter dans le fond un mur en briques. Pour ne pas laisser le fond vide, la fonction fait seulement 7 lignes :

def wall_brick(x, y, width_bricks, height_bricks):
    for i in range(height_bricks):
        for j in range(width_bricks):
            if i % 2 == 0:
                fill_rect(x+65*j, y+35*i, 60, 30, (161, 84, 68))
            else:
                fill_rect(x+30+65*j, y+35*i, 60, 30, (161, 84, 68))

Les paramètres sont simples, la position du mur (le bas à gauche du mur) via x et y, et le nombre de briques en longueurs, ainsi que le nombre de briques en hauteur. fill_rect() est une fonction maison inspiré de kandinsky.fill_rect(), elle permet de dessiner des rectangles :

def fill_rect(x, y, w, h, c=(0, 0, 0)):
    travel(x, y)
    pencolor(c)
    fillcolor(c)
    begin_fill()
    for i in range(4):
        forward(w if i % 2 == 0 else h)
        right(90)
    end_fill()

Ci-dessous donc, le mur en briques, contruit par la fonction wall_brick(-668, -330, 21, 21) :

Difficultés rencontrées

Il ne reste donc plus qu’à dessiner les aiguilles et les faire pivoter au fur et à mesure. Voici donc la fonction qui occupe cette lourde tâche, et qui m’a bien cassé la tête :

def clock_hands(colors_hands, size_hands):
    s, m, h, k = get_time("s"), get_time("m"), get_time("h"), 0
    update_hours(h, colors_hands[0], size_hands[0])
    update_minutes(m, colors_hands[1], size_hands[1])
    while True:
        update_seconds(s, colors_hands[2], size_hands[2])
        sleep(.6 if k < 90 else .5 if k < 180 else .3 if k < 240 else 0)
        s += 1
        if s == m+2:
            update_minutes(m, colors_hands[1], size_hands[1])
        if s+1 == (h+1)*5:
            update_hours(h, colors_hands[0], size_hands[0])
        if s == 60:
            s, m, h = get_time("s"), get_time("m"), get_time("h")
            update_minutes(m, colors_hands[1], size_hands[1])
            update_hours(h, colors_hands[0], size_hands[0])
            update_seconds(s, colors_hands[2], size_hands[2], 1)
        k += 1

C’est sans doute la fonction la plus compliquée du programme. Les deux paramètres ne sont qu’esthétique, ils permettent de modifier la couleur de chaque aiguille, ainsi que la largeur de chaque aiguille, on ne donc y s’attarder plus que ça.
L’objectif est simple, avoir l’heure la plus précise possible, mais en gardant un mouvement des aiguilles fluide.
J’ai fait le choix d’appeler la fonction get_time() le moins de fois possible, car elle requiert de faire un nombre extrêmement élevé de requêtes plusieurs fois par secondes. Et faire des requêtes inutiles, ça ralentit le programme… La fonction n’est donc appelée que lors de l’initialisation (avant de rentrer dans la boucle infinie), et lorsque la trotteuse à passe à la soixantième seconde. Nous appelons donc la fonction get_time() environ une fois par minute ; et c’est suffisant. Ensuite, on met à jour la position des aiguilles toutes les secondes… Enfin, c’est un peu plus compliqué que ça. En effet, il faut que le mouvement soit fluide, et donc il faut supprimer toutes les actions inutiles. Sauf que 98% du temps, il n’y a que l’aiguille des secondes qui bouge, celle des minutes et des heures ne bougent beaucoup moins souvent. Donc cela ne sert à rien de mettre à jour ces aiguilles à chaque seconde. On le fait donc à des instants précis.
Malgré toutes les optimisations pour fluidifier le rafraichissement, il n’est malheureusement pas parfait.
Également, il s’avère que plus le programme tourne longtemps, plus il est lent… Il faut donc adapter la pause de la fréquence en fonction de quand le programme a démarré. Voici à quoi sert la variable k, et la fonction time.sleep(), nous perdons donc beaucoup de précisions au fil du temps. Mais en contrepartie, j’ai mis en place un système pour rerégler automatiquement les aiguilles.

L’image finale

À toi de « jouer » ?!

Tu ne pourras malheureusement pas vraiment t’amuser avec ce programme. À moins que tu veuilles fixer une horloge. Néanmoins, si tu veux savoir comment elle fonctionne exactement, et la voir bouger, n’hésite pas à télécharger le script !

Télécharger le .py

Tutoriels

Découvrir le module turtle de python

Ce mini tutoriel vous propose quelques exemples de scripts python, simple à comprendre et à modifier, vous permettant de débuter sereinement la réalisation d’une image dessiné avec le module turtle de python.

Cet article a été écrit à deux mains, ainsi vous ne saurez pas qui accabler ci vous y trouvez des coquilles 😅

Tableau des méthodes Turtle en python

Ce tableau présente quelques méthodes turtle, mais il en existe d’autres, il ne faut pas hésiter à lire la documentation officielle : turtle — Turtle graphics

instructionsExplication en françaisExemples d’utilisation
forward(distance)La tortue avance de distance dans la direction précédemment fixéeDessiner des triangles
circle(radius)La tortue trace un cercle de rayon radiusDessiner des cercles
goto(x, y)La tortue se deplace aux point de coordonnées (x,y)Dessiner des triangles
begin_fill()
fillcolor(couleur)
end_fill()
La tortue remplit des formes géométriques de la couleur couleur, c’est comme le seau de peinture dans Paint.Colorier des cercles
il existe de nombreuses autres fonctions dans le module turtle, lisez la documentation officielle : turtle — Turtle graphics et cherchez d’autres tutoriels !

Dessiner des triangles équilatéraux

Le script ci-dessous définit une fonction, capable de construire un triangle équilatéral aux coordonnées (x, y) et de spécifier la longueur du côté du triangle. La couleur par défaut est le noir #000000 ou (1,1,1) mais cette couleur peut-être personnalisé lors de l’appel de la fonction.

from turtle import *
from random import randint

colormode(255)

def triangle(longueur, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x,y)
    pendown()
    pencolor(couleur)
    for i in range(3):
        forward(longueur)
        left(120)

for i in range(42):
    x, y = randint(-600, 400), randint(-300, 200)
    long = randint(10, 200)
    color = (randint(0, 255), randint(0, 255), randint(0, 255))
    triangle(long, x, y, color)

Dessiner des cercles

Le script ci-dessous définit une fonction, capable de construire un cercle aux coordonnées (x, y) et de spécifier la longueur du rayon de ce cercle. La couleur par défaut est le noir #000000 ou (1,1,1) mais cette couleur peut-être personnalisé lors de l’appel de la fonction.

from turtle import *
from random import randint

colormode(255)

def cercle(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y-rayon)
    pendown()
    pencolor(couleur)
    circle(rayon)
    

for i in range(42):
    x, y = randint(-600, 400), randint(-300, 200)
    radius = randint(10, 200)
    color = (randint(0, 255), randint(0, 255), randint(0, 255))
    cercle(radius, x, y, color)

Dessiner des disques

Le script ci-dessous définit une fonction, capable de construire un disque aux coordonnées (x, y) et de spécifier la longueur du rayon de ce disque. La couleur par défaut est le noir #000000 ou (1,1,1) mais cette couleur peut-être personnalisé lors de l’appel de la fonction.

from turtle import *
from random import randint

colormode(255)

def disque(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y-rayon)
    pendown()
    pencolor(couleur)
    fillcolor(couleur)
    begin_fill()
    circle(rayon)
    end_fill()
    

for i in range(42):
    x, y = randint(-600, 400), randint(-300, 200)
    radius = randint(10, 200)
    color = (randint(0, 255), randint(0, 255), randint(0, 255))
    disque(radius, x, y, color)

Ecrire des fonctions et les réutiliser

Une manière intelligente d’écrire un script est de coder des fonctions, des fonctions paramétrables.

Les fonctions proposées ci-dessus sont paramétrables :

  • coordonnées (x, y),
  • couleur,
  • rayon ou longueur

Nous aurions pu ajouter d’autres paramètres à ces fonctions, comme par exemple la largeur du trait ou une rotation initiale dans le cas des triangles…

Un exemple d’image générée avec une unique fonction, cette fonction est appelée dans une boucle.

Un champ de rose (source), un script de moins de 42 lignes, beaucoup moins !

La fonction elle même contient une boucle.

L’histoire raconte que plusieurs milliers de cercles ont été tracés.

L’image est générée au format .png en exploitant le tutoriel Exporter une image générée par le module turtle sur python