Décor Urbain

Projets

Plongeons dans un univers qui évoque sans le savoir pourquoi une nostalgie avec cette scène inspirée de ces soirs où après être passer une soirée avec ses amis il est temps de retourner à sa voiture dans la nuit et l’humidité. Au premier plan, une voiture au design minimaliste évoque les lignes classiques d’une BMW M3 e30, garée devant un bâtiment aux néons vibrants. Sous un ciel étoilé, l’ensemble évoque une esthétique des années 80, où le contraste entre l’ombre et les couleurs vives nous transporte dans une ambiance intemporelle et nostalgique.

Inspirations

Pour créer nôtre image, celle-ci nous a beaucoup servit de repère, notamment dans les perspectives.

source : @initial_clip (instagram)

Cette voiture est celle que l’on a représentée, une BMW M3 e30. Mise en vente dans le milieu des années 80

Résultat Final

Pour générer cette image le script est découper en plusieurs parties :

  • Mise en place du script
  • L’arrière plan
  • Le bâtiment
  • La voiture
  • L’enregistrement de l’image

Mise en place du script

import turtle
import random
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 = "Décor Urbain"
turtle.title(titre)
screen = turtle.Screen()
screen.setup(width=1920, height=1080)
turtle.speed(150000)
turtle.ht()
turtle.colormode(255)

On commence le code en important tout nos modules nécessaires : Turtle, Random et Pillow.

import turtle
import random
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 = "Décor Urbain"
turtle.title(titre)
screen = turtle.Screen()
screen.setup(width=1920, height=1080)
turtle.speed(150000)
turtle.ht()
turtle.colormode(255)

On continue avec la mise en place du titre de la fenêtre, des dimensions de l’écran, la vitesse du curseur, la disparition du curseur et le système de couleur mit en rgb.

L’arrière plan

On rentre dans le vif du sujet avec l’arrière plan de l’image. Qui comporte le ciel étoilé et la route avec ses trottoirs.

# Fonction pour dessiner le fond avec un dégradé
def fond():
    rciel, gciel, bciel = 176, 196, 205  # Couleur initiale du ciel
    hauteur = -351
    turtle.penup()
    turtle.goto(-960, hauteur)
    turtle.pendown()

    # Boucle pour créer un dégradé de couleur vers le haut
    while hauteur < 540:
        turtle.pencolor(int(rciel), int(gciel), int(bciel))
        turtle.forward(1920)
        hauteur += 1
        turtle.goto(-960, hauteur)
        bciel = max(100, bciel - 205 / 540)  # Ajuste la composante bleue
        rciel = max(0, rciel - 176 / 540)    # Ajuste la composante rouge
        gciel = max(0, gciel - 196 / 540)    # Ajuste la composante verte

# Fonction pour dessiner des étoiles aléatoirement
def etoiles():
    for i in range(150):
        turtle.penup()
        x = random.randint(-960, 960)
        y = random.randint(-351, 540)
        turtle.goto(x, y)
        turtle.pendown()
        turtle.dot(random.randint(1, 8), "white")
        
# Dessiner la route en perspective
def route():
    turtle.pensize(7)
    
    turtle.begin_fill()
    turtle.color("black","Slate Grey")
    turtle.penup()
    turtle.goto(-428,-81)
    turtle.pendown()
    turtle.goto(-928,-81)
    turtle.goto(-928,-411)
    turtle.goto(-428,-81)
    turtle.end_fill()
    
    turtle.begin_fill()
    turtle.color("black")
    turtle.penup()
    turtle.goto(-928,-411)
    turtle.pendown()
    turtle.goto(-428,-81)
    turtle.goto(1200,-300)
    turtle.goto(315,-900)
    turtle.goto(-928,-411)
    turtle.end_fill()

    turtle.color("white")
    turtle.penup()
    turtle.goto(-775,-411)
    turtle.pendown()
    turtle.goto(-275,-81)
    
    turtle.color("Slate Grey")
    turtle.begin_fill()
    turtle.penup()
    turtle.goto(315,-410)
    turtle.pendown()
    turtle.goto(-500,-330)
    turtle.goto(0,0)
    turtle.goto(1000,-350)
    turtle.goto(315,-410)
    turtle.end_fill()
    
# Appelle les fonctions pour dessiner le fond, les étoiles et la route
fond(),etoiles(),route()

Le ciel :

# Fonction pour dessiner le fond avec un dégradé
def fond():
    rciel, gciel, bciel = 176, 196, 205  # Couleur initiale du ciel
    hauteur = -351
    turtle.penup()
    turtle.goto(-960, hauteur)
    turtle.pendown()

    # Boucle pour créer un dégradé de couleur vers le haut
    while hauteur < 540:
        turtle.pencolor(int(rciel), int(gciel), int(bciel))
        turtle.forward(1920)
        hauteur += 1
        turtle.goto(-960, hauteur)
        bciel = max(100, bciel - 205 / 540)  # Ajuste la composante bleue
        rciel = max(0, rciel - 176 / 540)    # Ajuste la composante rouge
        gciel = max(0, gciel - 196 / 540)    # Ajuste la composante verte

.Le ciel de l’image est en grand dégradé qui vire d’un gris-bleu à un bleu nuit.
Pour ce faire on défini la couleur initiales du ciel, avec sa quantité de rouge, vert et bleu. On détermine ensuite la hauteur où démarre le dégradé avec la variable « hauteur ». On déplace le curseur en -960 et à la hauteur minimale ici -351.
On démarre une boucle qui prend fin lorsque hauteur atteint 540, soit la hauteur maximale souhaitée. La couleur y est défini sur les valeurs actuelles de rouge, de vert et de bleu, on fait avancer le curseur de 1920, la largeur de la fenêtre. On ajoute un à la hauteur et déplace le curseur de nouveaux en -960 quant aux abscisses et à la nouvelle hauteur. La couleur est ensuite modifier en soustrayant la quantité initiale de la couleur divisé par le nombre de traits faits. Ce qui va logiquement amené la valeur à 0 au bouts de toute les itérations. Mais voulant du bleu et non du noir en couleur finale en instaure une limite avec la fonction max() qui est définie sur 100.

Les étoiles :

# Fonction pour dessiner des étoiles aléatoirement
def etoiles():
    for i in range(150):
        turtle.penup()
        x = random.randint(-960, 960)
        y = random.randint(-351, 540)
        turtle.goto(x, y)
        turtle.pendown()
        turtle.dot(random.randint(1, 8), "white")

Pour faire les étoiles on défini le nombre d’étoiles que l’on veut mettre ici c’est défini en argument de range(), que est défini sur 150 itérations. On défini une variable x qui comporte une valeur entière aléatoire entre -960 et 960, de même pour la variable y cette fois entre -351 et 540. On déplace le curseur à ces valeurs qui servent de coordonnées. Et on y fait un point d’un diamètre aléatoire entre 1 et 8 et de couleur blanche : range()

La génération aléatoire permet d’avoir parfois la formations de constellation non calculées. Cela donne je trouve une belle authenticité à l’image.

La route :

# Dessiner la route en perspective
def route():
    turtle.pensize(7)
    
    #Tottoir gauche
    turtle.begin_fill()
    turtle.color("black","Slate Grey")
    turtle.penup()
    turtle.goto(-428,-81)
    turtle.pendown()
    turtle.goto(-928,-81)
    turtle.goto(-928,-411)
    turtle.goto(-428,-81)
    turtle.end_fill()
    
    #Route
    turtle.begin_fill()
    turtle.color("black")
    turtle.penup()
    turtle.goto(-928,-411)
    turtle.pendown()
    turtle.goto(-428,-81)
    turtle.goto(1200,-300)
    turtle.goto(315,-900)
    turtle.goto(-928,-411)
    turtle.end_fill()

    turtle.color("white")
    turtle.penup()
    turtle.goto(-775,-411)
    turtle.pendown()
    turtle.goto(-275,-81)
    
    #Troittoir droit
    turtle.color("Slate Grey")
    turtle.begin_fill()
    turtle.penup()
    turtle.goto(315,-410)
    turtle.pendown()
    turtle.goto(-500,-330)
    turtle.goto(0,0)
    turtle.goto(1000,-350)
    turtle.goto(315,-410)
    turtle.end_fill()

Le code là assez répétitif, on trace un polygone que l’on rempli de couleur à des fonctions turtle.begin_fill() qui déterminer le début du remplissage et turtle.end_fill() qui détermine la fin du remplissage. On fait ceci pour trois polygones, un qui va faire le trottoir gauche, un qui va faire la route, et l’autre qui va s’installer devant la route et va servir de trottoir droit. Après le traçage du polygone pour la route on trace une ligne simple qui sert de ligne blanche pour ajouter du réalisme à la route.

Les polygones et traits paraissent pas propres, et avec des coordonnées douteuses mais seront par la suites recouverts de façons à ce que cela soit joli.

Appel des fonctions :

# Appelle les fonctions pour dessiner le fond, les étoiles et la route
fond(),etoiles(),route()

On appelle finalement les trois fonctions.

Le bâtiment

#fonction pour convertir les points de mon dessin en des points sur python
def point(x,y): 
    l = (1920 * x) / 14,5
    h = (1080 * y) / 8
    return l,h

pen = turtle.Turtle() 
pen.penup() 
pen.pensize(3)
pen.speed(15000)
pen.ht()
# Liste des coordonnées pour les points du bâtiment 

def batiment():
    coords = [ (315, 445),(-398, 324),(-398, -284),(315, -351), (398, -351), (973, -324), (973, 324),  (315, 445), ] 
    pen.fillcolor("light gray")
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    for x, y in coords[1:]:
        pen.goto(x, y)
    pen.end_fill()
# Dessiner la ligne centrale 
    pen.penup() 
    pen.goto(315, 445) # Retour au sommet
    pen.pendown() 
    pen.goto(315, -351) # Descend jusqu'au bas du bâtiment
    return

def pare_soleil():
    coords = [(-398, 27),  (315, 54), (315, -108),(-438, -81), (-398, 27), (-110, 37.5),(-157, -90.5),(108, -101.2),(151,47.25),(315,54),(274,-108),]
    pen.penup()
    pen.goto(coords[0]) # Aller au premier point de la liste
    pen.pendown() 
    pen.fillcolor("#FFD700")# colorier le pare soleil côté gauche
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[5])
    pen.goto(coords[6])
    pen.goto(coords[3])
    pen.end_fill()

    pen.fillcolor("#FAFAD2")# colorier le pare soleil côté droit
    pen.penup()
    pen.goto(coords[5])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(coords[2])
    pen.goto(coords[6])
    pen.end_fill()

    pen.fillcolor("#FFFFF0")# colorier le pare soleil sur l'extrémité de droite pour donné un effet de 3D
    pen.penup()
    pen.goto(coords[1])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(coords[2])
    pen.goto(coords[10])
    pen.goto(coords[1])
    pen.end_fill()

    pen.color("black")          # Couleur du contour
    pen.pensize(5)              # Épaisseur du contour
    pen.penup()# Début du remplissage de la figure
    pen.goto(coords[0])          # Aller au premier point de la liste des coordonnées
    pen.pendown()
# Dessiner la figure en reliant les points
    for x, y in coords[1:]:
        pen.goto(x, y)
    pen.penup()
    return
             
def contour_fenetre():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.penup()
    pen.goto(coords[0]) # Aller au premier point de la liste des coordonnées
    pen.pendown() 
    for x, y in coords[1:]: # Boucle pour aller de point en point 
        pen.goto(x, y)
        pen.fillcolor("#FFFFF0")

    pen.fillcolor("#808080")# colorier en gris le contour des fentres
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(185,202)
    pen.goto(-82.5,175)
    pen.goto(coords[16])
    pen.goto(coords[15])
    pen.goto(-112,173)
    pen.goto(coords[8])
    pen.goto(coords[9])
    pen.goto(coords[10])
    pen.goto(coords[0])
    pen.end_fill()
    return

def fenetre_gauche():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.fillcolor("#FF69B4")
    pen.penup()
    pen.goto(coords[8])         
    pen.pendown()
    pen.begin_fill()
    pen.goto(-112,173)
    pen.goto(coords[15])
    pen.goto(coords[9])
    pen.goto(coords[8])
    pen.end_fill()
    return

def fenetre_droite():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.fillcolor("#FF69B4")# fenetre de droite
    pen.penup()
    pen.goto(coords[18])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(185,202)
    pen.goto(coords[4])
    pen.goto(coords[19])
    pen.goto(coords[18])
    pen.end_fill()
    return
    
batiment(), pare_soleil(), contour_fenetre(), fenetre_gauche(), fenetre_droite()

Fonction usuelle et mise en place du code :

def point(x,y): 
    l = (1920 * x) / 14,5
    h = (1080 * y) / 8
    return l,h

Pour commencer, nous avons créé une fonction appelée point. Cette fonction consiste à convertir l’emplacement des points de notre image de référence ( en cm) en point sur python tout en gardant les proportions et symétries. Cette fonction est très simple, il suffit de lui donner 2 valeurs soit x et y puis elle va procéder à un produit en croix qui nous rendra l et h l’emplacement du point sur python.

pen.turtle est utilisé pour créer un nouvel objet turtle nommé pen.

On utilisera la “tortue” (ici pen) , on pourra ensuite l’utiliser pour dessiner.

pen.penup() Cette commande indique à la tortue de lever son stylo, ce qui signifie qu’elle va se déplacer sans tracer de ligne.

pen.pensize(3) Cette ligne définit la taille du stylo de la tortue, c’est-à-dire l’épaisseur des lignes qu’elle va tracé.

pen.speed(15000) Cette commande fixe la vitesse de déplacement de la tortue. Nous avons choisi 15000 pour être sûr que la tortue va à sa vitesse maximale en fonction de l’ordinateur utilisé.

 pen.ht() cela signifie “hide turtle”, c’est-à-dire cacher la tortue.

pen = turtle.Turtle() 
pen.penup() 
pen.pensize(3)
pen.speed(15000)
pen.ht()

Définition des fonctions :

def batiment():
    coords = [ (315, 445),(-398, 324),(-398, -284),(315, -351), (398, -351), (973, -324), (973, 324),  (315, 445), ] 
    pen.fillcolor("light gray")
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    for x, y in coords[1:]:
        pen.goto(x, y)
    pen.end_fill()
# Dessiner la ligne centrale 
    pen.penup() 
    pen.goto(315, 445) # Retour au sommet
    pen.pendown() 
    pen.goto(315, -351) # Descend jusqu'au bas du bâtiment
    return

def batiment()

Tout d’abord, nous avons créé une fonction nommée batiment. Elle regroupe le code utilisé pour faire la base du bâtiment.

Puis , nous avons créé une liste de tuples nommé coords, chacun représentant les coordonnées (x, y) de points autour desquels la « tortue » va se déplacer pour dessiner les contours du bâtiment.

pen.fillcolor(“light gray”)

Cette commande fixe la couleur de remplissage pour le dessin de la tortue en gris clair. La tortue remplira l’intérieur du bâtiment avec cette couleur.

pen.goto(coords[0]) La tortue va se déplacer au premier point de la liste de tuples.

pen.begin_fill() démarre le processus de remplissage. Une fois que la tortue trace tous les côtés du bâtiment, elle remplira la forme fermée avec la couleur light gray définie plus haut.

pen.end_fill() termine le processus de remplissage et remplit la forme fermée (le bâtiment) en gris clair.

for x, y in coords[1:]:

 pen.goto(x, y)

Cette boucle for parcourt les coordonnées dans coords à partir du deuxième point (indiqué par coords[1:]).

À chaque itération, la tortue se déplace vers le point (x, y), dessinant une ligne entre chaque point consécutif.

pen.penup() 

pen.goto(315, 445)

pen.pendown() 

pen.goto(315, -351)

Cette partie dessine une ligne centrale verticale à l’intérieur du bâtiment.

pen.penup() lève le stylo pour que la tortue se déplace sans tracer jusqu’au sommet du bâtiment.

pen.goto(315, 445) la place en haut du bâtiment.

pen.pendown() abaisse le stylo, permettant de dessiner une ligne jusqu’à pen.goto(315, -351), qui est le bas du bâtiment.

def pare_soleil():
    coords = [(-398, 27),  (315, 54), (315, -108),(-438, -81), (-398, 27), (-110, 37.5),(-157, -90.5),(108, -101.2),(151,47.25),(315,54),(274,-108),]
    pen.penup()
    pen.goto(coords[0]) # Aller au premier point de la liste
    pen.pendown() 
    pen.fillcolor("#FFD700")# colorier le pare soleil côté gauche
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[5])
    pen.goto(coords[6])
    pen.goto(coords[3])
    pen.end_fill()

    pen.fillcolor("#FAFAD2")# colorier le pare soleil côté droit
    pen.penup()
    pen.goto(coords[5])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(coords[2])
    pen.goto(coords[6])
    pen.end_fill()

    pen.fillcolor("#FFFFF0")# colorier le pare soleil sur l'extrémité de droite pour donné un effet de 3D
    pen.penup()
    pen.goto(coords[1])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(coords[2])
    pen.goto(coords[10])
    pen.goto(coords[1])
    pen.end_fill()

    pen.color("black")          # Couleur du contour
    pen.pensize(5)              # Épaisseur du contour
    pen.penup()# Début du remplissage de la figure
    pen.goto(coords[0])          # Aller au premier point de la liste des coordonnées
    pen.pendown()
# Dessiner la figure en reliant les points
    for x, y in coords[1:]:
        pen.goto(x, y)
    pen.penup()
    return

pare soleil

Ensuite, nous avons créé une fonction nommée pare_soleil, qui regroupe le code utilisé pour dessiner un pare-soleil avec des effets de remplissage et de contour.

Puis, nous avons créé une liste de tuples nommée coords. Chacun de ces tuples représente les coordonnées (x, y) de points autour desquels la tortue va se déplacer pour dessiner le contour du pare-soleil.

La commande pen.penup() lève le stylo pour éviter de tracer une ligne jusqu’à la position initiale. Ensuite, pen.goto(coords[0]) déplace la tortue au premier point de la liste coords, et pen.pendown() abaisse le stylo pour pouvoir commencer à dessiner.

Pare soleil extrémité de gauche

La commande pen.fillcolor(« #FFD700 ») fixe la couleur de remplissage en jaune doré pour dessiner le côté gauche du pare-soleil.

La séquence suivante utilise pen.penup() pour lever le stylo, puis pen.goto(coords[0]) pour déplacer la tortue au premier point de la liste des coordonnées, et pen.pendown() pour abaisser le stylo à cet endroit.

pen.begin_fill() démarre le processus de remplissage. 

Ensuite, la tortue se déplace successivement aux coordonnées coords[5], coords[6], et coords[3], ce qui crée un contour fermé. pen.end_fill() termine le processus et remplit cette zone en jaune doré.

Pare soleil extrémité de droite

Ici, pen.fillcolor(« #FAFAD2 ») change la couleur de remplissage pour un jaune clair (presque crème) qui sera utilisé pour le côté droit du pare-soleil.

pen.penup() lève le stylo pour déplacer la tortue sans tracer. pen.goto(coords[5]) place la tortue au point coords[5], et pen.pendown() abaisse le stylo pour commencer à tracer le contour.

pen.begin_fill() démarre le remplissage, puis pen.goto(coords[1]), pen.goto(coords[2]), et pen.goto(coords[6]) déplace la tortue aux différents points du côté droit du pare-soleil pour former le contour. Enfin, pen.end_fill() remplit cette zone avec la couleur jaune clair.

Troisième remplissage(effet 3d)

Ensuite, pen.fillcolor(« #FFFFF0 ») définit la couleur de remplissage en blanc cassé pour créer un effet 3D sur le bord droit du pare-soleil.

La séquence suivante lève le stylo avec pen.penup(), puis pen.goto(coords[1]) positionne la tortue au point de départ du bord droit. pen.pendown() abaisse le stylo pour commencer à dessiner.

pen.begin_fill() démarre le remplissage, et la tortue se déplace aux coordonnées coords[2], coords[10], et retourne à coords[1] pour former la bordure en blanc cassé, créant ainsi un effet de profondeur. pen.end_fill() termine et remplit cette zone.

Contour

Pour le contour du pare-soleil, pen.color(« black ») définit la couleur du contour en noir, et pen.pensize(5) fixe l’épaisseur de ce contour à 5 pixels.

pen.penup() lève le stylo pour éviter de tracer avant d’arriver au point de départ. pen.goto(coords[0]) place la tortue au premier point de la liste, et pen.pendown() abaisse le stylo pour commencer le tracé.

La boucle for parcourt les coordonnées à partir du deuxième point (indiqué par coords[1:]). À chaque itération, la tortue se déplace aux coordonnées (x, y), dessinant un segment de ligne entre chaque point et formant ainsi le contour complet du pare-soleil.

Enfin, pen.penup() lève le stylo pour éviter de tracer accidentellement en dehors de la figure.

def contour_fenetre():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.penup()
    pen.goto(coords[0]) # Aller au premier point de la liste des coordonnées
    pen.pendown() 
    for x, y in coords[1:]: # Boucle pour aller de point en point 
        pen.goto(x, y)
        pen.fillcolor("#FFFFF0")

    pen.fillcolor("#808080")# colorier en gris le contour des fentres
    pen.penup()
    pen.goto(coords[0])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(coords[1])
    pen.goto(185,202)
    pen.goto(-82.5,175)
    pen.goto(coords[16])
    pen.goto(coords[15])
    pen.goto(-112,173)
    pen.goto(coords[8])
    pen.goto(coords[9])
    pen.goto(coords[10])
    pen.goto(coords[0])
    pen.end_fill()
    return

def contour fenetre

Nous avons créé une fonction appelée contour_fenetre, qui contient le code nécessaire pour dessiner le contour d’une fenêtre avec des effets de remplissage.

Nous définissons ensuite une liste de coordonnées coords pour représenter les points (x, y) que la tortue va relier afin de former le contour de la fenêtre.

La commande pen.pensize(3) définit l’épaisseur du trait à 3 pixels. Ensuite, pen.penup() lève le stylo pour éviter de tracer pendant le déplacement initial, et pen.goto(coords[0]) positionne la tortue au premier point de la liste de coordonnées. pen.pendown() abaisse le stylo pour commencer à dessiner.

La boucle for parcourt chaque point dans coords à partir du deuxième (indiqué par coords[1:]). À chaque itération, la tortue se déplace aux coordonnées (x, y) et trace une ligne entre chaque point, créant ainsi le contour extérieur de la fenêtre.

La commande pen.fillcolor(« #808080 ») change la couleur de remplissage en gris pour le contour de la fenêtre. Ensuite, pen.penup() lève le stylo pour éviter de tracer avant d’arriver au point de départ. pen.goto(coords[0]) positionne la tortue au premier point des coordonnées, et pen.pendown() abaisse le stylo pour commencer le remplissage de la fenêtre.

La commande pen.begin_fill() démarre le processus de remplissage. Tous les segments suivants seront remplis de gris jusqu’à ce qu’on appelle pen.end_fill()

Dans cette séquence, la tortue se déplace de point en point pour dessiner les différents segments de la fenêtre en utilisant des coordonnées spécifiques dans coords ainsi que des coordonnées explicites pour certaines parties de la fenêtre.

  • pen.goto(coords[1]), pen.goto(185, 202), et pen.goto(-82.5, 175) tracent le premier côté du contour intérieur de la fenêtre.
  • pen.goto(coords[16]), pen.goto(coords[15]), et pen.goto(-112, 173) dessinent le côté gauche de la fenêtre.
  • pen.goto(coords[8]), pen.goto(coords[9]), et pen.goto(coords[10]) tracent la partie inférieure.
  • pen.goto(coords[0]) ramène la tortue au point de départ, fermant ainsi la forme.
def fenetre_gauche():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.fillcolor("#FF69B4")
    pen.penup()
    pen.goto(coords[8])         
    pen.pendown()
    pen.begin_fill()
    pen.goto(-112,173)
    pen.goto(coords[15])
    pen.goto(coords[9])
    pen.goto(coords[8])
    pen.end_fill()
    return

def fenetre Gauche

La fonction fenetre_gauche dessine une fenêtre colorée en rose (code hexadécimal #FF69B4) sur le côté gauche de la structure.

Nous commençons par définir la liste coords, qui contient les points (x, y) pour tracer les contours de la fenêtre. Ces coordonnées permettent de structurer la forme que la tortue va dessiner.

Ensuite, pen.pensize(3) définit l’épaisseur du trait à 3 pixels, et pen.fillcolor(« #FF69B4 ») fixe la couleur de remplissage en rose.

La tortue se rend au point de départ coords[8] sans tracer, puis abaisse le stylo pour commencer le remplissage.

La tortue se déplace vers plusieurs points pour créer une forme fermée

Cette séquence de déplacements trace les côtés de la fenêtre. pen.end_fill() termine le processus de remplissage en rose, créant ainsi une fenêtre complète.

def fenetre_droite():
    coords = [ (-370, 162),(185, 216),(209, 202),(209,53),(185,52),(185, 201.5),(185, 216),(185, 201.5),(-350, 148),(-350, 31),(-370, 30),(-370, 162),(-350, 148),(-370, 162),(-112,187),(-112,38),(-82.5,39),(-82.5,189),(-62.5,175),(-62.5,41),]
    pen.pensize(3)
    pen.fillcolor("#FF69B4")# fenetre de droite
    pen.penup()
    pen.goto(coords[18])          
    pen.pendown()
    pen.begin_fill()
    pen.goto(185,202)
    pen.goto(coords[4])
    pen.goto(coords[19])
    pen.goto(coords[18])
    pen.end_fill()
    return

def fenetre droite

Pour la fenêtre de droite, la fonction est exactement la même.Les seules différences sont les pen.goto(coords[.]) car les fenêtres ne sont pas superposées mais côte à côte.

Appel des fonctions :

batiment(), pare_soleil(), contour_fenetre(), fenetre_gauche(), fenetre_droite()

On appel là toutes les fonctions pour dessiner le bâtiment.

La voiture

Pour terminer le visuel de l’image on dessine la voiture.

turtle.pensize(6)

def ligne(xa,ya,xb,yb):
    turtle.penup()
    turtle.goto(xa,ya)
    turtle.pendown()
    turtle.goto(xb,yb)

# faire une ellipse
def roue(x,y,rad):
  	turtle.color("black")
    turtle.begin_fill()
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    # inclinaison
    turtle.seth(45)
     
    # rad --> rayon de l'arc
    for i in range(2):
        # deux arcs de cercles

        turtle.circle(rad,90)		#côté grand
        turtle.circle(rad//2.5,90)	#côté petit, le diviseur est responsable de la perspective
    turtle.end_fill()

def phares(x,y):
    positions = [(x, y, "orange"), (x + 40, y + 5, "light cyan"), (x + 150, y + 20, "light cyan"), (x + 190, y + 25, "orange")]
    
    for pos_x, pos_y, color in positions:
        turtle.penup()
        turtle.goto(pos_x, pos_y)
        turtle.pendown()
        turtle.dot(30, color)

def pc(x,y):
    turtle.color("white smoke")
    for i in range (7):
        turtle.pensize(2)
        ligne(x+40,y+abs((y/25))-(4*i)+5,x+150,y+abs((y/20))-(4*i)+15)
    phares(x,y)


def voiture_v2():
    #CÔTÉ
    turtle.color("black","grey")
    coord = [((-330,-200),(-310,-210)),((-310,-210),(-310,-223)),((-310,-223),(-265,-220)),((-265,-220),(-270,-233)),((-270,-233),(-35,-240)),((-35,-240),(100,-280)),((100,-280), (100,-388)),((100, -388),(-293,-365)),((-293,-365),(-330,-350)),((-330,-350),(-330,-200))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(-35,-240,-35,-380)
    #AILERON
    turtle.color("black")
    coord = [((-330,-200),(-250,-195)),((-250,-195),(-255,-206)),((-255,-206),(-310,-210)),((-310,-210),(-330,-200))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    #HAUT
    turtle.color("black","royal blue")
    coord = [((-270,-233),(-220,-140)),((-220,-140),(-50,-150)),((-50,-150),(180,-130)),((180,-130),(250,-210)),((250,-210),(-35,-240)),((-35,-240),(-270,-233))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    turtle.color("black")
    coord = [((-220,-140),(-30,-127)),((-30,-127),(180,-130)),((180,-130),(-50,-150)),((-50,-150),(-220,-140))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(-50,-150,-35,-240)
    ligne(-210,-370,-190,-140)
    #AVANT
    roue(280,-380,57)		#roue avant droite
    turtle.color("black","dim gray")
    coord = [((-35,-240),(-50,-210)),((-50,-210),(-83,-207)),((-83,-207),(-83,-223)),((-83,-223),(-59,-227)),((-59,-227),(-35,-240)),((-35,-240),(100,-280)),((100,-280),(100,-388)),((100,-388), (350,-355)),((350,-355),(350,-250)),((350,-250),(250,-210)),((250,-210),(-35,-240))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(100,-280,350,-250)
        
voiture_v2()
roue(-250,-383,55)		#roue arrière
roue(50,-410,65)		#roue avant gauche
pc(130,-300)

Déclaration d’une fonction usuelle :

On définit d’abord de quelle épaisseur seront les traits pour construire la voiture avec turtle.pensize(), ici défini sur 6.
On déclare ensuite une fonction ligne() avec en argument les coordonnées de deux points. Cette fonction va permettre le traçage de lignes en évitant d’utiliser la fonction turtle.forward(), trop imprécise, ou les quatre lignes habituelles en utilisant des turtle.goto(). Faisant gagner quelques lignes.

turtle.pensize(6)

def ligne(xa,ya,xb,yb):
    turtle.penup()
    turtle.goto(xa,ya)
    turtle.pendown()
    turtle.goto(xb,yb)

Traçage d’une roue :

# faire une ellipse
def roue(x,y,rad):
  	turtle.color("black")
    turtle.begin_fill()
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    # inclinaison
    turtle.seth(45)
     
    # rad --> rayon de l'arc
    for i in range(2):
        # deux arcs de cercles

        turtle.circle(rad,90)		#côté grand
        turtle.circle(rad//2.5,90)	#côté petit, le diviseur est responsable de la perspective
    turtle.end_fill()

Pour la génération de la voiture on va devoir générer 3 roues. Pour ce faire on déclare une fonction roue() avec en arguments les coordonnées et le rayon de la roue.

On souhaite la roue pleine on utilise donc les balises turtle.begin_fill()() et turtle.end_fill() qui vont déterminer le remplissage des roues. On lève le stylo pour ne plus dessiner et on va aux coordonnées demandés. La fonction turtle.seth() permet d’incliner le curseur.

La route est enfaite une ellipse, une ellipse, c’est simplement deux arc de cercles de mêmes rayons reliés par deux autres arc de cercles de rayon différents aux premiers mais communs entre eux. Pour réaliser cela on utilise la fonction turtle.circle() avec en arguments le rayon demander et 90 degrés qui correspond au traçage d’un quart de cercle. On va utiliser une nouvelle fois cette fonction mais cette fois-ci avec en arguments le rayon diviser par 2.5, et toujours 90 degrés. Ceci va permettre le traçage à la suite du premier arc de cercle un deuxième plus petit.

On met ceci dans une boucle à deux itération à l’aide de for i in range(2), et on obtient une ellipse

Pare-chocs avant :

def phares(x,y):
    positions = [(x, y, "orange"), (x + 40, y + 5, "light cyan"), (x + 150, y + 20, "light cyan"), (x + 190, y + 25, "orange")]
    
    for pos_x, pos_y, color in positions:
        turtle.penup()
        turtle.goto(pos_x, pos_y)
        turtle.pendown()
        turtle.dot(30, color)

def pc(x,y):
    turtle.color("white smoke")
    for i in range (7):
        turtle.pensize(2)
        ligne(x+40,y+abs((y/25))-(4*i)+5,x+150,y+abs((y/20))-(4*i)+15)
    phares(x,y)
def phares(x,y):
    positions = [(x, y, "orange"),
                 (x + 40, y + 5, "light cyan"),
                 (x + 150, y + 20, "light cyan"),
                 (x + 190, y + 25, "orange")]
    
    for pos_x, pos_y, color in positions:
        turtle.penup()
        turtle.goto(pos_x, pos_y)
        turtle.pendown()
        turtle.dot(30, color)

Pour tracer les phares je déclare la fonction phares() avec comme arguments les coordonnées des phares.

On déclare en premier lieu les positions et couleur qu’auront les phares à l’aide d’une boucle for avec trois indices correspondants aux coordonnées en x et en y, et la couleur on parcours la liste « positions ». On lève le stylo, se déplace aux positions x et y correspondants à là où se trouvent les variables pos_x et pos_y qui parcourent la liste des coordonnées, on abaisse le stylo, utilise la fonction turtle.dot() avec en arguments une épaisseur de 30 et la couleur correspondante à là où se trouve la variable color qui parcoure la liste. La boucle for permet de mettre fin aux itérations lorsqu’on atteint la fin de la boucle.

def pc(x,y):
    turtle.color("white smoke")
    for i in range (7):
        turtle.pensize(2)
        ligne(x+40,y+abs((y/25))-(4*i)+5,x+150,y+abs((y/20))-(4*i)+15)
    phares(x,y)

Le pare-chocs est composé des phares qu’on a défini juste avant et de 7 lignes qui relient les phares. On déclare donc une fonction pc() avec en argument les coordonnées où le dessin va se faire.

On défini premièrement la couleur sur « white smoke » et l’épaisseur du trait à 2.

On commence une boucle for avec comme indice i avec une range() de 7.

Pour tracer ces traits en gardant une perspective on appelle la fonction ligne(), déclarée en début de code, avec comme arguments les coordonnées des points inscrits en argument de pc(). Quant aux abscisses de points on se contente de garder les valeurs en argument de la fonction en ajouter un léger décalage. Par contre pour les coordonnées en ordonné on ajoute à l’ordonnée de départ une fraction de celle-ci, et de manière à ce que l’ordonné d’arrivé est plus haut pour créer une perspective. On ajoute ensuite 4*i, permettant d’espacer chaque traits à chaque itérations.

Suite à cette boucle on appelle la fonction phares() avec comme arguments les arguments de pc().

def voiture_v2():
    #CÔTÉ
    turtle.color("black","grey")
    coord = [((-330,-200),(-310,-210)),((-310,-210),(-310,-223)),((-310,-223),(-265,-220)),((-265,-220),(-270,-233)),((-270,-233),(-35,-240)),((-35,-240),(100,-280)),((100,-280), (100,-388)),((100, -388),(-293,-365)),((-293,-365),(-330,-350)),((-330,-350),(-330,-200))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(-35,-240,-35,-380)
    #AILERON
    turtle.color("black")
    coord = [((-330,-200),(-250,-195)),((-250,-195),(-255,-206)),((-255,-206),(-310,-210)),((-310,-210),(-330,-200))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    #HAUT
    turtle.color("black","royal blue")
    coord = [((-270,-233),(-220,-140)),((-220,-140),(-50,-150)),((-50,-150),(180,-130)),((180,-130),(250,-210)),((250,-210),(-35,-240)),((-35,-240),(-270,-233))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    turtle.color("black")
    coord = [((-220,-140),(-30,-127)),((-30,-127),(180,-130)),((180,-130),(-50,-150)),((-50,-150),(-220,-140))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(-50,-150,-35,-240)
    ligne(-210,-370,-190,-140)
    #AVANT
    roue(280,-380,57)		#roue avant droite
    turtle.color("black","dim gray")
    coord = [((-35,-240),(-50,-210)),((-50,-210),(-83,-207)),((-83,-207),(-83,-223)),((-83,-223),(-59,-227)),((-59,-227),(-35,-240)),((-35,-240),(100,-280)),((100,-280),(100,-388)),((100,-388), (350,-355)),((350,-355),(350,-250)),((350,-250),(250,-210)),((250,-210),(-35,-240))]
    turtle.begin_fill()
    for start, end in coord:
        turtle.penup()
        turtle.goto(start)
        turtle.pendown()
        turtle.goto(end)
    turtle.end_fill()
    ligne(100,-280,350,-250)

Cette voiture est construite de plusieurs polygones le code en est de ce fait assez répétitif suivant toujours la même méthodologie :

  • On défini la couleur de contour et de remplissage du polygone avec la fonction turtle.color()
  • On déclare une liste de coordonnées des sommets de nos polygones
  • On débute le remplissage de nos polygones avec la fonction turtle.begin_fill()
  • On créer une boucle for() qui avec comme indices deux variables, start et end, qui parcourent la liste de coordonnées pour déterminer les deux points à relier
  • On relit les deux points à l’aide de turtle.goto() auxquels on met en argument les valeurs de start et end
  • On conclue avec turtle.end_fill(), pour finir le remplissage.

On note quelques moments où on ajoute des lignes supplémentaires :

  • Lorsque dans #CÔTÉ on ajoute une ligne pour définir la partie droite de la portière
  • Dans #HAUT on fait deux lignes, une qui relie le toit à ligne faite juste avant pour définir le par brise. Et une autre ligne définissant la partie gauche de la portière en reliant le toit au bas de la voiture.
  • Dans #AVANT une ligne définissant la partie haute du pare-chocs
  • Dans #AVANT on appelle la fonction roue() pour faire la roue gauche qui sera en partie cachée par la voiture

Appel des fonctions :

On appel toutes les fonctions ensembles

voiture_v2()
roue(-250,-383,55)		#roue arrière
roue(50,-410,65)		#roue avant gauche
pc(130,-300)

L’enregistrement de l’image :

# Enregistrement de l'image
image = turtle.getcanvas()
nom_du_fichier_sans_extension=titre+"_"+hex(random.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((1920, 1080))
    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")
turtle.exitonclick()

turtle.done()

On récupère l’image, on lui assigne un nom aléatoire afin de ne pas écraser les autres et on l’enregistre automatiquement dans le fichier où se trouve le programme, au format png.

Image finale

Lors de l’enregistrement en png, on voit des traits qui apparaissent suite aux déplacements en goto() même si le stylo est en position penup().

Télécharger le code