Author: Bastien S.

Tutoriels

Tuto: configurer son logiciel de stream ou d’enregistrement

OBS Studio (Open Broadcaster Software) est un logiciel gratuit et open source utilisé pour l’enregistrement vidéo et le streaming en direct. Ce tutoriel vous guidera à travers les étapes pour configurer OBS Studio de manière optimale.

Les prérequis

-Une connexion stable avec un débit d’au moins 3 Mbps (strict minimum) mais il est recommandé d’avoir un débit d’environ 8 Mbps

-Un ordinateur de compétition .Tout dépend du type de contenu, si vous souhaitez uniquement faire du face caméra, un PC dit “classique” avec un petit i5 ou Ryzen 5 peut totalement convenir. Cependant, si vous souhaitez streamer vos meilleurs games, vous allez devoir ouvrir grand votre portefeuille. 

Trois solutions s’offrent à vous : 

1 : Utiliser un deuxième ordinateur pour streamer à l’aide d’une carte d’acquisition que vous pouvez trouver aux alentours des 40 € pour un rendu convenable. L’ordinateur “de stream” n’a pas besoin d’être particulièrement puissant encore une fois un i5 ou un Ryzen 5 suffit.

2 : Streamer avec son ordinateur de jeu. Pour cela vous aurez besoin d’un très bon pc. 16 Go de RAM au grand minimum, plus il y en a mieux c’est, i7, Ryzen 7 ou bien un très bon i5 ou Ryzen 5 récent pour votre processeur… il faut au moins ça pour gérer les deux à la fois sans trop de difficulté ! Cependant vous pouvez décider de streamer à l’aide de votre carte graphique et pour votre choix aucun doute possible Nvidia est le roi. Les cartes graphiques de chez Nvidia des générations 3000 et 4000 possèdent un encodeur (Nvenc) intégré avec une puce dédiée à l’encodage, ce qui en théorie permet de minimiser l’impact du stream sur vos performances en jeux.( je conseil cependant au moins une RTX 3060 voir une RTX 3060 ti pour avoir une puissance convenables)

3 : Installer une seconde carte graphique dans votre ordinateur fixe. Je ne recommande pas forcément cette solution. Vous pourriez ruiner l’airflow de votre boitier. Cette solution reste envisageable à condition de posséder une très grosse alimentation et un boîtier adapté.

Site officiel pour installer OBS studio:  https://obsproject.com/.

Paramétrage

Avant tout, veillez à bien cliquer sur Appliquer en bas à droite de la fenêtre après vos modifications. Et ne copiez pas bêtement les paramètres sur les photos ils ne sont peut-être pas adaptés à votre configuration.

Stream(Flux)

La première chose à faire est de lier votre compte de service de streaming (twitch, youtube…) à OBS. Puis vous pourrez ignorer ou non les paramètres du service de streaming si votre débit dépasse les 6000 kbps, sachant que celui de Twitch atteint en réalité 8000 kbps. 

SI vous souhaitez voir votre tchat directement depuis obs, c’est possible en sélectionnant BetterTTV et FrankerFaceZ dans Extensions du chat twitch. Cependant vous ne pourrez pas intervenir dessus, je vous invite plutôt à ouvrir votre dashboard Twitch où vous pourrez gérer votre tchat 

Général

Je vous invite à ne pas toucher la catégorie Général sauf si vous souhaitez changer de langue.

Sortie / Vidéo

Sélectionnez le mode avancé en haut de votre page. 

Sélectionner piste audio 1, vous pouvez cocher piste VOD Twitch afin de séparer une piste, cela peut servir ,par exemple, pour une musique que vous ne désirez pas pour votre redif, mais uniquement pour votre stream. 

Sélectionner l’encodeur vidéo en fonction de sur quel composant vous souhaitez encoder Nvidia Nvenc H264 est destiné aux cartes graphiques Nvidia et x264 a votre processeur, vous pourrez aussi rencontrer l’encodeur AMD que je ne vous conseil pas.

Il est temps de choisir la définition de votre stream et son framerate (fps) Il paraît évident de choisir du 1080p 60 fps, cependant il faut prendre en compte le débit vidéo maximal de votre service de streaming. Pour twitch le débit maximal est officiellement 6000 kbps (ou plutôt  8000kbps en réalité). Si on regarde le débit d’une vidéo 1080p 60 fps en H264 est d’environ 14000 kbps. C’est ce paramètre qui va rendre votre image horrible. On ne peut pas dépasser les 8000 kbps.

 Le tableau ci dessous présente le bitrate nécessaire en fonction de votre définition et de votre framerate

Il faut donc faire un compromi 

60 fps50 fps30fps
Résolution bitrate (kbps)bitrate (kbps)bitrate (kbps)
1080p(1920×1080)13686114056843
936p(1664×936)1028085665140
900p(1600×900)950479204752
864p(1536×864)875972994379
720p(1280×720)608350693041
540p(960×540)342128511711
480p(852×480)269922491350

La mise à l’échelle est nécessaire si vous souhaitez streamer dans une autre définition que celle de votre écran, si c’est le cas sélectionnez Lanczos

Dans les paramètres de l’encodeur sélectionner CBR dans le contrôle du débit, mettez le débit nécessaire en fonction de votre résolution choisie (arrondi au-dessus) puis 2 s dans l’intervalle d’images clé.

Si vous choisissez Nvidia Nvenc H264

Pour le préréglage il est quasiment inutile de dépasser P4 : moyen et je vous invite à faire des essais pour trouver le préréglage le plus optimal pour votre configuration. Pour réglage, c’est la même chose. Sélectionner un profil high. Décocher Prédiction (Look-ahead) et Améliorations psycho-visuelles.

Il est possible que vous ayez plusieurs cartes graphiques. Si vous souhaitez faire tourner le stream sur votre autre carte graphique, mettez 1 sinon laissez 0 (pour sélectionner une 3eme carte graphique sélectionnez 2, 3 pour sélectionner votre 4eme carte graphique etc…)

Dans nombre maximal de Bframes, sélectionnez 2

Si vous choisissez x264 Je vous invite à faire des test en sachant qu’au dessus de médium comme préréglage les différences sont minime. Vous pouvez essayer les réglage fins mais ne touchez pas à Option x264 

Dans Enregistrement, je vous conseille le format mkv mais libre a vous de changer en fonction de vos besoins.

Vous pouvez changer d’encodeur vidéo pour enregistrer avec un plus haut bitrate et donc une meilleure qualité. Sélectionner piste audio 1 si vous n’avez pas touché à piste VOD twitch. Si vous avez configuré une autre piste pour l’enregistrement sélectionnez cette piste

Audio

Dans les parametres audio, veillez a chosir votre microphone dans Audio micro/auxiliaire et ne touchez pas au reste.

Autre

Vous pouvez configurer des raccourcis clavier pour certaines actions. Je vous conseil de na pas toucher aux parametres d’Accessiblité et Avancé.

Projets

Subaru Impreza WRC

Dans le cadre du projet Art génératif qui consiste a générer une image en pythona l’aide du module turtle, j’ai réalisé ma voiture favorite, la Subaru Impreza dans un thème néon. Je vous explique dans cet article la rélisation de ce projet

La légendaire Subaru Impreza

L’Impreza est une compacte du constructeur automobile japonais Subaru, apparue en 1992. Icône de la marque grâce à ses succès en championnat du monde des rallyes (trois titres pilotes et trois titres constructeurs), elle en est à sa cinquième génération depuis 2016.Avec un moteur d’une cylindrée de 2 litres et 211 chevaux (94/97) et 217 (98/00) pour la version européenne de première génération sous l’appellation GT, les premières Impreza qui deviendront les WRX peuvent afficher des caractéristiques allant jusqu’à 320 chevaux dans leur version STI. Depuis 2015, La Subaru WRX est devenu un modèle indépendant de la Impreza et suit son propre développement. De ce fait, le nom Impreza disparait peu à peu des références sportives remplacé par la WRX et à moindre mesure par la Subaru BRZ.

Avant meme de realiser

Appel et verification des modules

from turtle import *
from random import randint


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 = "Bastien.S"
title(titre+" | Subaru Impreza WRC")
setup(1920,1080)
colormode(255)
speed(0)
hideturtle()
flash = True 
if flash:
    wn = Screen()
    wn.tracer(0)

Ici on appelle les fonctions turtle et random ou plutot uniqument randint. On verifie ensuite on verifie si l’utilisateur a bien PIL d’installer s’il ne l’a pas un code d’erreur s’affichera ainsi qu’un lien pour installer le module. On definie le titre de la fenetre ainsi que sa taille,le type de couleurs utiliséeds (ici R,G,B), on cache la tortue, et randons le script instantané.

Un script en calques

Comme pour tout dessin numérique nous avons besoins de differents calques. Un calque est une couche transparente sur laquelle des éléments graphiques peuvent être placés et manipulés indépendamment les uns des autres. Les differentes fonctions représentent nos calques voici les notres :

background()
batiments()
road()
subaru()
logo()

Background()

def background():
    r = 20
    g = 20
    b = 20
    hauteur = 540
    x = 0
    for i in range(50):
        pensize(10),color(r,g,b),penup(),goto(-960,hauteur),pendown(),forward(1920)
        hauteur = hauteur - 8
        b = b + 1
        r = r + 1 
    goto(-960,hauteur)

    for i in range(37):
        pensize(10),color(r,g,b),penup(),goto(-960,hauteur),pendown(),forward(1920)
        hauteur = hauteur - 10
        g = g + 2
        r = r - 1
    goto(-960,hauteur)

    for i in range(90):
        pensize(7),color(35,35,45),penup(),goto(-960,hauteur + 1),pendown(),forward(1950)
        hauteur = hauteur - 7

Nous avons décomposer fond en 3 parties distinctes: degradé noir vers rose puis rose vers vert pour le ciel puis du gris foncé pour la route.

Pour creer nos degradés nous plaçons notre tortue tout en haut a gauche de notre fenetre puis nous la faisons avancer jusqu’a l’extremité droite. Ensuite on retourne a gauche et on va a la ligne du dessous en diminuant la valeur (hauteur), tout ca grace a la fonction goto. On modifie la couleur en augmantant ou diminuant les valeur (R,G,B) et on recommence. Pour creer la route on fait la meme chose mais sans changer la couleur

batiments()

def batiments():   
    pensize(2)
    penup()
    goto(-960,-226)
    pendown()
    forward(100)
    color(20,20,20),forward(360),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(620),end_fill(),left(90),backward(80),begin_fill(),left(90),forward(650),left(90),forward(120),left(90)
    forward(40),right(70),forward(60),left(70),forward(592),end_fill(),backward(2),left(90),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(624),end_fill(),left(90),backward(260),color(30,30,30)
    begin_fill(),left(90),forward(640),left(100),forward(240),left(80),forward(599),end_fill(),left(90),forward(240),begin_fill(),left(90),forward(640),right(100),forward(240),right(80),forward(599),end_fill()
    left(90),forward(350),begin_fill(),left(90),forward(640),left(100),forward(240),left(80),forward(599),end_fill(),left(90),forward(240),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(620)
    end_fill(),color(20,20,20),begin_fill(),left(90),forward(1),left(90),forward(350),right(45),forward(80),right(95),forward(60),left(50),forward(35),left(25),forward(50),right(115),forward(383),end_fill(),begin_fill()
    left(180),color(25,25,25),forward(430),right(100),forward(80),right(80),forward(415),end_fill(),left(90),begin_fill(),color(15,15,15),forward(3),left(90),forward(250),right(90),forward(80),left(45),forward(20),right(45)
    forward(15),left(90),forward(60),right(90),forward(100),right(90),forward(325),end_fill(),left(90),backward(20),color(25,25,25),begin_fill(),left(90),forward(230),right(95),forward(100),left(95),forward(110),right(80)
    forward(100),right(55),forward(10),right(45),forward(342),end_fill(),begin_fill(),left(90),backward(15),left(90),color(10,15,15),forward(300),right(92),forward(120),right(88),forward(20),left(90),forward(20),right(90)
    forward(275),end_fill(),color(25,25,25),left(180),begin_fill(),forward(275),right(90),left(80),forward(20),right(65),forward(200),right(15),forward(100),right(90),forward(360),end_fill(),left(90)

Pour creer ses batiments sombre rien de plus simple et d’aussi long. Nous avons utilisé les fonctions bengin_fill et end_fill, avec differéntes teintes de gris pour créer du relief

road()

def road():
    color(100,100,100),pensize(7)
    for i in range(2):
        liste_longueur_bandes1 = [2,10,6,10,60,150,]
        liste_longueur_bandes2 = [1,4,7,16,75,220]
        liste_longueur_bandes3 = [2,10,10,12,100,200]
        liste_longueur_bandes4 = [1,4,8,15,25,97]
        liste_longueur_distance_bandes = (1,3,6,9,20,40)
        liste_angle_gauche = [15,20,25,30,43,85]
        liste_angle1 = [90,50,45,35,45,85]
        liste_angle2 = [90,135,135,155,155,133]
        liste_angle3 = [90,70,40,20,25,45]
        liste_angle4 = [90,105,140,150,135,97]
        nblb1 = len(liste_longueur_bandes1)
        nblb2 = len(liste_longueur_bandes2)
        nblb3 = len(liste_longueur_bandes3)
        nblb4 = len(liste_longueur_bandes4)
        nbldb = len(liste_longueur_distance_bandes)
        nba = len(liste_angle_gauche)
        nba1 = len(liste_angle1)
        nba2 = len(liste_angle2)
        nba3 = len(liste_angle3)
        nba4 = len(liste_angle4)
        penup(),goto (-540,-226),pendown()  
        for i in range(6):
            right(liste_angle_gauche[i%nba])
            forward(liste_longueur_bandes1[i%nblb1])
            left(liste_angle1[i%nba1])
            forward(liste_longueur_bandes2[i%nblb2])
            left(liste_angle2[i%nba2])
            forward(liste_longueur_bandes3[i%nblb3])
            left(liste_angle3[i%nba3])
            forward(liste_longueur_bandes4[i%nblb4])
            left(liste_angle4[i%nba4])
            forward(liste_longueur_bandes1[i%nblb1])
            penup()
            forward(liste_longueur_distance_bandes[i%nbldb])
            pendown()
            left(liste_angle_gauche[i%nba])

        color(255,255,255)
        pensize(2)

Pour realiser les bandes nous avons creer des listes contenants les differents parametres de celles ci (longueurs, angle, etc)

subaru()

def subaru():
    color(0,150,250)
    pensize(7)
    for i in range(2):
        penup()
        goto(-330,-200)
        pendown()

        #roue arriere
        left(106),forward(95),left(60),forward(30),left(50),forward(30),backward(30),right(50),backward(30),right(60),forward(25),left(85),forward(40),left(65),forward(25),left(2),forward(30),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),left(37),forward(40)

        #arriere voiture
        right(155),forward(75),right(55),forward(20),left(45),forward(45),right(45),forward(50),right(25),forward(40)

        #aileron
        left(160),forward(30),right(80),forward(30),right(100),forward(60),backward(60),left(100),forward(8),right(100),forward(60),backward(60),left(80),forward(5),left(10),left(90),forward(20),left(90),forward(50),left(90),forward(35),left(20)
        
        #plafond
        forward(20),left(30),forward(80),right(22),forward(65),right(24),forward(85),right(9),forward(185),right(17),forward(70),backward(20)

        #parebrise
        right(165),forward(70),left(5),forward(145),left(112),forward(95)


        #capot
        left(50),forward(140),right(15),forward(35),left(5)

        #phare
        right(55),forward(32),backward(32),right(85),forward(35),left(90),forward(25),left(80),forward(120),left(110),forward(25),left(65),forward(85),right(10)

        #capot
        left(155),backward(35),left(20),backward(140),left(18),forward(150),left(35),backward(10),forward(20),right(35),forward(110),right(50),forward(10),backward(5),left(50),forward(15),right(40),backward(110) ,forward(110),left(23),forward(130),right(20),forward(50),right(35)


        #phare droit
        forward(20),right(10),forward(10),right(100),forward(60),right(100),forward(20),right(75),forward(50),penup(),goto(-330,-200),right(2),pendown()

        #roue arriere
        left(106),forward(95),left(60),forward(30)

        #dessus du peneu
        left(50),forward(30),backward(30),right(50),backward(30),right(60),forward(25),left(85),forward(40),left(65),forward(25)

        #jante
        left(2),forward(30),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),left(37),forward(40),left(37),forward(70),left(65),forward(55),left(60),forward(70)
        
        #bas de caisse
        right(58),backward(25),forward(190)

        #roue avant
        left(86),backward(45),right(78),forward(33)

        #jante
        penup(),left(85),forward(90),left(170),pendown(),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),penup(),left(48),forward(84),pendown(),left(96),backward(33),left(78),forward(112)

        #portiere
        left(10),forward(50),right(20),forward(55),left(35),forward(95),left(60),forward(75),left(35),forward(85),left(30),forward(70),left(124),forward(220),backward(140),left(67),forward(100),backward(180),right(140),forward(80),left(73),forward(140)

        #roue avant
        left(86),forward(20),right(22),forward(56),right(67),forward(50),right(67),forward(6),right(94),forward(47),left(47),forward(40),left(26),forward(62),left(27),forward(42),left(64),forward(71),left(60),forward(50),left(125),forward(15),right(77),forward(115)

        #parechock
        backward(20),right(108),forward(215),left(120),forward(40),right(120),forward(140),right(115),forward(38),left(115),backward(110),forward(190)

        #aeration parchock
        backward(45),penup(),right(90),forward(7),pendown(),right(90),forward(190),left(120),forward(10),right(120),penup(),forward(40),pendown(),forward(60),left(95),forward(20),left(85),forward(50),left(55),forward(25),right(55)
        penup(),forward(35),pendown(),right(60),forward(50),left(60),forward(130),left(60),forward(60),left(30),penup(),forward(7),pendown(),right(90),forward(45)
        
        #parechock
        right(90),backward(10),forward(42),right(90),forward(10),right(60),forward(20),right(120),forward(20),right(90),forward(17),right(90),forward(5),left(85),forward(50),right(86),forward(30),forward(160),left(5),forward(170),backward(170),right(5),backward(160),left(86),forward(40),right(25),forward(20),right(60),forward(57),right(50),forward(20),right(30),forward(40),backward(40),left(80),forward(30),right(85),forward(40),backward(25),left(85),forward(210),right(180),color(255,255,255),pensize(2)

Nous avons dit que les batiments etaient longs? Et bien ce n’est rien a coté de cette subaru. Cette subaru a été bètement dessiné

logo()

def logo():
    pensize(4)



    def etoile_logo_main():  
        left(10),forward(60),left(60),forward(40),right(140),forward(40),left(60),forward(60),right(160),forward(60),left(60),forward(40),right(140),forward(40),left(60),forward(60),right(160),forward(60),right(10)
    
    
    def etoile_logo():    
        left(10),forward(30),left(60),forward(20),right(140),forward(20),left(60),forward(30),right(160),forward(30),left(60),forward(20),right(140),forward(20),left(60),forward(30),right(160),forward(30),right(10)
    
    color(255,255,0)
    for i in range(2):
        xetoile = [740,760,680,625,710]
        nbx = len(xetoile)
        yetoile = [400,350,350,305,310]
        nby = len(yetoile)
        for i in range(5):
            penup(),goto (xetoile[i%nbx],yetoile[i%nby]),pendown(),etoile_logo(),penup(),goto (560,380),pendown(),etoile_logo_main()
        pensize(2),color(255,255,255)

Afin de réaliser le logo Subaru nous avons créé deux fonction qui sont aussi simple que la subaru etoile_logo_main() qui correspond a la plus grande étoile et etoile_logo() a la plus petite. Avec goto() on a placer les etoiles a différentes coordonées.

Fin de script

if flash:
    wn.update() 

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()

Ce script permet generer l’image final en .ps puis a la convertir en .png avec un nom aléatoir evitant que l’image précdédemment généré soit écrasé.

Script complet

from turtle import *
from random import randint


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 = "Bastien.S"
title(titre+" | Subaru Impreza WRC")
setup(1920,1080)

speed(0)
hideturtle()
flash = True 
if flash:
    wn = Screen()
    wn.tracer(0)


# ============== MON SCRIPT PYTHON ==============
colormode(255)


def logo():
    pensize(4)



    def etoile_logo_main():  
        left(10),forward(60),left(60),forward(40),right(140),forward(40),left(60),forward(60),right(160),forward(60),left(60),forward(40),right(140),forward(40),left(60),forward(60),right(160),forward(60),right(10)
    
    
    def etoile_logo():    
        left(10),forward(30),left(60),forward(20),right(140),forward(20),left(60),forward(30),right(160),forward(30),left(60),forward(20),right(140),forward(20),left(60),forward(30),right(160),forward(30),right(10)
    
    color(255,255,0)
    for i in range(2):
        xetoile = [740,760,680,625,710]
        nbx = len(xetoile)
        yetoile = [400,350,350,305,310]
        nby = len(yetoile)
        for i in range(5):
            penup(),goto (xetoile[i%nbx],yetoile[i%nby]),pendown(),etoile_logo(),penup(),goto (560,380),pendown(),etoile_logo_main()
        pensize(2),color(255,255,255)



def background():
    r = 30
    g = 30
    b = 30
    y = 540
    x = 0
    for i in range(50):
        pensize(10),color(r,g,b),penup(),goto(-960,y),pendown(),forward(1920)
        y = y - 8
        b = b + 1
        r = r + 1 
    goto(-960,y)

    for i in range(37):
        pensize(10),color(r,g,b),penup(),goto(-960,y),pendown(),forward(1920)
        y = y - 10
        g = g + 2
        r = r - 1
    goto(-960,y)

    for i in range(90):
        pensize(7),color(35,35,45),penup(),goto(-960,y + 1),pendown(),forward(1950)
        y = y - 7
def batiments():   
    pensize(2)
    penup()
    goto(-960,-226)
    pendown()
    forward(100)
    color(20,20,20),forward(360),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(620),end_fill(),left(90),backward(80),begin_fill(),left(90),forward(650),left(90),forward(120),left(90)
    forward(40),right(70),forward(60),left(70),forward(592),end_fill(),backward(2),left(90),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(624),end_fill(),left(90),backward(260),color(30,30,30)
    begin_fill(),left(90),forward(640),left(100),forward(240),left(80),forward(599),end_fill(),left(90),forward(240),begin_fill(),left(90),forward(640),right(100),forward(240),right(80),forward(599),end_fill()
    left(90),forward(350),begin_fill(),left(90),forward(640),left(100),forward(240),left(80),forward(599),end_fill(),left(90),forward(240),begin_fill(),left(90),forward(640),right(100),forward(100),right(80),forward(620)
    end_fill(),color(20,20,20),begin_fill(),left(90),forward(1),left(90),forward(350),right(45),forward(80),right(95),forward(60),left(50),forward(35),left(25),forward(50),right(115),forward(383),end_fill(),begin_fill()
    left(180),color(25,25,25),forward(430),right(100),forward(80),right(80),forward(415),end_fill(),left(90),begin_fill(),color(15,15,15),forward(3),left(90),forward(250),right(90),forward(80),left(45),forward(20),right(45)
    forward(15),left(90),forward(60),right(90),forward(100),right(90),forward(325),end_fill(),left(90),backward(20),color(25,25,25),begin_fill(),left(90),forward(230),right(95),forward(100),left(95),forward(110),right(80)
    forward(100),right(55),forward(10),right(45),forward(342),end_fill(),begin_fill(),left(90),backward(15),left(90),color(10,15,15),forward(300),right(92),forward(120),right(88),forward(20),left(90),forward(20),right(90)
    forward(275),end_fill(),color(25,25,25)
    left(180),begin_fill(),forward(275),right(90),left(80),forward(20),right(65)
    forward(200),right(15),forward(100),right(90),forward(360),end_fill(),left(90)

t = -200
u = -330
def subaru():
    color(0,150,250)
    pensize(7)
    for i in range(2):
        penup()
        goto(u,t)
        pendown()

        #roue arriere
        left(106),forward(95),left(60),forward(30),left(50),forward(30),backward(30),right(50),backward(30),right(60),forward(25),left(85),forward(40),left(65),forward(25),left(2),forward(30),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),left(37),forward(40)

        #arriere voiture
        right(155),forward(75),right(55),forward(20),left(45),forward(45),right(45),forward(50),right(25),forward(40)

        #aileron
        left(160),forward(30),right(80),forward(30),right(100),forward(60),backward(60),left(100),forward(8),right(100),forward(60),backward(60),left(80),forward(5),left(10),left(90),forward(20),left(90),forward(50),left(90),forward(35),left(20)
        
        #plafond
        forward(20),left(30),forward(80),right(22),forward(65),right(24),forward(85),right(9),forward(185),right(17),forward(70),backward(20)

        #parebrise
        right(165),forward(70),left(5),forward(145),left(112),forward(95)


        #capot
        left(50),forward(140),right(15),forward(35),left(5)

        #phare
        right(55),forward(32),backward(32),right(85),forward(35),left(90),forward(25),left(80),forward(120),left(110),forward(25),left(65),forward(85),right(10)

        #capot
        left(155),backward(35),left(20),backward(140),left(18),forward(150),left(35),backward(10),forward(20),right(35),forward(110),right(50),forward(10),backward(5),left(50),forward(15),right(40),backward(110) ,forward(110),left(23),forward(130),right(20),forward(50),right(35)


        #phare droit
        forward(20),right(10),forward(10),right(100),forward(60),right(100),forward(20),right(75),forward(50),penup(),goto(u,t),right(2),pendown()

        #roue arriere
        left(106),forward(95),left(60),forward(30)

        #dessus du peneu
        left(50),forward(30),backward(30),right(50),backward(30),right(60),forward(25),left(85),forward(40),left(65),forward(25)

        #jante
        left(2),forward(30),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),left(37),forward(40),left(37),forward(70),left(65),forward(55),left(60),forward(70)
        
        #bas de caisse
        right(58),backward(25),forward(190)

        #roue avant
        left(86),backward(45),right(78),forward(33)

        #jante
        penup(),left(85),forward(90),left(170),pendown(),left(10),forward(45),left(24),forward(40),left(90),forward(35),left(62),forward(60),left(45),forward(35),left(90),forward(37),penup(),left(48),forward(84),pendown(),left(96),backward(33),left(78),forward(112)

        #portiere
        left(10),forward(50),right(20),forward(55),left(35),forward(95),left(60),forward(75),left(35),forward(85),left(30),forward(70),left(124),forward(220),backward(140),left(67),forward(100),backward(180),right(140),forward(80),left(73),forward(140)

        #roue avant
        left(86),forward(20),right(22),forward(56),right(67),forward(50),right(67),forward(6),right(94),forward(47),left(47),forward(40),left(26),forward(62),left(27),forward(42),left(64),forward(71),left(60),forward(50),left(125),forward(15),right(77),forward(115)

        #parechock
        backward(20),right(108),forward(215),left(120),forward(40),right(120),forward(140),right(115),forward(38),left(115),backward(110),forward(190)

        #aeration parchock
        backward(45),penup(),right(90),forward(7),pendown(),right(90),forward(190),left(120),forward(10),right(120),penup(),forward(40),pendown(),forward(60),left(95),forward(20),left(85),forward(50),left(55),forward(25),right(55)
        penup(),forward(35),pendown(),right(60),forward(50),left(60),forward(130),left(60),forward(60),left(30),penup(),forward(7),pendown(),right(90),forward(45)
        
        #parechock
        right(90),backward(10),forward(42),right(90),forward(10),right(60),forward(20),right(120),forward(20),right(90),forward(17),right(90),forward(5),left(85),forward(50),right(86),forward(30),forward(160),left(5),forward(170),backward(170),right(5),backward(160),left(86),forward(40),right(25),forward(20),right(60),forward(57),right(50),forward(20),right(30),forward(40),backward(40),left(80),forward(30),right(85),forward(40),backward(25),left(85),forward(210),right(180),color(255,255,255),pensize(2)



def road():
    color(100,100,100),pensize(7)
    for i in range(2):
        liste_longueur_bandes1 = [2,10,6,10,60,150,]
        liste_longueur_bandes2 = [1,4,7,16,75,220]
        liste_longueur_bandes3 = [2,10,10,12,100,200]
        liste_longueur_bandes4 = [1,4,8,15,25,97]
        liste_longueur_distance_bandes = (1,3,6,9,20,40)
        liste_angle_gauche = [15,20,25,30,43,85]
        liste_angle1 = [90,50,45,35,45,85]
        liste_angle2 = [90,135,135,155,155,133]
        liste_angle3 = [90,70,40,20,25,45]
        liste_angle4 = [90,105,140,150,135,97]
        nblb1 = len(liste_longueur_bandes1)
        nblb2 = len(liste_longueur_bandes2)
        nblb3 = len(liste_longueur_bandes3)
        nblb4 = len(liste_longueur_bandes4)
        nbldb = len(liste_longueur_distance_bandes)
        nba = len(liste_angle_gauche)
        nba1 = len(liste_angle1)
        nba2 = len(liste_angle2)
        nba3 = len(liste_angle3)
        nba4 = len(liste_angle4)
        penup(),goto (-540,-226),pendown()  
        for i in range(6):
            right(liste_angle_gauche[i%nba])
            forward(liste_longueur_bandes1[i%nblb1])
            left(liste_angle1[i%nba1])
            forward(liste_longueur_bandes2[i%nblb2])
            left(liste_angle2[i%nba2])
            forward(liste_longueur_bandes3[i%nblb3])
            left(liste_angle3[i%nba3])
            forward(liste_longueur_bandes4[i%nblb4])
            left(liste_angle4[i%nba4])
            forward(liste_longueur_bandes1[i%nblb1])
            penup()
            forward(liste_longueur_distance_bandes[i%nbldb])
            pendown()
            left(liste_angle_gauche[i%nba])

        color(255,255,255)
        pensize(2)

#calque ===================================
background()
batiments()
road()
subaru()
logo()

#GENERER DES IMAGES AUTOMATIQUEMENT ==============

if flash:
    wn.update() 

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()

Télécharger mon script

Le rendu final