Author: Thomas S.

Tutoriels

Comment allumer et accéder à son ordinateur à distance

Vous avez un puissant ordinateur fixe chez vous ? Une connexion internet satisfaisante ? Et vous aimeriez entièrement contrôler votre ordinateur à distance pour profiter de la puissance de celui-ci ? Et bien sachez qu’allumer et prendre le contrôle de cet appareil est aujourd’hui possible, sur tous vos appareils : ordinateur portable, téléphones, tablettes, etc.

Présentation

En lisant ce tutoriel, vous allez :

  • configurer le Wake-On-Lan (WOL) : un standard des réseaux Ethernet qui permet à un ordinateur en veille ou éteint d’être démarré à distance1 ;
  • configurer son routeur pour permettre le démarrage de son ordinateur via internet ;
  • découvrir une liste de logiciels qui permettent d’allumer son ordinateur à distance à l’aide de WOL ;
  • découvrir une liste de logiciels accordants l’accès et le contrôle de son ordinateur ;
  • installer et configurer un logiciel en particulier comme exemple (Parsec qui fonctionne pour MacOS et Windows).

Avant toute chose, voici des précisions concernant quelques limitations en rapport avec mon tutoriel :

  • La configuration du WOL est décrite pour Windows. Dans la suite de l’article, vous trouverez des liens vers des tutoriels pour le faire sur MacOS. Veuillez noter qu’après quelques recherches, le support du WOL sur MacOS est dit « bizarre », il ne fonctionnerait pas tout le temps. Je ne peux pas essayer de mon côté, donc si cela ne fonctionne pas, je suis navré pour vous ;
  • Je ne peux pas vous montrer la configuration du logiciel Parsec sur MacOS, mais le système étant réputé comme simple d’utilisation, vous devriez y arriver en suivant mes indications générales ;
  • Les listes de logiciels pour allumer son ordinateur à distance ou pour y accéder contiendront des logiciels que je n’ai pas essayé par moi-même, mais rassurez-vous, vous pourrez trouver bon nombre de tutoriels en ligne concernant ceux-ci (je mettrai en lien des tutoriels pour que vous n’ayez pas à chercher). Je ne suis pas responsable de problème.s avec des logiciels présent dans la liste, notamment sur les produits de la marque Apple (je pense notamment aux logiciels pour allumer son ordinateur à distance).

Configurer le Wake-On-Lan (WOL) sur son ordinateur

Windows

1. Vérifier que le paramètre est activé dans le BIOS :

Vous devez vous assurer que le Wake-On-Lan est activé dans les paramètres de votre carte mère. Pour cela vous devez vous rendre dans le BIOS (interface permettant de configurer sa carte mère), puis rechercher dans tous les paramètres un paramètre qui a un nom similaire à « Wake-On-Lan ». Pour accéder au BIOS, il faut lors du démarrage de l’ordinateur (entre le moment où vous appuyez sur le bouton et le moment où vous voyez le logo Windows apparaître) appuyer à plusieurs reprises sur l’une des touches de votre clavier parmi celles-ci : Suppr ; F2 ; F12. En effet, cette touche dépend de votre carte-mère. Soit vous appuyez à plusieurs reprises sur toutes les touches en même temps, soit vous recherchez sur internet quelle touche permet d’accéder au BIOS. La recherche internet ressemblerait à ce qui suit :

[Marque de la Carte Mère] [Modèle de la carte mère] accéder au BIOS

Note : Et si je ne connais pas le modèle de ma carte mère ni la marque qui l’a produite ? – Si c’est un ordinateur portable, vous pouvez mettre la marque puis le modèle du pc portable et « accéder au BIOS » (si vous ne trouvez rien, cherchez en anglais). Pour les ordinateurs fixes2 :

  1. Appuyez simultanément sur les  touches Windows + R ;
  2. Entrez le code suivant : msinfo32 puis Entrée ;
  3. Une fenêtre d’affichage avec les informations du système Windows, consultez les éléments fabricant, produit, version de la carte de base.

Une fois que vous avez accès au BIOS, veuillez noter que chaque BIOS est différent, ainsi je vous suggère de faire une recherche sur internet comme suit :

[Marque de la Carte Mère] [Modèle de la carte mère] Wake On Lan BIOS settings

Suite à cela, vous pourrez trouver soit des articles, soit mieux, des vidéos qui vous montreront avec des images qui correspondent à votre BIOS. Internet regorge de ressources pour cela, vous devriez trouver sans crainte.

Voici des images d’illustrations. Ici est représenté le BIOS de la carte mère Gigabyte B550M-DS3H :

2. Activer le paramètre dans Windows :

Pour ce faire, dans la barre de recherche, écrivez « Panneau de configuration ».

Appuyez sur la touche Entrée, puis allez dans la catégorie « Réseau et Internet », puis dans « Centre Réseau et partage ». Regardez l’image ci-dessous. Dans « Afficher vos réseaux actifs » se trouvent la liste de toutes vos interfaces réseaux. Choisissez quelle interface sera utilisée : votre wifi, votre connexion filaire, etc. Sur cette image on constate qu’il n’y a qu’une seule interface. Donc on choisit celle-ci. Notez que vous pouvez toujours répéter les mêmes étapes pour chaque interface afin d’être sûr que ça fonctionne partout.

Note : Si votre réseau wifi ou votre connexion filaire n’est pas directement relié à votre box, cela posera problème pour l’étape de configuration de la box internet. Renseignez vous auprès de votre administrateur réseau pour avoir l’information.

Il faut donc cliquer là où c’est souligné sur l’image.

Puis, cliquez sur Propriété, puis Configurer puis Avancé et dans cette liste, cherchez « Wake on Magic Packet » (Traduis en français : « Réveil par paquet magique »). Une fois trouvé, à droite il y a « Valeur ». Définissez la sur Enable (ou « Activé »). Une fois cela fait, cliquez sur OK.

MacOS

Comme dit au début de ce tutoriel, le support du WOL sur MacOS est dit « bizarre », il ne fonctionnerait pas tout le temps. Je ne peux pas essayer de mon côté, je vous fournis les liens, à vous d’essayer de de bidouiller pour que ça fonctionne :

Maintenant, passons à la configuration du routeur.

Configuration du routeur pour permettre un démarrage via internet

Avant toute chose, il est important que vous vérifiez comment est construit votre réseau là où vous vous situez.

  • Si votre ordinateur est directement relié à la box internet, par câble, par wifi, ou même par répéteur/routeurs qui servent uniquement à amplifier le réseau, alors vous n’aurez qu’à configurer la box. Si vous n’êtes pas en possession de cette information, veuillez vous rapprocher de votre administrateur réseau.
  • Si votre ordinateur n’est pas directement relié à la box internet mais qu’il transite via un sous-réseau au réseau de votre box (via un routeur configuré comme tel), la tâche est plus ardue et ne sera pas explicitement décrite ici. Dans l’idée, vous devez répéter l’étape réalisée sur la box sur le routeur qui contrôle le sous-réseau, de sorte qu’un port soit « visible » sur le réseau de la box et donc de rendre « visible » ce port sur internet. Pour ce cas particulier plus complexe, veuillez vous référer à votre administrateur réseau (ou à internet avec vos précieuses recherches).

Admettons que nous sommes dans le 1er cas décrit : votre ordinateur est directement relié à votre box internet.

Sur Windows, veuillez vous rendre à nouveau dans le Panneau de configuration, Réseau et Internet, Centre de réseau et partage, cliquer sur l’interface que vous allez utiliser pour le WOL, puis cette fois-ci cliquer sur Détails… plutôt que Configurer. Ici vous avez plein d’informations. Notez quelque part celles-ci :

  • Adresse physique (également appelé adresse MAC) : sous la forme XX-XX-XX-XX-XX-XX
  • Adresse IPv4 : sous la forme xxx.xxx.xxx.xxx
  • Passerelle par défaut IPv4 : sous la forme 192.168.xxx.xxx

Maintenant, ouvrez une page internet et mettez l’adresse IP qui était sur la même ligne que « Passerelle par défaut IPv4 » puis appuyez sur Entrée.

Vous tombez sur la page d’administration de votre box internet. Il va vous falloir un mot de passe que votre administrateur réseau doit connaître pour vous connecter. Une fois cela fait, vous allez devoir rendre accessible sur internet un port qui sera utilisé pour allumer votre ordinateur.

Vous allez avoir différents liens selon votre box internet, mais ces liens vont vous expliquer comment rendre accessible un port quelconque sur internet (dit autrement « ouvrir un port quelconque de votre box internet »). Vous devrez suivre à la lettre la vidéo sauf que vous devrez choisir le port 7 ou 9. Il existe deux ports pour le WOL, donc choisissez-en un arbitrairement, et si lorsque vous essaierez d’allumer votre pc à distance et que cela ne fonctionne pas, considérez parmi les problèmes possibles le port utilisé, et donc tentez celui que vous n’avez pas choisi.

  • SFR :
    • Il prend exemple pour un serveur Minecraft, remplacez juste 25565 par 7 ou 9. Concernant les protocoles, mettez soit « UDP » soit « les deux » ;
    • La vidéo
  • Free :
    • remplacez le port 80 par 7 ou 9. Plus tôt dans l’article, vous avez noté l’adresse IP de votre ordinateur ;
    • La vidéo
  • Orange
    • il parle beaucoup pour rien dire, mais c’est la plus claire – ATTENTION LE SON EST TRÈS FORT AU DÉBUT DE LA VIDÉO ;
    • la partie qui nous intéresse commence à 5:32, partez du principe qu’il ne parle pas de l’xbox mais d’un pc, faites donc les mêmes manipulations pour votre pc ;
    • notez que vous n’êtes pas obligé de renommer votre pc et qu’il suffit de vous rappeler du nom de celui-ci ;
    • A 7:42, quand il commence à remplir les informations, mettez le nom que vous voulez, il sert uniquement à le retrouver dans la liste des ports « ouverts ». Pour le port interne et externe, mettez bien 7 ou 9, pour les protocoles, mettez soit « UDP », soit « les deux », choisissez votre pc à la place de l’xbox (si le pc n’est pas listé, vous l’avez mal ajouté dans l’onglet DHCP) et si vous avez un onglet supplémentaire « IP externe », laissez vide ;
    • Après 8:00, la vidéo ne nous intéresse plus, vous avez fini vos manipulations ;
    • La vidéo
  • Si vous avez une autre box, ou en tout cas un panel administrateur différent, je vous suggère de chercher comme suit sur un moteur de recherche :
    • [Opérateur] [Nom de la box] [Version de la box] ouverture port
    • Ajoutez après port « nat » ou « nat/pat » si vous ne trouvez rien

En cas de doutes, rapprochez-vous de votre administrateur réseau.

Une fois le PC configuré, de même pour la box, passons à la suite !

Logiciels pour allumer son ordinateur à distance

Voici une liste de logiciels pour démarrer son ordinateur à distance :

  • Windows : Wake On Lan
  • Linux : 😂 – Vous voulez pas qu’on vous tienne la main aussi… Bon bon ok : lien 😒 ou lui
  • Mac OS : lien (je n’ai pas pu tester, alors attention)
  • Android : lien Play store (Remarque : Quand vous ajoutez une connexion, choisissez le petit nuage et ne vous occupez pas des 2 dernières cases à remplir)
  • iOS : lien Apple store (je n’ai pas pu tester, alors attention)

Dans la majorité des logiciels, qui font plus ou moins peur dus à leur choix de design plus ou moins douteux, vous devrez fournir les informations suivantes :

  • Le nom de l’appareil : n’a aucune utilité autre que vous permettre d’identifier pour vous à quel appareil correspond cette configuration ;
  • Le port utilisé (pas de panique si ce n’est pas à précisé, c’est sûrement que par défaut le logiciel va utiliser le port 7 ou 9 ou les deux) ;
  • L’adresse physique/l’adresse MAC ;
  • l’adresse IP du routeur/nom d’hôte : votre adresse IP publique, qui peut changer de temps en temps : vous pouvez la retrouver en allant sur ce site par exemple.

N’hésitez pas à faire un test en éteignant votre ordinateur, en vous branchant en connexion LTE (4G, 5G) en partage de connexion ou avec le logiciel pour téléphone mobile et en essayant d’allumer votre ordinateur. Si cela ne fonctionne pas, rendez-vous dans la partie Si ça ne fonctionne pas…

Logiciels pour accéder et contrôler son ordinateur à distance

Il existe une multitude de logiciel pour faire ceci, voici une courte liste des plus connus :

Il existe même des manipulations plus complexes mais plus performantes et qui fonctionnent même sur linux (😱) à base de création de réseaux privés virtuels et de logiciels de diffusions…

Un exemple de logiciel : Parsec

Parsec est un logiciel parmi tant d’autres. Il permet l’host sur Windows et Mac OS. « Host » veut dire que l’ordinateur se place en tant qu’appareil sur lequel on peut se connecter. C’est un hôte.
A contrario, le client signifie les appareils qui se connectent aux hôtes. Le client existe sur Windows, Mac OS, Linux, Android, et Web.

Suivez ce lien pour télécharger l’application.

Suivez l’installeur qui vous guide dans l’installation.

Remarque 1 : Si l’installeur vous demande si vous souhaitez cocher « Virtual Display Driver » (ou nom similaire), vous pouvez le cocher, c’est utile pour certaines fonctionnalités du logiciel.

Remarque 2 : L’installeur vous proposera un choix entre « Per User » et « Shared » si vous êtes sur un appareil hôte (windows par ex), VOUS DEVEZ INPERATIVEMENT CHOISIR « Shared » !

Une fois l’installation achevée, le logiciel se lance automatiquement (lancez le si ce n’est pas le cas), puis cliquez sur « Sign Up » si vous n’avez pas de compte. Cela va vous rediriger vers une page internet, suivez toutes les étapes pour créer un compte, vérifier l’email, etc. puis connectez-vous sur l’application.

Une fois que vous êtes connecté, l’interface ressemblera à celle-ci.

Cliquez sur l’engrenage à gauche, entouré en bleu dans les images précédentes. C’est là que vous verrez une différence entre les différentes versions de Parsec (selon la plateforme). En effet, seuls les appareils hôtes ont la catégorie « Host », et les clients entre-eux n’ont pas les mêmes paramètres.

Nous n’allons pas aller plus loin au niveau des paramètres, le site de parsec contient un support (article) très complet qui explique tout parfaitement et clairement. Pour la démonstration nous allons laisser les paramètres par défaut et tenter une connexion.

Tips : Allez tout de même jeter un coup d’œil dans la catégorie « Hotkeys » qui liste quelques raccourcis utiles, et gardez en mémoire les premiers raccourcis : « Disconnect » et « Menu ».

Remarque : Sachez que parmi les paramètres, il y en a qui peuvent aider à optimiser la connexion entre les 2 appareils sans perdre de qualité et de fluidité, et pouvant l’améliorer selon votre connexion et selon vos appareils. Il est donc intéressant que vous vous y intéressiez dans un second temps.

Il faut que Parsec soit démarré sur les deux machines et que vous vous soyez connecté (avec le même compte ou pas car il y a un système d’amis et de liens de partages, mais c’est plus simple avec le même compte puisque c’est pour un usage personnel).

Sur votre client, vous allez voir votre ordinateur hôte apparaitre dans la liste :

Vous allez pouvoir cliquer sur « Connect » (ou « Connecter »), et après un temps de chargement, ça y est vous êtes connecté et vous pouvez utiliser votre ordinateur à distance. En haut à gauche est présente une petite icône qui vous permet de changer quelques paramètres, passer en mode immersif, etc. Évitez de faire dis paître cette icône (il y a un bouton qui masque l’icône, évitez de l’utiliser), pour que le menu se ferme, il suffit de cliquer n’importe où sur l’écran autre que sur le menu que la petite icône a ouvert quand vous avez cliqué dessus. Si vous l’avez quand même fermé par mégarde, plusieurs solutions :

  • le raccourci pour se déconnecter, si vous vous en souvenez ou même mieux, le raccourci pour faire réapparaitre la petite icône ;
  • vous rendre sur internet et crier au secours auprès de google, le support (article) de parsec et les forums communautaires vous donneront des conseils (vous devriez trouver réponse à vos questions, ce logiciel a une communauté) ;
  • vous avez accès au logiciel sur l’hôte ! Et bien oui, vous avez tout le contrôle, et notamment le contrôle du logiciel, et si vous cliquez ici, vous pouvez vous kick :

Conclusion

Et bien voilà, il ne vous reste plus qu’à tout tester, c’est-à-dire éteindre votre ordinateur hôte, vous mettre en connexion 4G (par exemple), tenter de démarrer l’ordinateur, confirmer qu’il s’allume bien. Je vous conseille d’essayer lorsque vous mettez l’ordinateur en veille, puis lorsque vous l’arrêtez. Puis, assurez-vous à distance (ne touchez pas à l’ordinateur hôte, l’objectif est qu’il fasse tout les démarrages tout seul, comme si vous n’étiez pas devant l’ordinateur) que le logiciel Parsec a fini par se lancer et que l’ordinateur est bien affiché dans la liste des ordinateurs hôtes. Finalement, tentez de vous connecter, et si ça fonctionne, c’est gagné !

Merci d’avoir lu ce tutoriel, il reste la catégorie juste en dessous qui répertorie quelques problèmes, sinon je vous invite à rechercher méthodiquement sur internet ou demander à une intelligence artificielle de le faire pour vous.
Vous retrouverez les sources utilisées en dernière catégorie de cet article.

Si ça ne fonctionne pas…

S’il y a un ou plusieurs problèmes, tentez ces différentes solutions (une par une, dans l’ordre que vous voulez) :

  • Vérifier les paramètres dans le BIOS du PC, ainsi que les paramètres Windows ;
  • Vérifier les paramètres dans la box internet :
    • Changer le port ouvert en le remplaçant par le port que vous n’avez pas choisi entre 7 et 9 ;
    • Changer le protocole (Si vous avez choisi « UDP », mettez « les deux », si vous avez choisi « les deux », mettez « UDP ») ;
    • Vérifier que l’adresse IP de l’ordinateur ou le nom de l’ordinateur soit correct.e ;
    • Assurez-vous d’avoir bien suivi chaque étape des tutoriels vidéos ainsi que mes commentaires pour chacune d’entre-elles ;
  • Vérifier les informations indiquées dans le logiciel pour allumer votre ordinateur à distance :
    • Adresse MAC de l’ordinateur (que vous avez normalement noté) ;
    • L’adresse IP publique de votre box internet (celle qui vous identifie sur internet) : il est possible que l’adresse ait changé, rendez-vous sur ce site pour vous en assurer ;
  • Pour le moindre problème en rapport avec Parsec :
    • Rendez-vous sur le support (article) officiel
    • Le reddit
    • Chercher comme ceci une information :
      • Parsec [problème décrit en anglais, explication concise, qu’avec des mots clés] [Système d’exploiration]
      • Au pire demandez à une IA 😆 (Bing Copilot qui a accès à internet par exemple)
    • Si vous avez un problème d’écran noir quand vous vous connectez à un ordinateur à distance : ça ou ça

Sources

Projets

Un météorologue personnel en briquette !

Qui n’a jamais rêvé d’avoir un robot en LEGO qui lui annonce la météo ? Et bien même si ce n’est pas le cas, nous l’avons fait pour vous ! Venez découvrir un robot capable de comprendre son environnement pour vous donner la météo.

Fonctionnalités du robot

Notre robot au doux nom de ROBKEY est capable de :

  • déplacer ses bras et son bassin ;
  • reconnaitre l’endroit où il se trouve pour donner précisément la météo ;
  • afficher l’heure, la météo et la température ambiante ;
  • d’avoir quelques réactions faciales ;
  • et bien plus.

La conception du robot

Pour concevoir notre robot, nous avons dû prendre en compte plusieurs choses. Tout d’abord, les moteurs n’ont pas été particulièrement dur à installer car il ne font que la moitié de la taille de l’esp 32. Il nous a donc paru évident de mettre les moteurs des bras dans le torse du robot et le moteur du bassin dans le châssis de ses chenilles.

Ensuite il a fallu installer planche de test qui a eu plusieurs positions possibles. Premièrement dans son dos car cela aurait permis de pouvoir faire tourner le bassin du robot à 360°, mais les câbles auraient difficilement bien tenu à l’esp 32 et au robot lui-même. Nous nous sommes finalement entendu à l’idée de mettre la planche sur la batterie des chenilles bien que cela empêche le robot de faire des tours sur lui même.

Maintenant, le plus important : le placement de l’ESP32. Nous avions deux idées, l’une le plaçait dans le torse du robot, l’autre faisait en sorte qu’il soit la tête légèrement rentrée dans les épaules. Nous avons opté pour la seconde option car celle-ci nous permet d’afficher un petit visage sur l’écran du microcontrôleur.

Pour conceptualiser l’apparence de notre robot, nous avons donc réalisé un schéma en 3D très simple sur Paint 3D en regroupant nos idées pour imaginer ce à quoi il ressemblera.

Construction de la structure du robot

Pour construire le robot, j’ai (Sylvain) commencé par regarder les constructions Lego que j’avais précédemment réalisées et qui pouvaient être détruite pour commencer à récupérer leurs pièces. Avec toutes ses matières premières je me suis laissé porter par mon imagination pour construire le LEGO le plus ressemblant à un robot en essayant de faire en sorte qu’il soit plutôt résistant (bon d’accord j’ai peut-être failli à cette tâche).

C’est grâce aux joies de la maladie que j’ai pu entamer la construction. Pour commencer, j’ai récupéré le châssis d’une autochenille radiocommandée en la modifiant pour la rendre plus compacte et en laissant un espace pour le moteur du bassin.

Ensuite j’ai commencé à faire ledit bassin, que j’élargis à la fin de la construction car je l’avais fait trop fin. Suivi du torse, le plus simple car il devait être creux pour laisser la places aux câbles et aux moteurs. Il fallait aussi préparer les trous pour les axes des bras.

Après j’ai fait les bras qui sont vraiment très simplistes mais à ce moment je commençais sérieusement à manquer de pièces plus techniques et même des plus simples pour faire quelque chose de plus sympathique. Mais quoi qu’il en est l’un des deux bras représente un soleil pour quand il fait beau, tandis que l’autre représente un ciel nuageux.

Pour finir j’ai réalisé la cage de la planche de test et solidifié les éléments les moins solides et résolu les quelques problèmes mécaniques rencontrés lors des premiers tests des moteurs.

L’électronique du robot

En parallèle de la construction du LEGO, je (Thomas) me suis lancé dans la conception électronique de celui-ci.

Pour cela, j’ai d’abord listé tout ce que je voulais intégrer à l’électronique :

  • 2 boutons,
  • 1 capteur de température,
  • 3 moteurs.

Pour m’aider dans la réalisation électronique, je me suis aidé de tous ces sites :

Allez c’est parti !

On commence par le branchement des boutons :

Les câbles blancs (entourés en rouge) récupèrent l’information de la pression du bouton et les câbles noirs (entourés en vert) s’occupe de fermer le circuit (de l’électricité passent dans le bouton, et il faut que l’électricité puisse faire une boucle). Si vous voulez, les boutons reçoivent de l’énergie par les câbles blancs et l’expulsent par les câbles noirs.

Concernant le branchement du capteur :

A droite à quoi ressemble le capteur de température de face et à gauche son branchement. La câble de gauche, en blanc récupère les mesures du capteur, celui du milieu en marron, alimente positivement le capteur (le capteur reçoit de l’énergie par ce câble) et le câble noir à droite du câble marron lui ferme la boucle (le capteur expulse l’énergie par ce câble.)

Et pour finir, les moteurs ont 3 câbles :

Le câble orange sert à contrôler le moteur, le rouge à l’alimenter et le marron à fermer la boucle. On refait ça 3 fois puisqu’on a 3 moteurs.

On branche tout ceci à la planche de test puis à l’ESP32, et voilà montage terminé :

Programmation du robot

Maintenant que le robot est construit et le montage électronique assemblé, il faut passer à la programmation de l’ESP32. Veuillez noter que depuis l’écriture de ce qui suit, le code a bénéficié de quelques mises à jours. Vous retrouverez l’archive en fin d’article avec les fichiers à jours.

Tout d’abord, il faut coder les briques de bases, qui vont nous permettre de manipuler différents outils, capteurs, actionneurs, api, etc.

  • C’est pour cela que nous créons un fichier buttons.py qui contient une classe Button dans laquelle nous initialisons 4 boutons : les 2 du microcontrôleur et les deux boutons ajoutés. Dans cette classe, vous verrez que chaque boutons a des caractéristiques supplémentaires. En effet il est possible de rendre un bouton poussoir équivalent à un levier. Nous créons différentes fonctions pour récupérer ou modifier des informations en rapport avec les boutons.
from machine import Pin
from time import sleep

# Importer les modules est inutile car ils sont déjà importés dans boot.py

class Buttons():
    def __init__(self):
        #self.name = "t-display-s3"
        
        # NomDuBouton : [                    PinUtilisé                     ,    mode    , value ]
        #      1      : [ Pin 3 en mode INPUT avec une résistance Pull-Down ,   levier   ,   0   ]
        # 1 : [ Pin(3, mode=Pin.IN, pull=Pin.PULL_DOWN), 1, 0 ]
        
        # Note : le chiffre de value dans la liste n'est pas pris en compte si le bouton est en mode "poussoir" -> On ne peut pas mettre None car si on décide de changer le mode du bouton, la valeur devient importante.
        
        
        # Pour une raison inconnue, "left" et "right" ne fonctionne plus.
        self.list_button = {"left" : [Pin(0, Pin.IN, Pin.PULL_UP),0,1],
                            "right" : [Pin(14, Pin.IN, Pin.PULL_UP),0,1],
                            1 : [Pin(2, mode=Pin.IN, pull=Pin.PULL_UP),0,1],
                            2 : [Pin(3, Pin.IN, Pin.PULL_UP),0,1]
                            }


    def getButton(self, button):
        return self.list_button[button]
    
    def setButton(self, button, pin, mode, value=None): # Le set fait également add.
        self.list_button[button] = [pin,mode,value]

    def setMode(self, button, val:bool): # Ce mode change le mode du bouton -> soit "levier" soit "poussoir"
        if isinstance(val, bool) or val in (0,1):
            self.list_button[button][1] = val
            if not(val):
                self.list_button[button][2] = 1
            return print("Mode définie sur : " + str(self.list_button[button][1]))
        else:
            raise ValueError("val must be a boolean or a integer included between 0 and 1.")
    
    def setValue(self, button, value):
        if self.list_button[button][1]:
            self.list_button[button][2] = value
            return print("Valeur définie sur : " + str(self.list_button[button][2])) 
        else:
            print("Button must be a toogle button, not a push button.")
            return False
    
    def getValue(self, button): # Renvoie la valeur du bouton
        if not(self.list_button[button][1]): # Si le statut de mode_toogle est égal à 0 <=> Si le bouton est en mode "poussoir" et non "levier"
            return self.list_button[button][0].value()
        else:
            if not(self.list_button[button][0].value()):
                self.list_button[button][2] = 0 if self.list_button[button][2] else 1
                sleep(0.25)
            return self.list_button[button][2]
    
    def isButtonPressed(self,button): # Renvoie True si le bouton est pressé (donc si value = 0) et False sinon
        return not(self.getValue(button))
  • Continuons avec le fichier temperature.py dans lequel nous avons une simple fonction qui nous renvoie les données récupérées par le capteur de température et d’humidité.
from time import sleep  #Inutile car importé dans boot.py

def getTemperatureAndHumidity(capteur): # Capteur doit etre sous cette forme : capteur = dht.DHT11(Pin(17)) -> Ne pas oublier d'importer le module dht
    try:
        capteur.measure() # Met à jour les données de températures et d'humidités
        sleep(1)
        return (capteur.temperature(),capteur.humidity())
    except:
        print("Valeurs non récupérées")
        return False
  • Egalement, à l’aide des fichiers motor.py et servo.py (trouvé sur internet), nous créons des fonctions qui réaliseront des déplacements particuliers :
from servo import Servo
import time

motor=Servo(pin=12) # A changer selon la broche utilisée
motorbd=Servo(pin=10)
motorbg=Servo(pin=11)
 
def droit(t=1):
    motor.move(285)
    time.sleep(t)

def bassin(t=2):
    motor.move(265)
    time.sleep(t)
    motor.move(305)
    time.sleep(t)

def baissebg(t=0.5):
    motorbg.move(335)
    time.sleep(t)
    
def levebg(t=0.5):
    motorbg.move(270)
    time.sleep(t)

def baissebd(t=0.5):
    motorbd.move(335)
    time.sleep(t)
    
def levebd(t=0.5):
    motorbd.move(270)
    time.sleep(t)
    
droit()
  • Pour finir, à l’aide du fichier connection.py, nous créons plusieurs fonctions en rapport avec la partie sans-fil de l’ESP32.
import network
import st7789 #En théorie inutile car déjà importé dans boot.py
from time import sleep

def connect_to_wifi(display, font, ssid, mdp):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        display.init()
        display.draw(font,"Connexion a un point",0,111)
        display.draw(font,"d'acces en cours",15,126)
        wlan.connect(ssid,mdp)
        while not wlan.isconnected():
            pass
    display.fill_rect(0,107,170,25,st7789.BLACK)
    display.draw(font,'Connecte !',40,111)
    sleep(0.8)
    display.fill_rect(0,107,170,10,st7789.BLACK)
    display.deinit()

def search_wlan():
    station = network.WLAN(network.STA_IF)
    station.active(True)
    return station.scan()

Passons aux modules qui vont utiliser des apis :

  • En premier lieu, nous avons le fichier geoloc.py dans lequel nous utilisons l’api de google qui à l’aide des réseaux wifi aux alentours est capable de situer l’ESP32. Dans ce fichier est présent une fonction qui récupère les coordonnées géographiques de l’ESP32.
from modules.connection import search_wlan
import ustruct as struct
import urequests as requests
import ujson as json
import modules.api_txt as api_txt


def getLocation(api_key): # Avec Google maps API + sécurité sur le nombre de requête.    
    
    if int(api_txt.get_api_counter()[0]) > 24000:
        print("Quota de demande dépassé !!! Vous ne pouvez pas faire de requête...")
        return False
    
    list_wlan = search_wlan()
    data = {
        "considerIp": False,
        "wifiAccessPoints": []
    }

    for wifi in list_wlan:
        entry = {
            "macAddress": "%02x:%02x:%02x:%02x:%02x:%02x" % struct.unpack("BBBBBB", wifi[1]),
            "signalStrength": wifi[3],
            "channel": wifi[2]
        }
        data["wifiAccessPoints"].append(entry)
    
    headers = {"Content-Type": "application/json"}
    url = "https://www.googleapis.com/geolocation/v1/geolocate?key=" + api_key
    response = requests.post(url, headers=headers, data=json.dumps(data))

    api_txt.add_api_counter(0)

    return json.loads(response.content)["location"]
  • En second et dernier lieu, il reste le fichier meteo.py qui va être capable d’utiliser une api de météorologie pour récupérer, analyser et mettre en forme des données en rapport avec la météo.
import urequests
import modules.api_txt as api_txt

def get_meteo(latitude, longitude): # Sur la prochaine heure
    
    if int(api_txt.get_api_counter()[1]) > 10000:
        print("Quota de demande dépassé !!! Vous ne pouvez pas faire de requête...")
        return False
    
    url = "https://api.open-meteo.com/v1/forecast?latitude={0}&longitude={1}&current=temperature_2m,precipitation&daily=temperature_2m_max,temperature_2m_min,precipitation_sum&timezone=auto&forecast_days=3".format(latitude,longitude)
    json_meteo = urequests.get(url).json()
    
    api_txt.add_api_counter(1)
    
    return {"current":
            {"temperature":
             [
                 json_meteo["current"]["temperature_2m"],
                 json_meteo["current_units"]["temperature_2m"]
                 ],
             "precipitation":
             [
                 json_meteo["current"]["precipitation"],
                 json_meteo["current_units"]["precipitation"]
                 ]
             },
            "demain":
            {"temperature": [round((json_meteo["daily"]["temperature_2m_min"][1] + json_meteo["daily"]["temperature_2m_max"][1]) / 2, 1), json_meteo["daily_units"]["temperature_2m_min"]],
             "precipitation":
             [
                 json_meteo["daily"]["precipitation_sum"][1],
                 json_meteo["daily_units"]["precipitation_sum"]
                 ]
             },
            "apres-demain":
            {"temperature": [round((json_meteo["daily"]["temperature_2m_min"][2] + json_meteo["daily"]["temperature_2m_max"][2]) / 2, 1), json_meteo["daily_units"]["temperature_2m_min"]],
             "precipitation":[
                 json_meteo["daily"]["precipitation_sum"][2],
                 json_meteo["daily_units"]["precipitation_sum"]
                 ]
             }
            }

Passons à la gestion graphique, nous avons récupérer le module tft_config.py fournit par les développeurs du pilotes graphiques pour l’esp32. Celui-ci permet de créer facilement une gestion de l’écran avec les bonnes caractéristiques. Nous n’afficherons pas le code ici, car ce n’est pas nous qui l’avons codé. Vous pouvez le retrouver dans l’archive à la fin de cet article ou ici.

Nous avons créé le fichier affichage.py qui contient un certain nombre de fonctions pour réaliser le rendu graphique pour l’ESP32. Il contient également le code qui récupère des images pour les animations du visage et des icones. Ces dessins et animations ont été réalisé par Ilana, ancienne première NSI.

import st7789
from time import sleep, localtime
import modules.motor as motor

last_temps = -1

def display_time(display,font,x,y):
    global last_temps
    temps = localtime()
    if last_temps < temps[5]:
        display.png("/images/icones/horloge.png",x,y,True)
        display.fill_rect(x+30,y+5,60+6,10,st7789.BLACK)
        display.draw(font, str(temps[3]) + ":" + str(temps[4]) + ":" + str(temps[5]),x+30,y+10)
    last_temps = temps[5]

def display_meteo(display,font,infos_meteo, x, y):
    display.draw(font,str(infos_meteo["temperature"][0]),x,y)
    display.draw(font, font.LAST,x + display.draw_len(font,str(infos_meteo["temperature"][0])), y)
    display.draw(font, " C",x + display.draw_len(font,str(infos_meteo["temperature"][0])), y)
    
    display.draw(font,str(infos_meteo["precipitation"][0]),x+80,y)
    display.draw(font,str(infos_meteo["precipitation"][1]),x + 80 + display.draw_len(font,str(infos_meteo["precipitation"][0])),y)

def display_temperature(display,font,infos_temperature,x,y):
    display.fill_rect(x,y,70,20,st7789.BLACK)
    display.png("/images/icones/temperature.png",x,y,True)
    display.draw(font,str(infos_temperature) + " C",x+30,y+9)
    display.draw(font,font.LAST,x+30+display.draw_len(font,str(infos_temperature)), + y+9)    
    
def meteo_icon(display,icone,x,y):
    display.fill_rect(x,y,50,50,st7789.BLACK)
    if icone == "pluie":
        display.png("/images/icones/mauvais_temps.png",x,y,True) #Nuage pluie gris pas content
    else:
        display.png("/images/icones/beau_temps.png",x,y,True) # Soleil content
        

def meteo_widget(display,font,infos_meteo,x,y):
    display.fill_rect(x,y,170,200,st7789.BLACK)
    
    
    display.draw(font, "Auj.",x,y)
    display_meteo(display,font,infos_meteo["current"],x, y+20) #x,y+20)
    
    display.draw(font, "Dem.", x, y+40) #x+50, y)
    display_meteo(display,font,infos_meteo["demain"], x, y+60) #x+50,y+20)
    
    display.draw(font, "Apr-Dem.", x, y+80) #x+90, y)
    display_meteo(display,font,infos_meteo["apres-demain"], x, y+100) #x+90,y+20)

def main_menu(display,font,infos_temp,infos_meteo):
    display_time(display,font, 10, 111) # x = 52 pour un semblant de centrage
    display_temperature(display,font,infos_temp,10,151)
    
    if infos_meteo["current"]["precipitation"][0] > 0:
        icone = "pluie"
        motor.baissebg()
        motor.levebd()
    else:
        icone = "soleil"
        motor.baissebd()
        motor.levebg()
    
    meteo_widget(display,font,infos_meteo,10,191)
    meteo_icon(display,icone,110,111)

def animation(display,name:str,iteration:int,i_fixe:int): # list_anim : {"content":(2,1),"endormi":(4,1),"somnole":(3,1),"observe":(0,0),"monocle":(2,1)}
    display.fill_rect(0,0,170,105,st7789.BLACK)
    for i in range(2,iteration+1):
        display.png("/images/" + name + "/" + name + str(i) + ".png",0,0)
        if name == "endormi":
            sleep(0.3)
    for i in range(iteration,0,-1):
        display.png("/images/" + name + "/" + name + str(i) + ".png",0,0)
        if name == "endormi":
            sleep(0.3)
    display.png("/images/" + name + "/" + name + str(i_fixe) + ".png",0,0)
    

Pour finir nous avons le fichier api_txt.py qui s’occupe de gérer des fichiers de textes importants pour le fonctionnement du programme, présents dans le dossier data.

"""
api[0] => Google Maps API
api[1] => Météo API
"""

def get_api_counter():
    fichier_r = open("data/counter-api.txt",'r')
    liste = fichier_r.read().split(",")
    fichier_r.close()
    return liste

def add_api_counter(indice_api): # ne fonctionne qu'avec deux apis
    fichier_w = open("data/counter-api.txt",'w')
    val = get_api_counter()
    val[indice_api] = int(val[indice_api]) + 1
    
    fichier_w.write(str(val[0]) + "," + str(val[1]))
    fichier_w.close()

def set_api_counter(indice_api,value): # ne fonctionne qu'avec deux apis
    fichier_w = open("data/counter-api.txt",'w')
    api_value = get_api_counter()
    api_value[indice_api] = str(value)
    fichier_w.write(api_value[0] + "," + api_value[1])
    fichier_w.close()

Maintenant que toutes nos briques sont construites, il ne reste qu’à écrire le fichier python principal qui va organiser tout le programme tel un chef d’orchestre.

Assemblage final

Maintenant, il faut simplement assembler notre montage électronique à notre construction LEGO. Puis à brancher notre ESP32 à un câble, lui injecter le code, et tout en le gardant brancher, le lancer, et la magie opère !

Fichiers

Veuillez noter que vous devrez ajouter votre propre clé api Google Maps API pour que la position soit mise à jour (dans boot.py à la ligne 21). Sinon vous pouvez changer manuellement la position dans le fichier old-location.txt se trouvant dans le dossier data. Veuillez respecter l’ordre suivant et ne surtout rien ajouter d’autre dans le fichier, pas même un espace :

latitude,longitude

Vous devrez également ajouter vos propres informations pour un point d’accès dans le fichier boot.py au niveau de la ligne 19 : wlan_info = ("SSID","MDP")
Le projet ne fonctionne pas sans une connexion à internet !!

Projets

Un reversi sur ta NumWorks !

Un jeu de société existant sous l’ombre des dames et des échecs, il est temps de rendre justice ! Le Reversi est un jeu de société pour deux joueurs qui se joue sur un plateau de 64 cases. Les joueurs placent tour à tour des pions noirs ou blancs sur le plateau, en capturant les pions adverses et en retournant les pions de l’adversaire pour gagner le contrôle du plateau.

À la découverte d’un nouveau jeu !

« – Alors qu’avons-nous là… Un Tetris ? Déjà fait et étonnement, pas le niveau. Un 2048 ? 😤 Une bataille navale ? Oula, pas certain de ce coup. Bon alors, quel jeu faire sur la NumWorks qui n’est pas trop dur à réaliser, mais reste néanmoins intéressant ?
– « Le Reversi » ?
– À vos souhaits.
– Tu n’as pas la lumière à tous les étages toi… C’est un jeu de société également appelé Othello. Voici plus de détails concernant les règles.
– D’accord, je vois le style, et bien allez, c’est parti ! »

Une base graphique

Il faut commencer quelque part ! Tout d’abord, on récupère un exemple proposé par notre professeur. Moins on en fait, mieux on se porte. 😎

Maintenant, il faut l’arranger pour notre jeu. Pour commencer, on s’occupe de placer une grille au centre de l’écran, ce sera notre plateau de jeu.

[...]
def grille(x, y, t_x, t_y, c, col):
  for w in range(t_x):
    for h in range(t_y):
      rec(1+x+w*(c+2), 1+y+h*(c+2), c, c, col)

La fonction est assez simple, elle va simplement faire un nombre de petits carrés indiqués en paramètres. t_x pour la taille en horizontale et t_y pour la taille en vertical (il faut indiquer un nombre de carrés pour les 2 variables).

Ce n’est pas fini ! Même pas du tout 😥

On va s’occuper du système pour gérer les déplacements sur la grille en se basant sur ce qu’a proposé le prof dans son exemple. Avant ça, nous allons définir un paquet de variables qui nous serons utiles tout le long du code (et encore, cette liste n’est pas exhaustive) :

# Beaucoup... BEAUCOUP de couleurs...
col = ((100,203,111),(220,)*3,(60,)*3,(148,113,222),
       (242,0,0),(255,183,52),(255,)*3,(60,139,72),
       (90,)*3,(180,)*3,(160,)*3,(242,)*3)
# Différents paramètres, à commencer par la taille horizontale et verticale
# de notre grille (ce sont les var pour t_x et t_y)
len_x,len_y = 8,8
# On l'utilisera plus tard, ce sera la position par défaut du sélectionneur de case
pos = [2,3]
# la taille des carrés dans la grille, en pixel
c = 20
# De sombres calcul... Pour centrer la grille !
x_g = (320 - (1+len_x*(c+2))) // 2
y_g = (200 - (1+len_y*(c+2))) // 2
# Très important ! C'est notre grille, chaque valeur d'une case est renseignée dans cette matrice
g = [[0 for i in range(len_x)] for i in range(len_y)]
# Gestion des tours, des scores,
# et des tours où un joueur ne peut pas jouer (allez check les règles pour comprendre ça) 
player_turn,sc_noir,sc_blanc,no_round = 2,0,0,0

Une partie de ces variables se situent dans une fonction init() qui permet de relancer une nouvelle partie lorsque la précédente est terminée et de gérer le système de paramètres (nous le verrons plus tard). Une grosse fonction play() s’occupe de vérifier les actions du joueur, c’est-à-dire les déplacements, s’il place un pion, etc.

def play():
  [...]
  while 1:
    key_pressed = None
    pos_old = list(pos)
    [...]
    key_pressed = wait()
    if key_pressed == 1:
      pos[1] = (pos[1]-1) % 8
    elif key_pressed == 2:
      pos[1] = (pos[1]+1) % 8
    elif key_pressed == 3:
      pos[0] = (pos[0]+1) % 8
    elif key_pressed == 0:
      pos[0] = (pos[0]-1) % 8
    elif key_pressed in (4,52):
      action(pos) # Simplifié
    if key_pressed != None:
      deplacement(pos_old)
  [...]

Ce code permet de gérer les déplacements sur toutes la grille et permet lorsque l’on appuie sur la touche Ok ou EXE, de valider notre sélection et d’exécuter une fonction action() qui s’occupe de lancer différentes fonctions selon certaines conditions pour vérifier le placement du pion puis le placer ou non.

Revenons sur nos déplacements. Avant toute chose, nous allons créer deux fonctions bien pratiques : getCase() et setCase(). Comme leur nom l’indique, l’une nous renvoie des informations concernant une case, l’autre change la valeur d’une case. « Récupérer » des informations ou « changer » la valeur d’une case, c’est modifier/récupérer une valeur dans notre matrice.

def getCase(g_in, x, y, col_mode=False):
  if col_mode:
    if 0 <= g_in[y][x] <= 2:
      return col[g_in[y][x]]
    return None
  return -1 if x < 0 or x >= len_x or y < 0 or y >= len_y else g_in[y][x]

def setCase(g_in_in, x, y, value):
  g_in_in[y][x] = value

On peut voir que getCase(), en plus de pouvoir nous renvoyer un statut pour la case sélectionnée (-1 si non valide, 0 si vide, 1 si blanc et 2 si noir), peut également nous renvoyer la couleur de la case. setCase() est plus simpliste mais tout aussi importante.
Voici notre fonction deplacement() :

def deplacement(pos_old=[],for_error=False):
  global c
  if not(for_error):
    if pos_old != []:
      x, y = pos_old
      if getCase(g,x,y) in (1,2):
        rec(x_g+1+x*(c+2),y_g+1+y*(c+2),c,c,col[0])
        cercle(x_g+8+(c+2)*x,y_g+3+(c+2)*y,getCase(g,x,y,True))
      else:
        rec(x_g+1+x*(c+2),y_g+1+y*(c+2),c,c,getCase(g,x,y,True))
    x, y = pos
    rec(x_g+1+x*(c+2),y_g+1+y*(c+2),c,c,col[7])
    cercle(x_g+8+(c+2)*x,y_g+3+(c+2)*y,col[1] if player_turn == 1 else col[2],1)
    case = getCase(g,x,y)
    if case != 0:
      cercle(x_g+8+(c+2)*x,y_g+3+(c+2)*y,getCase(g,x,y,True))
  else:
    rec(x_g + 1 + pos[0]*(c+2),y_g + 1 + pos[1]*(c+2), c, c, col[4])
    sleep(0.1542)

Cette fonction s’occupe de rendre le déplacement naturel et fluide. En effet, si l’on est à une case de coordonnée (1;1) et que l’on décide d’aller en (2;1), il faut que l’on affiche une surbrillance de sélection sur la nouvelle case, et que l’on rende à l’ancienne case son apparence d’origine. C’est très vulgarisé, car en plus de ça, ce code gère un affichage différents si le placement est incorrect, ainsi qu’une surbrillance différentes si on le joueur décide de se déplacer sur une case avec déjà un pion de placé.

On remarque une fonction cercle(). Elle a été proposé par le professeur, qui est chaleureusement remercié, car les pions, au lieu de ressembler à ça…

Petit faux raccord sur la couleur de la grille. Vous voyez également une des premières versions du sélectionneur, qui depuis a été bien amélioré.

…ressemblent plutôt à ça :

def cercle(x,y,col,s=0):
  for d in range(6):
    rec(x-d+(d==0)+2*s,y+d+(d==5)+2*s,6+2*d-2*(d==0)-4*s,16-2*d-2*(d==5)-4*s, col)

Que d’aventure… Nous avons maintenant un système de déplacement performant. Il faut maintenant s’attaquer à la logique du programme. On est à 21,73 % d’avoir fini le jeu !

Logique du jeux & IA

La partie la plus complexe. Je remercie mon père qui m’a beaucoup aidé pour cette fonction cœur de mon jeu. Cette fonction a deux modes de fonctionnement, elle peut vérifier si un pion peut être placé ; et placer un pion.

def do_pion(mode,pion_x,pion_y,directions_in,ai_ask=False):
  if getCase(g,pion_x,pion_y) != 0:
    return False
  result = []
  if ai_ask:
    dist_totale = []
  global sc_noir,sc_blanc
  pion_adverse = 1 if player_turn == 2 else 2
  for d in directions_in:
    x,y,dir_x,dir_y = pion_x,pion_y,d[0],d[1]
    current = getCase(g, x + dir_x, y + dir_y)
    dist_parcourue = 1
    while pion_adverse == current:
      x,y = x+dir_x,y+dir_y
      if mode == 1:
        sc_blanc += 1-2*(player_turn!=1)
        sc_noir += 1-2*(player_turn!=2)
        setCase(g, x, y, player_turn)
      current = getCase(g, x + dir_x, y + dir_y)
      dist_parcourue += 1
    if mode == 0 and dist_parcourue > 1 and current == player_turn:
      if not(ai_ask):
        result.append(d)
      else:
        dist_totale.append(dist_parcourue)
        result.append(d)
    else:
      continue
  if mode == 1:
    if player_turn == 1:
      sc_blanc += 1
    else:
      sc_noir += 1
    setCase(g,pion_x,pion_y,player_turn)
  else:
    if ai_ask:
      result.append(sum(dist_totale))
    return result

Lorsqu’elle vérifie si un pion peut être placé, elle va vérifier dans les 8 directions si la situation permet un retournement de pions adverses. Si c’est le cas, elle stocke la direction, et continue. À la fin, elle renvoie une liste contenant toutes les directions valides. S’il y a au moins une direction valide, la fonction est réexécutée, mais cette fois-ci, elle changera les valeurs dans la matrice en appliquant les règles de retournement. La fonction qui appelle do_pion() et qui analyse le résultat de la première exécution de celle-ci, c’est la fonction action() :

def action(position):
  global player_turn
  result = do_pion(0,position[0],position[1],directions)
  if result != [] and result != False:
    do_pion(1,position[0],position[1],result)
    player_turn = 1 if player_turn == 2 else 2
    update() # Nous verrons cette fonction un peu plus tard.
  else:
    deplacement(for_error=True)

La fonction do_pion() s’occupe toute seule d’appliquer quasiment toutes les règles du Reversi, elle s’occupe même de mettre à jour le score. Cependant, il y a une règle dans le Reversi qui stipule qu’un joueur ne peut pas jouer si il n’a aucun « mouvement légal », c’est-à-dire qu’il n’a aucun placement possible sur le plateau (fun fact : ce plateau est appelé othellier) qui respecte les règles du jeu. Si c’est le cas, son tour est passé. C’est le job de la fonction has_legit_hit() :

def has_legal_hit():
  legal_hits = []
  for y in range(len_y):
    for x in range(len_x):
      if do_pion(0,x,y,directions):
        legal_hits.append([x,y])
  return legal_hits

Plus précisément, elle vérifie seulement. C’est la fonction play() qui s’occupe de passer le tour du joueur :

def play():
  [...]
  if has_legal_hit() == []:
      player_turn = 1 if player_turn == 2 else 2
      no_round += 1
      if no_round == 2:
        affichage() # Nous verrons cette fonction un peu plus tard.
        break
      affichage() # bis
      continue
    else:
      no_round = 0
  [...]

Ce petit bout de code s’occupe également d’arrêter la partie, car si les deux joueurs ont dû passer leur tour l’un après l’autre, c’est qu’aucune des deux ne pourra rejouer.

Alors, en effet, si vous êtes au fond de la classe – je ne suis responsable de rien – vous pouvez jouer avec votre voisin, mais si vous êtes devant ? Et bien oui, il faut penser à tout le monde.

Notre IA va utiliser tous les composants décris précédemment. La seule action qu’elle va faire d’elle-même est de choisir une case valide. Dans la version actuelle (1.2.1), l’IA a deux niveaux : un où elle choisit parmi toutes les cases valides une case aléatoirement, et un autre où elle choisit la case qui lui rapporte le plus de point. Si vous avez bien été observateur, certaines fonctions telles que do_pion() avaient une partie qui était réservée pour une utilisation par l’IA. C’est dans do_pion() qu’est calculé quel est la case qui rapportera le plus de point.
Voici le code de la fonction ai() :

def ai(lvl):
  if lvl == 0:
    return choice(has_legal_hit())
  elif lvl == 1:
    legal_hits = has_legal_hit()
    temp = []
    plus_grand = [[],0]
    for i in range(len(legal_hits)):
      legal_hits[i] = [legal_hits[i],do_pion(0,legal_hits[i][0],legal_hits[i][1],directions,True)]
    for i in legal_hits:
      if i[1][-1] > plus_grand[1]:
        plus_grand = [[i[0]],i[1][-1]]
      elif i[1][-1] == plus_grand[1]:
        plus_grand[0].append(i[0])
    return choice(plus_grand[0])

Je suis sûr que vous ne savez pas quelque chose… Mais on est à 73,21 % du jeu là ! On y est presque !

Interface graphique, mise à jour de la grille, Game Over & système de paramètres

On y est presque et pourtant… Ce n’est pas encore fini 😵

C’est bien beau de faire des retournements et tout, mais moi ma grille est toujours vide sur mon écran !

Mettons en place une fonction update() qui va s’occuper de mettre à jour graphiquement la grille.

def update():
  global c
  for y in range(len_y):
    for x in range(len_x):
      if getCase(g,x,y) in (1,2):
        rec(x_g+1+x*(c+2), y_g+1+y*(c+2), c, c, col[0])
        cercle(x_g+8+(c+2)*x, y_g+3+(c+2)*y, getCase(g, x, y, True))
      # Ce else pourrait être facultatif et ferait une belle optimisation
      # si le code d'autres fonctions était adapté.
      # Il est ici depuis très longtemps et s'est fait oublié xD
      else:
        rec(x_g+1+x*(c+2), y_g+1+y*(c+2), c, c, getCase(g, x, y, True))
  deplacement()

Elle n’est pas très compliquée à comprendre. Je parcours toute la grille, je récupère la valeur de chaque case et je mets à jour ce qui doit apparaître (s’il doit y avoir un pion ou pas, et la couleur du pion).

Ensuite, le visuel est un peu pauvre, comme ceci sera bien mieux :

Il y a vraiment des délires sombres avec les couleurs…

Je remercie le professeur qui m’a aiguillé pour la conception de l’interface (après attention, il m’a juste suggéré d’aligner les informations avec des cases de la grille, ça va il a pas tout fait non plus 😂).

On ajoute un système permettant d’utiliser l’interface en début de partie pour paramétrer si on veut jouer en mode multijoueur ou contre IA, et le niveau de difficulté de l’IA :

Et un Game Over :

C’est M. ROBERT qui a joué cette partie, il est trop mauvais (🤪).

EDIT : Normalement je ne modifie pas les articles des élèves, mais je me dois de nier l’affirmation précédente qui porte atteinte à mon honneur. 😉

On assemble les pièces de puzzles correctement, et… Attendez, je crois que ça y est ! On a terminé ! Le jeu est fini à 100,42 % 😁

La page de présentation du jeu + Téléchargement

Remerciements

  • Mon père pour ses conseils et aide pour le développement du jeu,
  • M. ROBERT pour ses ressources,
  • ChatGPT pour certaines parties de l’article (en fait, juste le paragraphe de présentation de l’article).
NumApps

Reversi en python, NumWorks

Le Reversi est un jeu de société pour deux joueurs qui se joue sur un plateau de 64 cases. Les joueurs placent tour à tour des pions noirs ou blancs sur le plateau en capturant les pions adverses et en retournant les pions de l’adversaire pour gagner le contrôle du plateau. Le joueur avec le plus de pions de sa couleur à la fin de la partie est déclaré vainqueur.

Fonctionnalités

  • Mode multijoueur et contre IA
  • 2 niveaux de difficultés pour l’IA
  • Système de score
  • Easter egg (trichez pas en regardant le code)

Captures d’écran

Commandes

◁ △ ▷ et ▽OK
Se déplacer / ParamétrerValider

En savoir plus

Si vous souhaitez en apprendre plus sur ce projet, cet article pourrait vous intéresser.

Télécharger

Voici différents liens pour récupérer le code du jeu et le télécharger sur votre calculatrice.

Tutoriels

Découvrir un outil linux pour gérer ses serveurs de…

A la recherche d’un moyen de gérer tous vos serveurs de jeux, serveurs vocaux, et autres avec une seule et même interface facile à utiliser ? Le logiciel linux Pterodactyl est fait pour vous ! Sous forme d’un site lors de l’utilisation, il va vous permettre de créer et administrer vos serveurs de jeux et vocaux.

Le tutoriel peut paraître long, mais a été simplifié le plus possible. L’installation qui vous est présenté est pensée pour un cadre expérimental et de découverte de l’outil Pterodactyl. Cela veut donc dire que le tutoriel ne vous permettra pas de l’utiliser sur des serveurs de productions.

 Teaser vidéo

Dans ce tutoriel, vous apprendrez à :

  1. Installer une machine virtuelle sur son propre ordinateur,
  2. Installer et configurer le système d’exploitation Ubuntu Server,
  3. Installer et configurer Pterodactyl à l’aide d’un script
  4. Utiliser quelques fonctionnalités de Pterodactyl (création de serveurs, création d’utilisateurs et présentations des outils pour gérer un serveur)

Qu’est-ce que Pterodactyl ?

Développé par Dane Everitt (et d’autres contributeurs) et disponible depuis 2015, Pterodactyl est un SaaS (« Software as a Service », « Logiciel en tant que service » en français, c’est-à-dire un logiciel plus généralement installé et utilisé sur un serveur) uniquement disponible sur des systèmes d’exploitation linux. Pour rappel, un serveur n’est rien d’autre qu’un ordinateur sans interface graphique (c’est-à-dire uniquement utilisé en ligne de commande) qui sert de point relais pour la communication entre d’autres machines sur internet et/ou à délivrer des services (Serveur Web, Mail, etc.). C’est pour cette raison que Pterodactyl peut être installé sur un ordinateur linux avec interface graphique. Vous apprendrez à l’installer pour une utilisation sur serveur. Sachez que l’installation sur un système d’exploitation linux avec interface graphique est strictement identique.

Pterodactyl est conçu avec le principal objectif d’assurer une sécurité avancée. Par exemple, chaque serveur qui sera créé sera techniquement séparé des autres, c’est-à-dire que si il y a un problème sur un des serveurs, cela ne se répercutera pas sur les autres serveurs.

Une fois l’importante étape qui est l’installation de Pterodactyl, vous pourrez :

  • Créer très simplement une multitude de serveurs de jeux, vocaux, de bots, etc.
  • Administrer les serveurs facilement, avec des fonctionnalités supplémentaires intégrées par défaut :
    • Création et gestion de backups pour les serveurs
    • Création de tâches programmables pour s’exécuter automatiquement, répétitivement, etc.
    • Création et gestion de bases de données.
  • (fonctionnalité très avancée) Ajouter des plugins payants proposés par Pterodactyl afin d’encore plus simplifier l’administration des serveurs (installation en un clic de plugins/mods pour les serveurs Minecraft par exemple).
  • Gestion avancée d’utilisateurs : Vous avez un projet de jeu mais votre ami en a aussi un complètement différent du votre ? Pterodactyl a un système de gestion de permissions, de propriété de serveur, etc.

Installation sur une machine virtuelle (VM)

⚠ Pour le reste du tutoriel, si vous avez un problème, des questions, des erreurs, etc. Je suis à votre disposition pour vous aider à nsi.aide.thomas@gmail.com

Je pense que ni vous ni moi louerait un serveur pour expérimenter Pterodactyl, c’est pour cette raison que vous ferez l’installation sur votre ordinateur personnel. Si vous êtes déjà sur une distribution Linux supportée par Pterodactyl tout va bien, vous pouvez passer cette étape. Les distributions supportées sont :

Système d’exploitationVersionSupporté ?Notes
Ubuntu18.04
20.04
22.04Le tutoriel est basé sur ce système d’exploitation (conseillé).
CentOS7Des dépôts, serveurs contenant des « paquets » (voir la définition d’apt1) supplémentaires sont requis.
8Des manipulations supplémentaires sont requises pour ce système d’exploitation. Cependant nous ne verrons pas son installation. Ce lien ainsi que la documentation officielle va vous permettre d’installer les prérequis supplémentaires.
Debian10
11
1 Expliqué plus loin : Ctrl + F est votre ami (La définition d’apt est dans la partie Prérequis)

Sinon il va falloir installer un de ces systèmes d’exploitations dans une VM sur votre ordinateur. Une Virtual Machine est sous la forme d’un logiciel et simule un autre ordinateur sur son propre ordinateur. Cela permet d’avoir par exemple sur un MacBook un ordinateur virtuel Windows. Pour installer un système d’exploitation sur une VM, nous avons besoin d’un fichier de type ISO (généralement appelé image ISO). Avant, les systèmes d’exploitations s’installaient grâce à des DVD (aujourd’hui, c’est moins répandu). Une image ISO est l’équivalent d’un disque (DVD) mais en version numérique. Voilà pourquoi on utilise ce type de fichier. Pour ce tutoriel, nous utiliserons cette image ISO (si le lien a un souci, allez sur ubuntu.com/download/server puis cliquez le bouton vert en plein milieu « Download Ubuntu Server XX.XX.X XXX »). Nous utiliserons ce fichier plus tard dans le tutoriel.

Nous allons utiliser le logiciel VirtualBox proposé par Oracle. Commençons par télécharger le logiciel ici, le « VirtualBox 7.0.4 platform packages » (selon votre système d’exploitation) ainsi que le « VirtualBox 7.0.4 Oracle VM VirtualBox Extension Pack » juste en dessous. Exécutez l’installeur (« VirtualBox-7.0.4-154605-Win », notez que le nom peut différer un peu avec cet exemple). Suivez les instructions, puis démarrez le logiciel. Voici comment il se présente :

Nous allons être efficace : Cliquez sur le bouton encadré en rouge, puis « Extensions ». Cliquez ensuite sur « Install », importez le second fichier que nous avons téléchargé (« Oracle_VM_VirtualBox_Extension_Pack-7.0.4.vbox-extpack » ou nom similaire) et cliquez sur « Installation » (sans oublier de lire, 😉, puis accepter les conditions d’utilisations). L’extension devrait être ajoutée et visible dans la liste.

Pour revenir à l’interface de bienvenue, cliquez sur le bouton encadré en rouge et allez sur « Bienvenue ». Ici nous allons pouvoir créer notre machine virtuel. Pour se faire, vous avez le bouton « Nouvelle », qui vous ouvre cette fenêtre :

Nom : Un nom pour votre VM, cela a peu d’importance, c’est pour vous y retrouver.

Folder : La localisation des fichiers de la VM.

ISO Image : Il faut mettre ici le fichier ISO que nous avons téléchargé au début du tutoriel qui contient le système d’exploitation.

Edition / Type / Version : Ces options se sont normalement grisées après avoir importé l’image ISO. De plus ne cochez pas la petite case Skip Unattended Installation.

Nous devons maintenant choisir le nom d’utilisateur, ainsi qu’un mot de passe. Evitez les noms d’utilisateurs farfelus, choisissez quelque chose de simple, sans espace, ni majuscule. Changez également le mot de passe.

Hostname : Chaque appareil connecté à son réseau local a un « hostname ». C’est son nom sur le réseau. Choisissez-en un qui vous permettra de le reconnaitre. Notez qu’il doit être d’au minimum trois caractères et ne peut être écrit qu’avec des caractères alphanumériques ainsi que des petits tirets et des points (mais ne peut pas se terminer par un point). « ubuntu-vm » est un très bon choix par exemple.

Domain Name : ¯\_(ツ)_/¯ Mais pas important dans notre cas.

Ne cochez pas Install in Background ni Guest Additions.

Passons à l’allocation des ressources à notre VM, c’est-à-dire combien de mémoire vive (mémoire volatile pour stocker les données et programmes en cours d’exécution) et de cœurs du processeur (partie qui exécute des instructions, plus il y a en, plus le processeur peut faire des tâches simultanément). Il faut choisir cela en fonction des ressources de son ordinateur. Dans notre cadre expérimental, nous n’avons pas besoin de beaucoup de ressources. Je vous conseille au strict minimum 2 Go (2048 Mo) ainsi que 2 cœurs ou sinon 4 Go (4096 Mo) de mémoire vive et 4 cœurs.

Nous allons maintenant allouer le stockage. Encore une fois, faites cela en fonction de l’espace que vous avez. 25 Gio fera très bien l’affaire.

Nous avons ensuite un récapitulatif des caractéristiques de la VM. On peut appuyer sur « Finish ».

La VM s’est automatiquement lancée, une nouvelle fenêtre est apparue. Au passage, n’hésitez pas à fermer le menu à droite avec le bouton encadré en rouge.

Avant de se lancer dans la configuration du système d’exploitation, nous allons éteindre la machine en allant dans Machine (encadré en jaune), puis Extinction par ACPI. Attendez que la fenêtre se ferme. Ensuite allez dans le bouton Configuration, Réseau et pour Adapter 1 changer l’option Mode d’accès réseau par « Accès par pont » et pour l’option Name, choisissez le nom de votre carte réseau. Je ne connais pas ma carte réseau… Allez vérifiez que l’image ISO dans Stockage (Menu à gauche) est présente au niveau du « Contrôleur : IDE ». Si ce n’est pas le cas, cliquez sur le bouton DVD avec un + et ajoutez le fichier ISO (comparez les noms pour savoir si c’est le bon).

Maintenant, lancez la machine virtuelle, et vous devriez avoir à nouveau la première page de configuration où l’on sélectionne la langue. C’est parti !

Pour en apprendre plus sur VirtualBox.

Installation et configuration du système d’exploitation

Sachez que la souris n’existe pas ! Toutes les manipulations se feront aux claviers. Vous bougez avec les touches fléchés et appuyez sur la touche Entrée pour confirmer une action. Sélectionnez votre langue puis confirmez. Dans la page qui suit, vous avez 3 options en bas, prenez celle du haut, donc « Mise à jour vers le nouveau programme d’installation », confirmez puis patientez. Maintenant, vous pouvez choisir la langue de votre clavier :

Si vous allez sur un des menus déroulants (sur « French – French (legacy, alt.) » pour le menu Variant par exemple), vous pourrez appuyer sur la touche Entrée et changer la variante. Choisissez la première, « French » puis confirmez en allant sur « Terminé » (ou « Done »).

La page d’après vous donne la possibilité d’installer une version allégée de Ubuntu Server, mais dans notre cas, nous allons conserver la version classique, donc confirmez juste. La page suivante concerne la connexion avec le reste du réseau local. Vous ne devriez rien avoir à toucher, confirmez juste. On voit différentes informations intéressantes comme l’IP, c’est-à-dire son identifiant pour la reconnaitre par rapport aux autres, qu’aura notre machine et qui nous sera utile pour y accéder (vous pourriez avoir une IP différente de celle-là) ainsi que le nom de la carte réseau que l’on retrouve en gris en dessous.

Il n’y a rien à changer sur la page suivante, ni à la page d’après. Celle d’après est par rapport au stockage, mais tout est présélectionné correctement, donc il suffit de descendre sur le bouton Done et confirmer.

La seconde page est également en rapport avec le stockage. Je vais y aller pas à pas, suivez les étapes selon les images dans leur ordre.

Par défaut.
Allez sur l’option où il y a le trait rouge, confirmez (touche Entrée) puis allez sur Unmount et confirmez.
Allez sur l’option où il y a le trait rouge, confirmez puis allez sur Edit et confirmez.
Ici, il faut changer la valeur de Size. Mettez la valeur entre les parenthèses (ici 22.996G). Attention à mettre un point et pas une virgule !
Il faut également changer la valeur de Mount. Allez dessus, appuyez sur Entrée, puis choisissez le « /« . Puis allez sur Save en bas et confirmez. Et pour finir allez sur Done et confirmez. Une popup apparaitra et vous demandera si vous êtes sûr. C’est le cas, donc confirmez.

Sur la page suivante, vous devez remettre les informations que nous avions mises lors de la configuration de la VM.

Your name : Ce n’est pas important, j’ai personnellement l’habitude de mettre la même chose que Pick a username.

You server’s name : Il faut mettre la même chose que le hostname (information renseignée lors de la création de la VM).

Pick a username : C’est le nom d’utilisateur, il doit être le même que username (information renseignée lors de la création de la VM).

Choose a password / Confirm your password : Mettez le mot de passe que vous aviez mis lors de la création de la VM.

Sur le page suivante, le service vous propose d’installer OpenSSH server. C’est un service qui vous permet d’accéder à distance à la console du serveur. C’est très pratique, on peut entièrement faire les installations avec, mais de la manière dont je me suis (mal) géré, je ne l’utiliserai que beaucoup plus tard dans le tutoriel pour une pauvre petite action. Déplacez vous en face de l’option (sauf si vous y êtes déjà) pour installer OpenSSH (encadré en rouge) et appuyez sur la touche Entrée, puis allez sur Done et confirmez.

La page qui suit vous propose une liste d’autres services à installer. Si nous avons besoin de ces services, nous les installerons en temps voulu. Confirmez en allant sur Done, et puis patientez, toutes les installations et configurations sont en train de se faire. Vous avez une page de log. Cela peut durer un certain temps, pas d’inquiétude. Lorsque l’installation sera achevé, le second bouton encadré en rouge changera, et deviendra Reboot Now. Allez dessus, confirmez puis patientez.

Une fois cela fait, une bonne quantité de texte va défiler, il faut attendre que ça se termine. Il est possible que l’image en dessous ne corresponde pas à ce que vous avez, mais ce n’est pas grave, sauf si il y a du rouge à la dernière ligne de texte… Si au bout d’un moment la ligne rouge reste et que plus rien d’autres se fait, rechercher le problème sur internet ou contactez moi

Sauf pour cette erreur là qui est « normale », il vous suffit simplement d’appuyer sur la touche Entrée.

Lorsque vous pourrez écrire, c’est que vous pourrez vous connectez, comme vous pouvez le voir sur l’image en dessous (ne faites pas ce que j’ai fait).

Ecrivez alors votre nom d’utilisateur puis appuyez sur la touche Entrée.

Une nouvelle ligne apparait, qui vous invite à écrire votre mot de passe, mais lorsque vous le faites… Rien n’apparait 😭. Mais détendez-vous ! C’est normal. Lorsqu’il faut écrire un mot de passe, linux ne fait jamais apparaitre de caractères, même pas des « * », mais il est quand même écrit ! Prenez donc le temps d’écrire le mot de passe, car souvent on l’écrit mal sans s’en rendre compte et du coup il nous le refuse.

😐
Enfin ! On a réussi 😁

Installation de Pterodactyl

Bon, c’était déjà bien sportif l’installation de cette VM et de ce linux… Je peux comprendre que certains d’entre vous soyez saturés. Et c’est pour cela que je vous propose une méthode assez simple pour installer Pterodactyl. Nous utiliserons un script. Il faut savoir que c’est un script non officiel, et que Pterodactyl ne le supporte pas. En cas de souci lors de l’installation avec ce script, contactez moi. Voici un lien vers la documentation officielle pour installer manuellement Pterodactyl (vous verrez, vous apprendrez beaucoup de chose).

Prérequis

Voici un récapitulatif de quelques commandes linux qui seront utilisées avec une courte explication :

  • sudo : Terme à mettre au début d’une commande que l’on souhaite exécuter avec les plus hautes permissions. Il faut faire très attention car une mauvaise manipulation peut endommager définitivement le système d’exploitation, qui nécessiterait une réinstallation. Lorsque vous utiliserez une commande avec ce terme au début, il faudra mettre son mot de passe pour pouvoir l’exécuter.
  • apt : Simplement : L’App Store version ligne de commande. Plus précisément : Commande qui permet de gérer des paquets. Les paquets sont des archives permettant d’installer des logiciels, stockés dans des dépôts, que l’on peut changer si nécessaire.
    • apt update : Recherche si il y a des mises à jour disponibles.
    • apt upgrade : Applique les mises à jour trouvées (se lance donc après la commande apt update).
    • apt install [nom_paquet] : Installe le paquet donné en paramètre (il faut remplacer [nom_paquet] par le nom d’un paquet, par exemple nano).
  • reboot : Redémarrage la machine virtuelle.
  • su : Permet de se connecter en tant qu’un autre utilisateur. Nous utiliserons cette commande pour accéder à l’utilisateur « root ».

Une notion a maîtriser est le terme « root ». Ce terme est le nom de l’utilisateur avec les plus hauts privilèges possibles. Il faut faire très attention car une mauvaise manipulation peut endommager définitivement le système d’exploitation, qui nécessiterait une réinstallation.

Une documentation très complète en français de l’utilisation d’Ubuntu est disponible si vous souhaitez en apprendre plus.

Quelques notions à comprendre en rapport avec Pterodactyl :

  • Le « panel » (le front-end) : La partie graphique de Pterodactyl. Elle envoie des ordres au daemon.
  • Le « daemon », également appelé « wings » (le back-end) : La partie de Pterodactyl qui crée véritablement les serveurs, qui fait les actions que le panel lui demande.
  • Le « Node » : C’est la configuration du daemon. C’est avec lui que nous renseignerons diverses informations comme par exemple la quantité de ressources allouées (la mémoire vive, le processeur et l’espace disque).
  • Le terme « port » : Ce n’est pas réservé à Pterodactyl. Un port est un système permettant aux logiciels (côté client comme côté serveur) de recevoir ou d’émettre des informations. Il y a 65536 possibilités de ports qui sont classifiés dans 3 catégories : les « ports reconnus » qui sont réservés à des processus spécifiques (le port 80 pour héberger un site par exemple), les « ports enregistrés » qui sont assignés par L’IANA et pour finir les ports dynamiques qui sont généralement utilisés pour des communications temporaires.
    Vous pouvez donc utiliser les ports que vous voulez à l’exception de la plage 0 à 1023 (sauf si le service utilise un de ces ports par défaut, comme un site internet). Notez que beaucoup de logiciels ont un port par défaut, donc privilégiez l’utilisation de celui-ci (pour Minecraft c’est par exemple le port 25565) Une petite liste répertoriant quelques ports…
  • Une liste d’autres notions en rapport avec Pterodactyl (notamment Nest, Egg, etc.)

Mettre à jour le système (IMPORTANT)

Nous devons d’abord vérifier si il y a des mises à jour disponibles :

cosmos@ubuntu-vm:~$ sudo apt update

Beaucoup de texte apparait, puis lorsque nous avons à nouveau cosmos@ubuntu-vm:~$ (cosmos le nom d’utilisateur et ubuntu-vm le « hostname ») qui apparait, c’est que la commande a fini de s’exécuter.

119 paquets peuvent être mis à jour. Exécutez « apt list --upgradable » pour les voir.
cosmos@ubuntu-vm:~$

Nous avons donc 119 paquets à mettre à jour. Et bien allons-y :

cosmos@ubuntu-vm:~$ sudo apt upgrade

Du texte défilera, puis vous aurez sûrement 5 dernières lignes similaires à celles-ci (peut-être en anglais) :

Si c’est écrit en français, vous devrez confirmer en appuyant sur le touche O de votre clavier puis appuyer sur la touche Entrée et si c’est en anglais, ce sera pareil sauf qu’il faudra appuyer sur la touche Y de votre clavier. Maintenant patienter, ça peut prendre un moment selon votre connexion internet.

Notez que j’ai eu une « pop-up » avec fond violet qui m’a informé d’une nouvelle version du « kernel » (le « noyau » du système d’exploitation). J’ai juste appuyé sur Entrée.

Ensuite, j’ai eu une autre « pop-up » avec une liste de services que je peux redémarrer. Dans tous les cas, nous redémarrerons le système, donc juste appuyer sur le touche Tab (la touche à gauche de la touche A sur votre clavier) deux fois, afin que Cancel soit avec une surbrillance rouge/orange puis appuyer sur Entrée.

Pour terminer, nous allons redémarrer la machine virtuelle, afin que tout soit correctement appliqué :

cosmos@ubuntu-vm:~$ sudo reboot

Installation rapide (avec script)

Notez que le script ne fonctionne pas sur CentOS 7 et 8 ! Suivez la documentation officielle pour installer Pterodactyl sur ces deux systèmes d’exploitations. ⚠ Les autres systèmes d’exploitation du tableau au début de l’article sont eux compatibles.

Avant toute chose, nous aurons besoin de savoir l’adresse IP de la machine virtuelle pour plus tard. Pour se faire, utilisez la commande ip addr:

cosmos@ubuntu-vm:~$ ip addr
Dans tout ce blabla bizarre, ce que nous cherchons est encadré en rouge ! Sachez que l’IP commencera toujours par 192.168 (si vous avez bien suivi le tutoriel) puis les deux autres nombres pourront varier. Notez l’adresse IP pour plus tard !

Nous allons utiliser le script d’installation écrit par vilhelmprytz. La page github du script est consultable ici. Pour s’assurer du bon fonctionnement du script, nous allons « passer en root », c’est-à-dire se connecter avec l’utilisateur root, pour se faire :

cosmos@ubuntu-vm:~$ sudo su

Mettez votre mot de passe, et vous remarquerez qu’à la place de votre nom d’utilisateur il y a le terme « root ». Exécutez maintenant cette ligne de commande :

root@ubuntu-vm:/home/cosmos$ bash <(curl -s https://pterodactyl-installer.se)

L’installeur se lance et vous propose différentes options.

Ici, vous dites ce que vous souhaitez installer. Nous voulons le panel et le daemon, donc l’option 2.
Vous configurez le nom de la base de donnée où seront stockés les informations, le compte utilisateur pour accéder à cette base de donnée et son mot de passe. Pour database name et database username, laissez par défaut, c’est-à-dire appuyez simplement sur Entrée. Concernant le mot de passe, c’est vous qui décidez. Personnellement j’ai juste appuyé sur Entrée pour que ça génère un mot de passe automatiquement.
Vous devez maintenant choisir une Timezone, mettez ce que j’ai mis, c’est-à-dire Europe/Paris.
Mettez une email valide, mais dans un cadre d’expérimentation, vous pouvez prendre une « email poubelle ».
Créez le premier compte utilisateur admin pour le panel. L’email ne doit pas obligatoirement être valide. Vous devrez vous rappelez de username et du mot de passe pour vous connecter.
Fully Qualified Domain Name. C’est l’IP (ou le nom de domaine) où est hébergé le panel. Notez que le panel et le daemon peuvent être installés sur deux serveurs séparés et cette option prend son sens dans ce cas là. Ici, ce sera sur la même machine, donc au final, ça revient au même.
Donc, mettez l’IP de la machine virtuel que vous avez noté après avoir fait ip addr. Notez que le warning vous prévient que vous ne pourrez pas générer un certificat ssl pour sécuriser votre site (qu’il soit en https), ce qui n’est pas grave puisque nous faisons tout en local. « Let’s Encrypt » est un service gratuit permettant de générer des certificat ssl.
Un pare-feu est très important, mais dans un cadre expérimental, ce n’est pas nécessaire. Mettez N puis confirmez.

On a ensuite un récapitulatif de la configuration puis nous devons confirmer que nous voulons cette configuration. Mettez Y et l’installation va débuter. Ensuite nous avons ceci :

Mettez no puis patientez. Et…
Le script a fini d’installer le panel (le front-end), passons au daemon (le back-end). Mettez Y.
Dans notre cas, le firewall est inutile. Mettez N.
Ceci est pour permettre la création de bases de données pour les serveurs de jeux, vocaux, etc. C’est une fonctionnalité un peu avancé, donc pour ce tutoriel, sauf si vous vous y connaissez, mettez N.
Puisque tout à l’heure, nous n’avions pas mis en place de certificat, il faut mettre N. Après avoir fait ça, mettez Y pour lancer l’installation.

L’installation est terminé, mais ce n’est pas encore fini…

Configuration du Node

Nous allons à présent configurer le Node. Il va falloir aller sur le panel. Mettez l’adresse IP de la machine virtuelle dans une page de votre navigateur.

Génial ! Connectez vous avec l’utilisateur créé plus tôt.
Il y aura ici la liste des serveurs créés grâce au panel. Cliquez sur le bouton avec des engrenages. Il vous renvoie vers l’interface administrateur du panel.
Ici c’est la partie pour administrer Pterodactyl, donc le panel, le daemon, etc. (pas les serveurs). Allez dans « Locations », puis « Create New ».
Il faut savoir que l’on peut associer différents daemon à un même panel et la « location » permet de les catégoriser. Ce n’est pas vraiment important, mais mettez quelque chose qui a du sens pour vous y retrouver. Par exemple fr.home car le daemon est en France et hébergé chez vous. La description est facultative.
Passons à la création d’un Node. Allez dans « Nodes », puis « Create New ».
Cela peut faire peur, mais ne vous inquiétez pas, c’est simple :

Name : Le petit nom que vous allez lui donner, pour vous y retrouver.

Description : Une description (facultative).

Location : Ce que nous avons créé il n’y a pas plus tard que 2 minutes.

Node Visibility : Permet de le masquer dans la liste des Nodes disponibles lors de la création de serveurs. Dans notre cas, inutile, donc laissez Public.

FQDN : Cela vous dit quelque chose non ? Mettez donc l’ip de votre machine.

Communicate Over SSL : Il faut cocher la première option si le panel est sécurisé avec un certificat, ce n’est pas le cas, donc mettez la seconde option (c’est normal que la case soit rouge une fois cliquée).

Behind Proxy : Si le daemon est derrière un proxy qui s’occupe de la connexion ssl, il faut mettre la seconde option. Je cite de la documentation : Si cette phrase n’a aucun sens pour vous, c’est que cela ne vous affecte pas. Alors, vous avez compris, laissez la première option 😉

Daemon Server File Directory : Où sera sauvegardé le contenu des serveurs du node. Laissez par défaut.

Total Memory : La quantité de mémoire vive que nous voulons allouer au Node. Il ne faut pas mettre la capacité maximale de la machine, car le système d’exploitation en nécessite un peu. Ici, je vais mettre 3Go. Notez que 1Go = 1024 MiB donc à multiplier par le nombre de Go que vous voulez.

Memory Over-Allocation : La quantité en pourcentage de mémoire vive qui sera utilisé en plus si les 3Go sont complètement utilisés. En mettant -1, il n’y aura pas de limite et en mettant 0, cela empêchera de dépasser la quantité de mémoire allouée. Cela va dépendre de vos utilisations, mais puisque que nous expérimentons et que nous sommes limités à 4Go, je vais mettre 0.

Total Disk Space : La quantité d’espace disque que nous voulons allouer au Node Il ne faut pas mettre la capacité maximale de la machine, car le système d’exploitation en nécessite un peu. Ici, je vais mettre 15Go. Notez que 1Go = 1024 MiB donc à multiplier par le nombre de Go que vous voulez.

Disk Over-Allocation : Même chose que pour Memory Over-Allocation mais pour l’espace disque.

Daemon Port / Daemon SFTP Port : Les ports utilisés par le daemon pour communiquer, écouter, etc. Pas touche !

Cliquez enfin sur « Create Node ».
Il faut maintenant ajouter des allocations, c’est-à-dire des ports pour les serveurs qui seront créés. Pour IP Adress, mettre 0.0.0.0 signifie « toutes les adresses IPv4 de la machine locale », car une machine peut avoir plusieurs IPs. C’est ce que nous mettrons. IP alias est facultatif, ne nous en préoccupons pas. Et nous allons donc ajouter des Ports. On peut les ajouter un par un, avec un espace entre chaque port ou alors les écrire d’une certaine façon, par exemple utiliser un tiret : 25565-25575
Et Bam ! Tout ça en moins de 10 secondes 😁 Mais ce n’est pas encore terminé !

Mais avant de continuer, nous allons avoir besoin d’utiliser OpenSSH (mentionné plus haut dans l’article). Pour vérifier que le service est installé et fonctionnel, chercher dans la barre de recherche de votre ordinateur « invite de commande » puis lancer l’application, puis taper la commande ssh.

Si vous avez une réponse, alors c’est bon ! OpenSSH est installé par défaut sur Linux et MacOS, pour
Windows je ne suis pas sûr, donc voici un lien pour l’installer sur Windows.

Comment ça fonctionne ? Et bien c’est plutôt simple :

ssh username@ip

Vous avez donc compris, vous devez mettre votre d’utilisateur, puis « @ » suivi de l’IP de votre machine virtuelle par exemple : ssh cosmos@192.168.1.31
Il vous demande en suite le mot de passe du compte, et ici aussi, aucun caractère n’apparait mais c’est normal.

Et voilà, vous êtes connectés à distance (je vous rappelle qu’une machine virtuelle est un ordinateur séparé de celui sur lequel il est hébergé). L’avantage d’avoir fait tout ça, c’est que nous allons pouvoir faire des copier/coller… Et croyez moi, ce que vous allez copier/coller juste après, vous n’auriez pas aimé devoir le recopier… Cela à d’autres avantages comme avoir plusieurs consoles en simultané (rien n’empêche d’ouvrir 42 invites de commandes et se connecter avec), le défilement avec le souris, des consoles redimensionnables, etc.

Repassons sur Pterodactyl maintenant que vous vous êtes connectés en parallèle avec OpenSSH. Vous êtes donc dans l’onglet Configuration.

Cliquez sur Generate Token
Copiez la ligne (vérifiez que vous avez bien tout sélectionné) puis collez là (en faisant un clique droit pas un Ctrl+V) dans l’invite de commande où vous vous êtes connectés en ssh.
Même si la mise en forme s’est fait la malle, y a bien écrit à la fin « Successfully configured wings ».

La configuration a bien été appliqué, mais le daemon (wings) n’est toujours pas lancé. On peut le lancer avec sudo wings

Pas de rouge… c’est rassurant ! Et si vous retournez sur le panel puis allez dans la catégorie « Node » vous verrez qu’un cœur vert apparait à côté du nom du Node.

En appuyant simultanément sur les touches Ctrl et C vous arrêterait le programme. tapez ensuite ces commandes :

cosmos@ubuntu-vm:/etc/pterodactyl$ cd /etc/systemd/system
cosmos@ubunt-vm:/etc/systemd/system$ sudo nano wings.service

Cela vous ouvre une « interface » ressemblant à ceci :

« nano » est un éditeur de texte en ligne de commande.

Copiez et coller (clique droit pour rappel) ce texte dans l’éditeur de texte :

[Unit]
Description=Pterodactyl Wings Daemon
After=docker.service
Requires=docker.service
PartOf=docker.service

[Service]
User=root
WorkingDirectory=/etc/pterodactyl
LimitNOFILE=4096
PIDFile=/var/run/wings/daemon.pid
ExecStart=/usr/local/bin/wings
Restart=on-failure
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s

[Install]
WantedBy=multi-user.target

Appuyez ensuite simultanément sur les touches Ctrl et S, cela ajoutera ce petit texte signifiant que cela bien sauvegardé ce que nous avons écrit.

Appuyez ensuite simultanément sur les touches Ctrl et X pour fermer l’éditeur puis écrivez cette commande :

cosmos@ubuntu-vm:/etc/systemd/system$ sudo systemctl enable --now wings

Alors… Vous n’allez pas me croire… mais l’installation et la configuration de Pterodactyl est ENFIN terminée !

Installation d’un serveur Minecraft avec Pterodactyl

Pour installer un serveur Minecraft avec Pterodactyl, rendez-vous dans l’interface administrateur du panel puis dans la catégorie « Servers ». Puis cliquez sur « Create New ».

Dans « Core Details » :

Server Name : Le nom du serveur qui apparaitra sur le panel.
Server Owner : Le propriétaire du serveur. Ecrivez les premiers caractères de l’adresse email du compte à qui appartiendra le serveur et celui-ci sera affiché dans la liste.
Server Description : Une description, c’est facultatif.
Start Server when Installed : Si coché, une fois l’installation terminé, le serveur se lancera automatiquement.

On passe à « Allocation Management » :

Node : Le Node sera installé le serveur
Default Allocation : Le port par défaut associé au serveur. Ce sont les ports que nous avions ajouté dans la configuration du Node. Et dans ces ports, il y a le port 25565, le port par défaut de Minecraft. Mettons le.
Additional Allocation(s) : Si vous voulez allouer d’autres ports à ce serveur. Cela peut être utile si vous utilisez des plugins/mods en nécessitant (mais n’en ajoutez pas pour rien).

Puis à « Application Feature Limits » :

Database/Backup/Allocation Limit : La limite du nombre de bases de données/backups/ports que le serveur aura. C’est-à-dire que les utilisateurs qui pourront créer ces éléments seront limités à ce nombre.
Pour « Resource Management » :

CPU Limit : Le pourcentage de ressource processeur que vous allouez au serveur. Un cœur correspond à 100 %. Cela veut dire que vous pouvez allouer un cœur et demi par exemple. Pour 2 cœurs -> 2 * 100 = 200
CPU Pinning : Fonctionnalité avancé, cela permet de préciser si vous voulez que le serveur utilise un ou plusieurs cœurs en particulier. Ne vous embêtez pas avec cela, sauf si cela vous est vraiment nécessaire (laissez vide si vous ne voulez pas l’utiliser).
Memory : La quantité de mémoire vive que vous allez au serveur (en MiB). 1 Go = 1024 MiB
Swap : Utilise de l’espace de stockage comme mémoire vive. C’est-à-dire que si la quantité de mémoire vive est saturée, cela utilisera une quantité d’espace de stockage. C’est cependant à éviter car cela chute les performances. -1 ne met pas de limite et 0 n’en alloue pas.
Disk Space : La quantité d’espace de stockage que vous allouez au serveur (en MiB).
Block IO Weight : Fonctionnalité avancé que je n’ai jamais utilisé.
Enable OOM Killer : Permet de forcer l’extinction du serveur si il dépasse la limite de mémoire.

Passons à « Nest Configuration » :

Nest : Catégorie classant différent fichier de configuration pour créer un serveur.
Egg : Le fichier de configuration pour créer un serveur. Vanilla Minecraft est le nom de la version classique de Minecraft. Forge Minecraft est utilisé pour les mods. Sponge n’est plus utilisé. Ignorez Bungeecord, c’est pour reliez différents serveurs Minecraft entre eux, c’est une notion avancé pour les administrateurs d’un serveur Minecraft. Pour finir, Paper est pour les plugins.
Skip Egg Install Script : Si vous cochez cette case, le script d’installation ne s’exécutera pas, dans notre cas, cela ne sert à rien.
Continuons avec « Docker Configuration » :
Docker Image : Dans notre cas, c’est la version de java qui sera utilisé pour faire tourner le serveur Minecraft. Selon la version que vous voulez installer sur votre serveur Minecraft, il faut une version Java plus ou moins récentes. L’option « Or enter a custom image » est une fonctionnalité avancé, n’y prêtez pas attention.
Et pour finir, « Startup Configuration » et « Service Variables » (ces options peuvent varier selon l’Egg que vous mettez) :

Start Command : La commande qui lancera le serveur à chaque fois que vous appuierez sur le bouton « start ». N’y touchez pas, à moins de savoir ce que vous faites.
Server Jar File : Le nom du fichier Jar. Si vous ne savez pas ce qu’est un fichier Jar, n’y touchez pas.
Server Version : La version de votre serveur Minecraft. « latest » installe donc la dernière version stable et « snapshot » la dernière version snapshot. Vous pouvez aussi mettre le numéro d’une version.

Vous pouvez maintenant cliquer sur « Create Server ». Cliquez sur le bouton encadré en rouge pour quitter l’interface administrateur du panel.

Vous voyez à présent votre serveur dans la liste des serveurs disponibles.

J’en ai créé un autre pour vous montrer deux cas : On a le premier qui a fini de s’installer, on va pouvoir le démarrer alors que le second en train de s’installer, il faut donc patienter un peu.

Cliquez sur le serveur listé que vous venez de créer et une nouvelle interface apparait.

Vous avez au milieu une console, à droite 3 boutons pour respectivement démarrer, redémarrer et arrêter le serveur. Toujours à droite, vous avez l’adresse avec le port, le statut du serveur, l’utilisation de différentes ressources puis des graphiques en bas.

Concernant la partie tout en haut :
Console : Le menu sur lequel vous êtes
Files : Une gestionnaire de fichier pour le serveur
Databases : Pour gérer les bases de données liés au serveur (ne peut être utilisé avec notre installation)
Schedules : La fonctionnalité des tâches automatisés. Nous ne l’aborderons pas dans ce tutoriel.
Users : Pour ajouter des utilisateurs. Vous pourrez personnaliser leur accès (toutes les permissions sont commentés). Un peu plus bas vous sera expliqué comment créer un nouvelle utilisateur.
Backups : Pour créer des backups.
Network : Pour ajouter des ports. Ne fonctionnera pas sans ajouter un quota d’allocation lors de la création du serveur ni sans activer une option sur le panel administrateur se trouvant dans Settings > Advanced > Automatic Allocation Creation.
Startup : Permet de modifier le « docker image » et la valeur de certaines variables renseignées lors de la création du serveur.
Settings : Vous permet de changer certains éléments, et vous permet également de réinstaller le serveur.
Activity : une page de log des actions faites sur le panel en rapport avec le serveur.
– La petit flèche permet d’accéder à la page en rapport avec le serveur sur le panel administrateur du panel, page qui permet de modifier à nouveau les informations précisées lors de la création du serveur.

Créer de nouveaux utilisateurs

Dans le panel administrateur (le bouton engrenage) vous avez une catégorie « Users ». Le compte que vous avez créé lors de l’installation de Pterodactyl est listé. Vous pouvez créer un nouvel utilisateur en cliquant sur Create New. Vous pourrez donc y ajouter une adresse email (mettez-en une, même invalide, cela vous permettra de l’identifier lorsque vous voudrez ajouter des accès à certains serveurs à cet utilisateur), un nom d’utilisateur, un prénom puis un nom. Default Langage est la langue par défaut que l’utilisateur aura pour le panel. C’est-à-dire qu’en remettant la main dans le cambouis, on peut ajouter des fichiers de langues, ce qui permet de changer la langue du panel. Mettre Administrator sur yes lui permettra d’accéder à l’interface administrateur du panel, ce que je vous déconseille. Pour le mot de passe, même si il est précisé que vous n’êtes pas obligé de mettre un mot de passe, dans notre cas si ! Le panel n’arrivera pas à envoyer un mail à l’adresse indiquée, qu’elle soit valide ou non.

Conclusion

  • Sachez qu’après avoir suivi ce tutoriel, les serveurs que vous créerez ne seront qu’accessible dans votre réseau local. Votre ami qui habite la ville d’à côté ne pourra pas y accéder, il y a d’autres manipulations à mettre en place.
  • Cet outil est très puissant mais requiert une certaine maitrise des systèmes linux. J’ai voulu rédiger ce tutoriel afin que vous découvriez Pterodactyl sans que vous soyez submerger par tout un paquet d’installations, de configurations, de problèmes, etc. ce qui implique de ne pas vous montrer toutes les fonctionnalités proposés par ce logiciel.
  • Si l’outil vous intéresse, et que vous voulez en apprendre plus ou l’utiliser sur un serveur de production, je peux déjà commencer par vous conseiller de recommencer l’installation mais en la faisant manuellement cette fois-ci, donc en suivant la documentation officielle. Sachez que le projet est très communautaire, en cas du moindre problème, vous pouvez rejoindre leur discord et poser des questions (en anglais).
  • Merci d’avoir lu cet article ! La principale source de cet article est le site officiel de Pterodactyl (et mes connaissances 😉).
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