Author: Victor E.

Projets

PhpMonDésastre


Dans le cadre du projet SGBDR, j’ai eu l’occasion de créer un site Internet en PHP. Je vous propose donc de découvrir mon projet, nommé phpMonDésastre. Il s’agit d’une version simplifiée de phpMyAdmin qui vous permet d’interagir de manière simplifiée avec une base de données.

Idée

Mon idée était de créer une version simplifiée de phpMyAdmin où les utilisateurs pourraient venir interagir de manière minimaliste avec une base de données et observer les résultats. Cette version, que je nommerais phpMonDésastre, devrait suivre les règles du CRUD, c’est-à-dire Créer, Lire, Mettre à jour et Supprimer.

Cahier des charges

Pour accéder à mon site, les utilisateurs doivent d’abord se connecter à leur session. S’ils n’ont pas de compte, ils devront en créer un. Une fois connectés, ils pourront parcourir les différentes tables de la base de données ainsi que leur contenu. Ensuite, ils auront la possibilité d’exécuter uniquement quatre types de commandes respectant la règle CRUD : créer une table, ajouter du contenu à une table, modifier le contenu d’une table et supprimer une table. Cela permettra de limiter les possibilités des utilisateurs afin d’éviter les abus de la base de données mise à leur disposition.

Mise en place


Pour mettre en place ce projet, il faut commencer par mettre en place une base de données qui contiendra les informations des comptes utilisateurs et qui recevra ces expériences des utilisateurs.

<?php
/*On se connecte à la base de données en entrant les informations nécessaires,
telles que le nom de l'hôte, le nom de la base, les identifiants et le mot de passe.
Ensuite, on définit cette connexion sur la variable $mysqlClient que l'on utilisera
pour gérer toutes les requêtes SQL. 
On permet aussi l'affichage des erreurs pour pouvoir déboguer plus facilement*/
$sql_host="";
$sql_id="";
$sql_password="";
$sql_dbname="";

try {
    $mysqlClient = new PDO(sprintf('mysql:host=%s;dbname=%s;charset=utf8', $sql_host, $sql_dbname),
    $sql_id,
    $sql_password);

    $mysqlClient->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $exception) {
    die('Erreur : ' . $exception->getMessage());
}



Ensuite, on met en place la page de connexion. D’abord, on s’occupe de la partie frontend, puis de la partie backend.

<!DOCTYPE html>
<html lang="fr" >
<head>
    <meta charset="UTF-8">
    <title>Login Form</title>
    <link rel="stylesheet" href="style.css">
</head>
 <body>
    <?php if (!isset($_SESSION['LOGGED_USER'])) : ?> // On vérifie si l'utilisateur est connecté.
        <center><div class = "message">
            <?php if (isset($_SESSION['LOGIN_ERROR_MESSAGE'])) : ?> // Si une erreur survient, on l'affiche.
                <?php echo $_SESSION['LOGIN_ERROR_MESSAGE'];
                unset($_SESSION['LOGIN_ERROR_MESSAGE']); ?> // Une fois affichée, on l'enlève.
            <?php endif; ?>
            <?php if (isset($_SESSION['SIGNUP_ERROR_MESSAGE'])) : ?> // de même avec les erruer pour l'incription
                <?php echo $_SESSION['SIGNUP_ERROR_MESSAGE'];
                unset($_SESSION['SIGNUP_ERROR_MESSAGE']); ?>
            <?php endif; ?>
        </div></center>
        <section class = "fond-noir"> 
            <div class="signin"> 
                <div class="content"> 
                    <h2>Sign In</h2> 
                        <form class = 'form' action="submit_login.php" method="POST"> 
                            <div class="inputBox" action="submit_login.php" method="POST"> // Boîte pour demander l'adresse e-mail.
                                <input type="Email" name="email" required> <i>Username</i> 
                            </div> 
                            <div class="inputBox" action="submit_login.php" method="POST"> // Boîte pour demander le mot de passe.
                                <input type="password" name="password" required> <i>Password</i> 
                            </div> 
                            <div class="links"> 
                                <a href="forgot_psw.php">Forgot Password</a> <a href="sing_up.php">Signup</a> // Bouton renvoyant vers la page de réinitialisation de mot de passe et la page d'inscription.
                            </div> 
                            <div class="inputBox"> 
                                <input type="submit" value="Login"> // Envoyer la requête de connexion.
                            </div>
                        </form>
                    </div> 
                </div> 
            </div> 
        </section>
    <?php endif; ?>
 </body>
</body>
</html>
<?php
// On démarre la session.
session_start();
/* On importe les différentes pages PHP nécessaires pour l'utilisation complète du script,
telles que "databaseconnect.php" mentionnée ci-dessus pour se connecter à la base de données.*/
require_once(__DIR__ . '/config/mysql.php');
require_once(__DIR__ . '/databaseconnect.php');
require_once(__DIR__ . '/variables.php');
require_once(__DIR__ . '/functions.php');

$postData = $_POST;

// On vérifie que les informations demandées soient bien rentrées.
if (isset($postData['email']) && isset($postData['password'])) { 
  	// On vérifie la validité de l'email fourni.
    if (!filter_var($postData['email'], FILTER_VALIDATE_EMAIL)) {
        $_SESSION['LOGIN_ERROR_MESSAGE'] = 'Il faut un email valide pour soumettre le formulaire.';
    } else {
      	// On vérifie la présence des informations données dans la base de données.
        foreach ($users as $user) {
            if (
                $user['email'] === $postData['email'] &&
                $user['password'] === $postData['password']
            ) {
                $_SESSION['LOGGED_USER'] = [
                    'email' => $user['email'],
                    'user_id' => $user['user_id'],
                ];
            }
        }
		// Si elles ne sont pas présentes dans la base de données, on renvoie une erreur.
        if (!isset($_SESSION['LOGGED_USER'])) {
            $_SESSION['LOGIN_ERROR_MESSAGE'] = sprintf(
                'Les informations envoyées ne permettent pas de vous identifier : (%s/%s)',
                $postData['email'],
                strip_tags($postData['password'])
            );
        }
      // De même pour la page d'inscription.
        if (isset($_SESSION['SIGNUP_ERROR_MESSAGE'])) {
            $_SESSION['SIGNUP_ERROR_MESSAGE'] = sprintf(
                'Les informations envoyées ne permettent pas de vous inscrire'
            );
        }
    }

    redirectToUrl('index.php');
}


En ce qui concerne la page d’inscription, c’est à peu près le même principe, sauf qu’au lieu de vérifier la présence des informations entrées dans la base de données, on les inscrit dans celle-ci avant de rediriger l’utilisateur vers la page de connexion afin qu’il puisse se connecter avec son profil fraîchement créé.


Une fois cette étape franchie, vous arrivez sur une page de connexion semblable à celle-ci :


Une fois connecté, on arrive sur la page principale.

Pour concevoir la page principale, j’ai élaboré une maquette que je suivrai pour la création de la page :

Tout d’abord, nous procédons à l’affichage des tables :

<form class="form" action="index.php" method="post"> // Affichage des tables
    <?php foreach ($TABLES as $table) : ?>
         <?php if ($table[0] === 'users') : ?>
         <?php else : ?>
             <input type="checkbox" value="<?= $table[0] ?>" name="choix_cle" onchange="disableOtherCheckboxesTable(this)" <?= isset($_SESSION['choix_cle']) && $_SESSION['choix_cle'] === $table[0] ? 'checked' : '' ?>>
             <label for="<?= $table[0] ?>"> <?= $table[0] ?></label><br>
         <?php endif ?>
    <?php endforeach; ?>
    <div calss = "case-boutton">
         <input class="submit-bouton" type="submit" value="Valider">
    </div>
</form>

L’affichage des colonnes :

<form class="form" action="index.php" method="post">
     <?php foreach ($CLE as $clecle) : ?>
          <input type="checkbox" name="choix_contenu" value="<?= $clecle['Field'] ?>" <?= isset($_POST['choix_contenu']) && $_POST['choix_contenu'] === $clecle['Field'] ? 'checked' : '' ?>>
          <label for="<?= $clecle['Field'] ?>"> <?= $clecle['Field'] ?></label><br>
     <?php endforeach; ?>
     <div calss = "case-boutton">
          <input class="submit-bouton" type="submit" value="Valider">
     </div>
</form>

L’affichage du contenu :

<form class="form" action="index.php" method="post">
     <?php foreach ($CONT as $cont1) : ?>
          <?php foreach($cont1 as $cont2) : ?>
               <input type="checkbox" name="choix_contenu" value="<?= $cont2 ?>" <?= isset($_POST['choix_contenu']) && $_POST['choix_contenu'] === $cont2 ? 'checked' : '' ?>>
               <label for="<?= $cont2 ?>"> <?= $cont2 ?></label><br>
          <?php endforeach; ?>
     <?php endforeach; ?>
</form>

Ensuite, on procède à l’affichage des commandes :

<div class="div-submit-bouton">
     <form class="form" action="index.php" method="post">
          <center>
          CREATE TABLE IF NOT EXISTS <input class="inputBox2" type="text" name="cree_table" required> (<br><input class="inputBox1" type="text" name="cree_cont" required>);
          <input class="submit-bouton2" type="submit" value="Crée une table"/>
          </center>
     </form>
     <form class="form" action="index.php" method="post">
          <center>
          INSERT INTO <input class="inputBox2" type="text" name="ajout_table" required> (<input class="inputBox2" type="text" name="ajout_valeurs1" required>) VALUES (<input class="inputBox2" type="text" name="ajout_valeurs2" required>);
          <input class="submit-bouton2" type="submit" value="Ajouté"/>
          </center>
     </form>
     <form class="form" action="index.php" method="post">
          <center>
          UPDATE <input class="inputBox2" type="text" name="modif_table" required> SET <input class="inputBox2" type="text" name="modif_def" required> WHERE <input class="inputBox2" type="text" name="modif_condi" required>;
          <input class="submit-bouton2" type="submit" value="Modifier"/>
          </center>
     </form>
     <form class="form" action="index.php" method="post">
          <center>
          DROP TABLE <input class="inputBox2" type="text" name="drop_table" required>;
          <input class="submit-bouton2" type="submit" value="Supprimé"/>
          </center>
     </form>
</div>

Et voici le résultat :

Conclusion

En conclusion, phpMonDésastre représente une tentative de créer une version simplifiée de phpMyAdmin, offrant une interaction minimale avec une base de données. Bien que le projet suive les principes du CRUD et offre des fonctionnalités de base telles que la création, la lecture, la mise à jour et la suppression de données, il reste encore des améliorations à apporter. L’intégration de fonctionnalités supplémentaires et l’amélioration de l’interface utilisateur pourraient rendre cette plateforme plus conviviale et fonctionnelle. En fin de compte, phpMonDésastre constitue un premier pas vers un outil de gestion de base de données simplifié, mais il reste encore du travail à faire pour atteindre son plein potentiel.

Dans le lien de téléchargement ci-dessous, vous trouverez le projet dans son intégralité. Si vous utilisez un environnement local, vous devrez utiliser XAMPP pour exécuter PHP. Si vous hébergez le projet sur un serveur, vous devrez modifier la configuration de « databaseconnect.php » comme présenté précédemment.

Tutoriels

Apprendre les bases de l’Arduino

Arduino est une plateforme matérielle et logicielle open source populaire utilisée pour le développement de projets électroniques, notamment pour la création de prototypes, de dispositifs interactifs et de systèmes embarqués.

Arduino comprend un microcontrôleur, un environnement de développement intégré (IDE) et une bibliothèque de logiciels qui facilitent la programmation et le contrôle de composants électroniques. Arduino est une plateforme de prototypage électronique qui simplifie le développement de projets électroniques interactifs, en offrant une approche conviviale pour la programmation et le contrôle de composants électroniques. Il est couramment utilisé dans l’éducation, le bricolage, la robotique, l’automatisation domestique et de nombreux autres domaines, ou pour s’amuser :).

Comment ce présente une carte Arduino ?

Il existe plusieurs types de cartes Arduino (Arduino UNO, Arduino Nano, Arduino Due, Arduino Mega, Arduino Leonardo …) qui appartinrent à de nombreuse gammes, chacune de ces gammes est spécifiques, plus ou moins puissante, et a différentes utilisations. Pour cet présentation j’utiliserais comme base une carte Arduino UNO pour présenté les pins présent et leurs utilité car c’est l’une des plus commune et les plus utilisé pour sa taille et sa polyvalence.

Premièrement voici à quoi ressemble un carte Arduino UNO :

Cela peut paraitre assez compliquer et assez brouillon à première vue mais en réalité plusieurs de ces pin on la même utilité et certains sont rarement utilisé.

En rouge ici nous avons le bouton reset, le bouton de réinitialisation (reset) sur une carte Arduino est utilisé pour redémarrer le programme en cours d’exécution sur le microcontrôleur. Lorsque l’on appuie sur le bouton de réinitialisation, cela a pour effet d’arrêter momentanément l’exécution du programme en cours sur la carte Arduino et de recommencer depuis le début.

En bleu la prise USB , elle sert à plusieurs fins importantes, notamment la programmation, la communication série, et parfois même l’alimentation. C’est grâce à cet prise USB que l’ont transfèrera les programmes.

En vert La prise ronde d’alimentation sur une carte Arduino est un connecteur de type barrel jack. Ce connecteur est utilisé pour fournir une alimentation externe à la carte Arduino.

En rouge les broches numériques (digital pins) sur une carte Arduino sont des broches d’entrée/sortie qui peuvent être configurées pour fonctionner en mode numérique. Elles peuvent être utilisées pour lire des signaux numériques (0 ou 1) ou pour envoyer des signaux numériques (c’est comme cela que nous allons les utilisé pour le reste de ce tutoriel). Voici les différentes manières dont dont laquelle sont utilisé les broches digitales :

  • Entrées numériques : Les broches numériques peuvent être configurées en tant qu’entrées pour lire des signaux numériques. Elles sont souvent utilisées pour détecter l’état logique d’un dispositif externe, tel qu’un capteur de lumière, un interrupteur ou un capteur de mouvement.
  • Sorties numériques : Les broches numériques peuvent être configurées en tant que sorties pour envoyer des signaux numériques. Elles peuvent être utilisées pour contrôler des dispositifs tels que des LED, des relais, des moteurs ou d’autres composants qui réagissent à des signaux logiques.
  • Communication série : Les broches numériques peuvent être utilisées pour la communication série. Par exemple, les broches RX (réception) et TX (transmission) permettent la communication série asynchrone avec d’autres dispositifs, tels qu’un ordinateur via le port USB.
  • Communication I2C et SPI : Certains broches numériques sont spécifiquement dédiées à la communication sur les bus I2C et SPI. Ces protocoles sont souvent utilisés pour interconnecter des composants tels que des capteurs, des écrans, des mémoires, etc.
  • Pulse Width Modulation (PWM) : Certains pins numériques peuvent être configurés en mode PWM, permettant de générer des signaux analogiques simulés. Cette fonction est couramment utilisée pour contrôler l’intensité lumineuse des LED ou la vitesse des moteurs.

En bleu le pin GND (Ground) sur une carte Arduino est la broche de mise à la terre, il est essentiel pour établir une référence commune de tension, fournir une mise à la terre pour les composants du circuit, et assurer des connexions électriques appropriées. Il est souvent utilisé en conjonction avec les broches d’alimentation (VCC) pour créer un circuit complet.

En jaune le pin AREF (Analog REFerence) est utilisé pour définir une tension de référence pour les mesures analogiques effectuées par les broches analogiques de la carte. Il permet de spécifier la plage de tension à laquelle les valeurs analogiques seront comparées lors de la conversion analogique-numérique (CAN). Dans ce tutoriel nous n’utiliserons pas ce pin.

En violet le pin SDA sur une carte Arduino est une broche utilisée dans les communications I2C (Inter-Integrated Circuit). I2C est un protocole de communication série à deux fils utilisé pour connecter différents composants électroniques sur un même bus. La signification de l’acronyme SDA est « Serial Data Line » (Ligne de Données Série). La broche SDA est utilisée pour transférer les données entre les différents composants connectés sur le bus I2C. Dans ce tutoriel nous n’utiliserons pas ce pin.

En orange le pin SCL (Serial Clock Line) sur une carte Arduino est utilisé dans le cadre du protocole de communication I2C (Inter-Integrated Circuit). Le bus I2C est un protocole de communication série à deux fils qui permet la connexion de plusieurs composants électroniques sur un même circuit. Le pin SCL est utilisé pour transmettre l’horloge synchronisant les échanges de données entre les différents composants connectés au bus I2C. Dans ce tutoriel nous n’utiliserons pas ce pin.

En vert le port ICSP (In-Circuit Serial Programming) est un ensemble de broches destinées à la programmation du microcontrôleur à l’aide d’un programmateur ISP (In-System Programmer). Ce port permet de reprogrammer le microcontrôleur sans avoir besoin de retirer le microcontrôleur de la carte. il y a 12 des ces ports sur la carte Arduino répartis en deux groupes de 6 à différentes endroits de la carte. Dans ce tutoriel nous n’utiliserons pas ce pin.

En rouge les broches « Analog In » (entrées analogiques) sur une carte Arduino permettent de mesurer des tensions analogiques. Contrairement aux broches numériques (digitales) qui peuvent prendre des valeurs logiques (0 ou 1), les broches analogiques peuvent mesurer une plage continue de tensions, généralement entre 0 et la tension de référence (par exemple, entre 0 et 5 volts sur une Arduino standard). Voici quelques utilisations et fonctionnalités des broches Analog In :

  • Lecture de capteurs analogiques : Les broches Analog In sont couramment utilisées pour lire les signaux provenant de capteurs analogiques tels que des capteurs de lumière, des capteurs de température, des potentiomètres, des capteurs de pression, etc. Ces capteurs fournissent des informations analogiques qui peuvent être lues avec précision à l’aide des broches Analog In.
  • Conversion analogique-numérique (CAN) : Les broches Analog In sont équipées de convertisseurs analogique-numérique (CAN) qui convertissent la tension analogique mesurée en une valeur numérique que le microcontrôleur de la carte Arduino peut comprendre et traiter.
  • Lecture de signaux analogiques externes : Les broches Analog In peuvent également être utilisées pour mesurer des signaux analogiques externes provenant d’autres dispositifs électroniques.
  • Tension de référence : La carte Arduino utilise généralement la tension d’alimentation (VCC) comme référence par défaut pour les mesures analogiques. Cependant, il est possible de configurer une tension de référence différente en utilisant le pin AREF (Analog REFerence).
  • Pulse Width Modulation (PWM) : Bien que les broches Analog In soient principalement conçues pour la lecture de signaux analogiques, certaines d’entre elles peuvent également être utilisées en mode de sortie PWM (Pulse Width Modulation) pour contrôler la luminosité des LED ou la vitesse des moteurs.

En vert le pin « Vin » est l’entrée d’alimentation. Il est conçu pour recevoir une tension d’alimentation externe qui peut être utilisée pour alimenter la carte. « Vin » signifie « Voltage In », ce qui indique que c’est l’endroit où l’on fournie une tension d’alimentation à la carte. Dans ce tutoriel nous n’utiliserons pas ce pin.

En bleu ce sont encore des pin GND (grounds) qui ont la même utilité que ceux déjà présenté.

En rouge foncé le pin 5V (5 volts) sur une carte Arduino est une sortie qui fournit une tension de 5 volts. Il peut être utilisé pour alimenter des composants externes tels que des capteurs, des modules, des écrans ou d’autres dispositifs qui nécessitent une alimentation de 5 volts. Cela permet de simplifier le câblage en utilisant la source d’alimentation de la carte Arduino.

En jaune le pin 3.3V (3,3 volts) sur une carte Arduino est une sortie qui fournit une tension de 3,3 volts. Certains capteurs, modules et dispositifs électroniques fonctionnent avec une tension d’alimentation de 3,3 volts. Le pin 3.3V permet d’alimenter ces composants spécifiques sans nécessiter de conversion de tension externe.

En orange le pin RESET sur une carte Arduino est utilisé pour réinitialiser le microcontrôleur de la carte. Lorsqu’une impulsion basse (un passage de l’état haut à bas) est appliquée au pin RESET, le microcontrôleur de la carte Arduino est réinitialisé. Cette réinitialisation force le microcontrôleur à recommencer l’exécution du programme à partir du début. Ce pin est équivalent au bouton reset. Dans ce tutoriel nous n’utiliserons pas ce pin.

En blanc le pin IOREF (Input/Output REFerence) sur une carte Arduino sert à indiquer le niveau de tension de référence utilisé par les broches d’entrée/sortie de la carte. C’est généralement une broche de sortie qui fournit une indication de la tension de référence actuellement utilisée par les broches I/O (E/S) de la carte. Dans ce tutoriel nous n’utiliserons pas ce pin.

Enfin, il y a un dernier pin que je n’ai pas présenté, sur certaines cartes Arduino, à côté du pin IOREF, il peut y avoir un pin marqué « Reserved » (réservé) ou « Not Connected » (non connecté). Ce pin n’a pas de fonctionnalité ou d’utilisation standard spécifique définie par le schéma officiel de la carte Arduino. Son but est souvent de prévoir des options d’extension pour des fonctionnalités futures ou de permettre aux concepteurs de cartes d’ajouter des fonctionnalités personnalisées.

Installation et fonctionnement de l’IDE Arduino

Premièrement, il faudra se rendre sur le site d’Arduino, sur la page de téléchargement. Ensuite, une fois arrivé sur cette page, il faudra cliquer sur le système d’exploitation sur lequel vous êtes. Dans mon cas, je cliquerais sur Windows.

Une fois cela fait, vous arriverez sur cette page qui vous propose de faire une donation. Si vous en avez l’envie, vous pouvez le faire. Pour passer et continuer le téléchargement, il suffira de cliquer sur « JUST DOWNLOAD ».

Ensuite, vous arriverez sur cette page qui vous propose de vous inscrire à leur newsletter. Si vous le voulez, faites-le, mais dans notre cas, nous allons nous contenter de continuer le téléchargement en appuyant sur « JUST DOWNLOAD ».

Normalement, le téléchargement va se lancer, et une fois fini, je vous invite à « Extraire tout » du dossier dans un dossier approprié de votre ordinateur.

Une fois cela fait, nous allons nous retrouver avec tous ces fichiers. Il suffira simplement d’exécuter le fichier nommé « Arduino IDE.exe ». Pour y accéder plus facilement, je vous invite à créer un raccourci sur votre Bureau.

Et voilà, vous venez de terminer l’installation de l’IDE Arduino. Maintenant, il va falloir comprendre comment il fonctionne. Voici comment il se présente.

Premièrement, si l’on regarde en haut à gauche de l’IDE, on trouve trois boutons. Le premier (✓) sert à compiler le code que l’on insère afin de vérifier s’il fonctionne avant de l’envoyer dans la carte. Le second (➔) est celui qui sert à transférer le code dans la carte, et le dernier sert au débogage. En ce qui concerne la fenêtre où il y a écrit « Select Board », c’est ici que nous allons sélectionner notre carte pour y transférer le code.

Une fois cliqué sur « Select Board », vous pouvez choisir votre carte. Bien sûr, il faut qu’elle soit branchée à votre ordinateur et bien détectée. Personnellement, dans l’exemple ci-dessous, cela me propose les deux cartes qui sont branchées sur mon ordinateur avec les bons ports COM. Il faut faire attention à ce que ce soit bien les bons ports COM.

Sur le reste de l’écran, vous avez la zone de programmation où vous allez entrer votre code.

En bas de l’écran, vous avez la console qui vous indiquera les erreurs que vous faites lors de la compilation de votre code.

Et en haut à droite de votre écran, vous avez un petit symbole qui ressemble à une loupe, c’est le Serial Monitor. Il vous servira à voir certaines informations (il sera utile lorsque l’on utilisera le capteur à ultrason).

Ce ne sont pas toutes les fonctionnalités de l’IDE Arduino ; il y en a bien plus encore. Cependant, pour le moment, c’est de ces fonctionnalités que nous allons nous contenter.

Les composants de base et leurs fonctionnements

Nous allons donc voir quelques composants de base qui servent particulièrement lorsque l’on utilise l’Arduino. Je vous expliquerai leur fonctionnement, à quoi ils servent, et où les procurer.

La Platine d’expérimentation ou Breadboard

Voici une platine d’expérimentation, et comme son nom l’indique, elle sert à faire nos expériences. C’est donc sur cet objet que nous allons réaliser nos branchements. Cela peut paraître compliqué à première vue, mais son fonctionnement est très simple. Voici à quoi ressemble l’interrupteur d’une platine.

Les lignes bleues représentent la masse ou GND, comme nous l’avons vu précédemment. Quant aux lignes rouges, elles représentent l’alimentation. En ce qui concerne les lignes vertes, c’est ici que nous allons brancher nos composants pour les relier entre eux.

Les câbles

Ils permettent de réaliser des branchements entre différents composants. On les insère dans les trous prévus sur la carte et ceux dans la platine d’expérimentation pour faire circuler le courant électrique.

Les résistances

Les résistances sont des composants électroniques qui limitent le courant électrique dans un circuit en opposition à sa circulation. La principale fonction d’une résistance est de limiter le courant électrique qui circule dans un circuit. Elle agit comme un obstacle au passage du courant, ce qui permet de contrôler la quantité de courant circulant dans une partie spécifique du circuit. Les résistances sont souvent utilisées pour protéger d’autres composants électroniques, tels que les LED, en limitant le courant qui les traverse. Cela empêche ces composants de recevoir un courant excessif et de s’endommager. Il existe différents types de résistances, plus ou moins puissantes. On peut reconnaître leur valeur grâce au code couleur (les petites traits) qui se trouve sur elles, et cela permet de connaître leur valeur en ohms. Une résistance est généralement représentée par le symbole suivant :

Les LED

Les LED (Light Emitting Diode) sont des diodes électroluminescentes qui émettent de la lumière lorsqu’un courant électrique les traverse. Elles sont largement utilisées dans l’électronique pour diverses applications en raison de leur efficacité énergétique, de leur longue durée de vie et de leur faible consommation d’énergie. Dans ce tutoriel, nous les utiliserons beaucoup, car c’est un élément très visuel qui permet de facilement constater des changements. Une des précautions qu’il faut prendre avec les LED est qu’elles ont un sens. Les grandes pattes de la LED représentent le + et la petite patte le -. Si elles sont mal positionnées, la LED peut griller. Une LED est représentée par le symbole suivant :

Et voici un petit circuite qui nous permet d’expérimenter une LED :

void setup() { // pour ce qui font du python "void setup" est assimilable à "def __init__"
  pinMode(8, OUTPUT); //on déclare le pin que l'on utilise
}

void loop() { // la fonction "void loop" est une boucle
  digitalWrite(8, HIGH); //on allume la LED
  delay(1000); // attendre 1000 millisecond(s)
  digitalWrite(8, LOW); // on etteint la LED
  delay(1000); // attendre 1000 millisecond(s)
}

Pour résumer le fonctionnement du circuit précédent, on envoie de l’électricité dans le fil rouge qui passe par la résistance (220Ω) pour réduire l’intensité du courant, puis qui arrive à la LED et l’allume. Enfin, on ferme le circuit en arrivant au GND. Et tout cela avec des intervalles d’une seconde.

Les boutons poussoir

Un bouton-poussoir, également appelé interrupteur à bouton-poussoir, est un composant électronique simple qui permet d’établir ou de couper un circuit électrique lorsqu’on appuie sur son bouton.

Et voici un petit circuite qui nous permet d’expérimenter une LED et un bouton :

void setup() {
  pinMode(8, OUTPUT); //on déclare le pin de la LED que l'on utilise
  pinMode(7, INPUT); //on déclare le pin du bouton que l'on utilise et la déclare comme entré
}

void loop() {
  if (digitalRead(7) == HIGH){ //on applique la condition au "if" qui est si la pin 7 resois un signal 
  	digitalWrite(8, HIGH); // dans ce cas on allume la LED
  }
  else{
    digitalWrite(8, LOW); // sinon est reste éteint
  }
}

Ce qui se passe dans le circuit précédent est que l’on alimente le bouton. Quand on appuie sur le bouton, cela laisse passer l’électricité qui alimente alors la pin 7. Lorsque la pin 7 reçoit un signal, cela valide la condition d’allumage de la LED. La pin 8 envoie alors de l’électricité, et donc la LED s’allume. La LED est toujours protégée par une résistance de 220Ω, et le bouton lui est protégé par une résistance de 10kΩ.

Les buzzer

Un buzzer est un composant électronique qui émet un son lorsqu’il est alimenté en courant. Il est souvent utilisé pour fournir des indications sonores dans divers projets électroniques. Un buzzer est représentée par le symbole suivant :

Et voici un petit circuite qui nous permet d’expérimenter un buzzer :

void setup() {
  pinMode(13, OUTPUT); //on déclare le pin du buzzer que l'on utilise
}

void loop() {
  tone (13, 650); //On utilise "tone" pour activer le buzzer avec comme deuxième paramètre la fréquence émise par le buzzer.
}

Dans ce circuit, on allume le buzzer via la pin 13 avec une tonalité de 650. Il est possible de modifier ce chiffre pour obtenir différentes tonalités.

Les potentiomètre

Un potentiomètre est un composant électronique ajustable qui permet de régler la résistance électrique dans un circuit. Il est également souvent appelé « potar ». Un potentiomètre peut être décrit comme une résistance variable. Il permet de régler la résistance électrique dans un circuit. Le principe de fonctionnement d’un potentiomètre implique de déplacer un curseur le long d’une piste résistive, ce qui modifie la portion de résistance entre le curseur et les bornes fixes. il existe de multiples modèle qui sous tous différent les un des autres. Un potentiomètre est représentée par les symboles suivant :

Et voici un petit circuite qui nous permet d’expérimenter une LED et un potentiomètre :

void setup() {
  Serial.begin(9600); // instanciation 
  pinMode(A0, INPUT); // on définit le pin analog 0 comme pin d'entré
  pinMode(13, OUTPUT); // le pin 13 comme sorti
}

void loop() {
  analogWrite(13, analogRead(A0)/4);// Ici, on dit que la LED va s'éclairer à l'intensité 
									// de "analogRead(A0)", soit ce qui est ressorti par le 
									// potentiomètre. Cependant, cette valeur est dans l'intervalle 
									//[0, 1023], et une LED ne peut prendre que des valeurs entre 
									//[0, 255]. On divise donc "analogRead(A0)" par 4 pour obtenir 
 									//une valeur lisible pour la LED.
}

On définit notre potentiomètre sur la pin A0 et notre LED sur la pin 13. Enfin, dans la fonction loop, on allume notre LED avec comme variable l’intensité résultante du potentiomètre. ( a noté que la résistance utilisé est une résistance de 220Ω)

Les photorésistances

Une photorésistance, également appelée cellule photoconductrice ou résistance photo-sensible, est un composant électronique dont la résistance électrique varie en fonction de l’intensité lumineuse à laquelle elle est exposée. C’est un type de capteur de lumière largement utilisé dans divers projets électroniques. Une photorésistance est représentée par le symbole suivant :

Et voici un petit circuite qui nous permet d’expérimenter une LED et une photorésistance :

void setup() {
  pinMode(A0, INPUT); // on définit le pin analog 0 comme pin d'entré
  pinMode(10, OUTPUT); // le pin 13 comme sorti
}

void loop() {
  if (analogRead(A0) > 400){ // Si la photorésistance ressort une valeur supérieure à 400.
    digitalWrite(10, HIGH); // Alors on allume la LED
  }
  else{ // Sinon
    digitalWrite(10, LOW); // Elle reste éteinte
  }
}

Ici, on branche notre photorésistance sur la pin A0 et notre LED sur la pin 10. Dans la fonction loop, on définit que la condition d’activation de la LED est si la valeur retournée par la photorésistance est supérieure à 400, soit un environnement un peu lumineux. À noter que l’on ne met pas une valeur en dessous de 400, car sinon la LED resterait allumée la plupart du temps en raison de la sensibilité de la photorésistance. (ici la résistance utilisé pour la LED est une résistance de 220Ω, et celle pour la photorésistance est de 10kΩ)

Les capteurs à ultrasons

Un capteur à ultrasons est un dispositif électronique qui utilise des ondes sonores à une fréquence supérieure à la limite supérieure de l’audition humaine (généralement supérieure à 20 kilohertz) pour mesurer la distance entre le capteur et un objet. Ces capteurs fonctionnent sur le principe de l’écholocation, similaire à la façon dont certains animaux utilisent des sons pour évaluer la distance et la position des objets dans leur environnement. dans l’exemple suivant nous utiliserons le capteur à ultra son de référence HC-SR04. Et voici un petit circuite qui nous permet d’expérimenter un capteur à ultrasons :

long temps; // Déclaration de variables pour stocker le temps de retour du signal ultrasonique et la distance calculée.
float distance;

void setup() {
  pinMode(2, OUTPUT); // Configuration des broches : 2 en mode sortie pour envoyer le signal ultrasonique,
  pinMode(3, INPUT); // Configuration des broches : 3 en mode entrée pour recevoir le signal de retour.
  digitalWrite(2, LOW); // Initialisation de la broche 2 à un état bas, prête à émettre le signal ultrasonique.
  Serial.begin(9600); // Initialisation de la communication série à une vitesse de 9600 bauds pour l'affichage des résultats.
}

void loop() {
  digitalWrite(2, HIGH); // Activation de la broche 2 pour émettre une impulsion ultrasonique.
  delayMicroseconds(10); // Attente de 10 microsecondes pour laisser le temps au signal ultrasonique de se propager.
  digitalWrite(2, LOW); // Désactivation de la broche 2 après l'impulsion.
  temps = pulseIn(3, HIGH); // Mesure du temps nécessaire pour que le signal ultrasonique revienne à la broche 3.
  if (temps > 25000) { // Vérification si le temps mesuré est supérieur à 25 000 microsecondes (25 millisecondes).
    Serial.println("Echec de la mesure"); // Affichage d'un message d'échec de mesure sur le moniteur série.
  } else {
    temps = temps / 2; // Utilisation de la moitié du temps mesuré car le signal ultrasonique fait l'aller-retour.
    distance = (temps * 340) / 10000.0; // Calcul de la distance en centimètres en utilisant la vitesse du son (340 m/s).
    Serial.print("Distance: "); // Affichage de la distance mesurée sur le moniteur série.
    Serial.print(distance);
    Serial.println(" cm");
  }
  delay(2000); // Attente de 2 secondes avant de répéter la mesure.
}

Les capteurs sonore

Les capteurs sonores, aussi appelés microphones ou capteurs audio, sont des dispositifs électroniques qui convertissent les variations de pression acoustique (ondes sonores) en un signal électrique. Ces capteurs sont largement utilisés pour capter des signaux sonores dans diverses applications. Et voici un petit circuite qui nous permet d’expérimenter un capteur sonores avec une LED. (malheureusement Tinkercad n’a pas cet élément je suis donc obliger de prendre des photos et donc la qualité sera moindre) :

Pour la connexion du capteur sonore à l’Arduino, j’utilise trois câbles : un gris, un noir, et un blanc. Le câble gris est relié de la broche digitale du détecteur sonore à la broche A2 de la carte. Le câble noir est relié de la broche + du détecteur sonore au 5V de la carte, et le câble blanc est relié de la broche G (ou GND) au pin GND de la carte.

En ce qui concerne le branchement de la LED, c’est un simple branchement où l’on utilise une résistance de 220Ω.

void setup() {
  Serial.begin(9600); // Initialisation de la communication série à une vitesse de 9600 bauds pour l'affichage des résultats.
  pinMode(13, OUTPUT); // Configuration de la broche 13 en mode sortie pour contrôler la LED.
  pinMode(A2, INPUT); // Configuration de la broche A2 en mode entrée pour lire une valeur analogique.
}

void loop() {
  if (analogRead(A2) >= 200) { // Vérification si la valeur lue depuis la broche A2 est supérieure ou égale à 200.
    digitalWrite(13, HIGH); // Allumage de la LED (broche 13) si la condition est vraie.
    delay(1000); // Attente de 1000 millisecondes (1 seconde).
  } else {
    digitalWrite(13, LOW); // Extinction de la LED (broche 13) si la condition n'est pas vraie.
  }
}

Il est important de noter qu’il est souvent nécessaire de calibrer son capteur sonore. Pour cela, il suffit de se munir d’un petit tournevis plat et de faire tourner la petite vis qui se trouve en haut du composant bleu du capteur sonore afin d’augmenter ou de réduire la sensibilité. Pour ma part, elle était grandement trop élevée, c’est donc à vous de régler cette partie. Une fois réglé, à chaque détection sonore, la LED s’allumera pendant 1 seconde.

Comment et ou obtenir du matérielle ?

Magasins en Ligne spécialisés :

Les magasins en ligne offrent une multitude d’options pour acheter des composants Arduino. Des sites tels que Adafruit, SparkFun, et Arduino Store proposent une large sélection de capteurs, de modules, de cartes et d’accessoires. Assurez-vous de vérifier les avis des utilisateurs pour garantir la qualité des produits avant d’effectuer votre achat.

Plateformes de Commerce Électronique :

Des sites comme Amazon, eBay, Temu et AliExpress proposent également une variété de composants Arduino. Cependant, soyez attentif à la provenance des produits et lisez les commentaires des utilisateurs pour éviter les contrefaçons et assurer la fiabilité des composants. La casse lors du transport des composants est plus fréquente, et les frais de transport peuvent être élevés. Cependant, les prix sont en général moins chers.

Recyclage Électronique :

Pour les bricoleurs soucieux de l’environnement, la récupération de composants électroniques à partir d’appareils recyclés peut être une option intéressante. Les vieux ordinateurs, téléphones portables et autres dispositifs électroniques obsolètes peuvent fournir une source abordable de composants. Par exemple, personnellement, en démontant un réveil, j’ai pu récupérer un afficheur de 7 segments à 4 digits, 4 boutons, un haut-parleur et d’autres petits composants.

Magasins Locaux de Bricolage :

Certains magasins de bricolage peuvent proposer une petite sélection de composants électroniques de base, comme des résistances, des transistors ou des diodes. Bien que le choix soit limité, cela peut être une solution pratique pour des besoins simples. Aussi bien qu’ils se fassent rares, il existe encore des magasins physiques de composants électroniques.

N’oubliez pas de vérifier la compatibilité des composants avec votre carte Arduino et de suivre les bonnes pratiques en matière d’électronique pour assurer la réussite de vos projets.

Projet de fin de tutoriel

Pour conclure ce tutoriel, nous allons faire un radars de recule, il comportera 5 LED de couleurs différentes, un buzzer, et un capteurs à ultrasons.

long temps;
float distance;

void setup() {
  pinMode(2, OUTPUT); // Configuration des broches : 2 en mode sortie pour envoyer le signal ultrasonique,
  pinMode(3, INPUT); // Configuration des broches : 3 en mode entrée pour recevoir le signal de retour.
  pinMode(4, OUTPUT); // on définit les pin 4, 5, 6, 7, 8 pour les LED
  pinMode(5, OUTPUT); 
  pinMode(6, OUTPUT); 
  pinMode(7, OUTPUT); 
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT); // on définit le pin 9 pour le buzzer
  digitalWrite(2, LOW); // Initialisation de la broche 2 à un état bas, prête à émettre le signal ultrasonique.
  Serial.begin(9600); // Initialisation de la communication série à une vitesse de 9600 bauds pour l'affichage des résultats.
}

void loop() {
  digitalWrite(2, HIGH); // Activation de la broche 2 pour émettre une impulsion ultrasonique.
  delayMicroseconds(10); // Attente de 10 microsecondes pour laisser le temps au signal ultrasonique de se propager.
  digitalWrite(2, LOW); // Désactivation de la broche 2 après l'impulsion.
  temps = pulseIn(3, HIGH); // Mesure du temps nécessaire pour que le signal ultrasonique revienne à la broche 3.
  if (temps > 25000) { // Vérification si le temps mesuré est supérieur à 25 000 microsecondes (25 millisecondes).
    Serial.println("Echec de la mesure"); // Affichage d'un message d'échec de mesure sur le moniteur série.
  } else {
    temps = temps / 2; // Utilisation de la moitié du temps mesuré car le signal ultrasonique fait l'aller-retour.
    distance = (temps * 340) / 10000.0; // Calcul de la distance en centimètres en utilisant la vitesse du son (340 m/s).
    Serial.print("Distance: "); // Affichage de la distance mesurée sur le moniteur série.
    Serial.print(distance);
    Serial.println(" cm");
    if (distance <= 300 ){
      digitalWrite(4, HIGH); // on allume la LED 4 
      digitalWrite(5, LOW); // on etteint les autres LED
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      tone(9, 350); // Activation du buzzer avec une fréquence de 35=50 Hz
    }
    if (distance <= 200 ){
      digitalWrite(4, LOW);// on etteint les autres LED
      digitalWrite(5, HIGH); // on allume la LED 5 
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      tone(9, 550); // Activation du buzzer avec une fréquence de 550 Hz
    }
    if (distance <= 50 ){
      digitalWrite(4, LOW);// on etteint les autres LED
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH); // on allume la LED 6 
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      tone(9, 750); // Activation du buzzer avec une fréquence de 750 Hz
    }
    if (distance <= 15 ){
      digitalWrite(4, LOW);// on etteint les autres LED
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, HIGH);// on allume la LED 7 
      digitalWrite(8, LOW);
      tone(9, 950); // Activation du buzzer avec une fréquence de 950 Hz
    }
    if (distance <= 6 ){
      digitalWrite(4, LOW);// on etteint les autres LED
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, HIGH); // on allume la LED 8 
      tone(9, 1050); // Activation du buzzer avec une fréquence de 1050 Hz
    }
  }
  delay(1000); // Attente de 1 seconde avant de répéter la mesure.
}

On se retrouve finalement avec un « radar ». Plus un objet est proche du radar, plus la tonalité du buzzer change, et plus on s’approche, plus les LED vont de la LED bleue vers la LED blanche.

Sources

Conclusion

En conclusion, l’exploration de l’Arduino ne représente qu’une simple plongée dans l’électronique. Ce que je vous ai montré n’est qu’une infime partie de ce que représente Arduino et l’électronique en général. J’ai abordé le fonctionnement de base d’une carte et comment on peut l’utiliser, mais c’est à vous d’imaginer et d’inventer des utilisations pour ces composants. Si vous souhaitez continuer avec Arduino, il peut être difficile de savoir par où commencer. C’est pourquoi il peut être bénéfique d’apprendre à travers des tutoriels, comme celui-ci. Je vous redirige donc vers un tutoriel que j’ai suivi réalisé par le Geek et son Marteau, qui est très bien réalisé et qui vous apprendra à faire un Stream Deck avec Arduino.

Amusez-vous bien !

Projets

Jeu vidéo en Python à l’aide de la librairie…

Dans le cadre du projet libre de fin d’année en NSI, je vous présente mon premier jeux vidéo en python fait à l’aide de pygame, une librairie spécialisé pour la création de jeux vidéo.

Librairie Pygame

Pygame est une bibliothèque de jeu open-source pour Python, qui permet de créer des jeux et des applications multimédias. Elle fournit des outils pour gérer les graphismes, le son, les entrées utilisateur, le réseau et plus encore.

Pygame utilise la bibliothèque SDL (Simple DirectMedia Layer) pour accéder aux fonctions du système d’exploitation, ce qui signifie que les jeux créés avec Pygame peuvent fonctionner sur de nombreuses plateformes, notamment Windows, macOS et Linux.

Pygame est une excellente option pour les débutants qui cherchent à créer des jeux simples (des base en programmation sont cependant nécessaire), mais il peut également être utilisé pour créer des jeux professionnels et des applications multimédias complexes.

Le Projet

Mon objectif sur ce projet a été de faire mes premiers pas avec la bibliothèque Pygame en Python. Cela a été un véritable défi qui m’aura fait découvrir de nombreuses mécaniques en Python, telles que le système de classe ou la programmation orientée objet, qui ont représenté pour moi un pas dans l’inconnu. Mon défi a donc été de créer un jeu simple pour débuter. Le but est de contrôler un personnage avec sa souris et d’éviter des briques qui apparaissent aléatoirement sur le côté de l’écran, tout cela en ayant le choix entre trois niveaux de difficulté différents.

Structure du Script

Pour la réalisation de mon jeu, j’ai décidé de me lancer un défi supplémentaire : l’utilisation de la Programmation Orientée Objet. Mais qu’est-ce que la Programmation Orientée Objet ?

La Programmation Orientée Objet est un paradigme de programmation qui permet de structurer un programme en utilisant des objets, qui sont des entités possédant des caractéristiques et des comportements spécifiques. Cette approche permet de modéliser des concepts du monde réel de manière plus naturelle et intuitive, en regroupant des fonctionnalités liées dans des classes, et en instanciant ces classes pour créer des objets.

En résumé, cela consiste à organiser son code de manière à ce qu’il soit ordonné à l’aide de classes contenant des fonctions et des constantes générales, ce qui conduit à un code plus lisible, plus maintenable et plus ordonné. Cependant, cela peut être relativement perturbant au début.

Voici un simple scripte sans utilisation de Programmation Orienté Objet qui permet de faire bougé une image nommé « ball.png » à l’aide des flèches directionnelles :

import pygame

pygame.init()
screen = pygame.display.set_mode((400, 400))
running = True

image = pygame.image.load("ball.png")

x = 0
y = 0

clock = pygame.time.Clock()

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_LEFT]:
        x -= 1
    if pressed[pygame.K_RIGHT]:
        x += 1
    if pressed[pygame.K_UP]:
        y -= 1
    if pressed[pygame.K_DOWN]:
        y += 1

    screen.fill((0, 0, 0))
    screen.blit(image, (x, y))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

code by TNtube

Le scripte est simple et efficace, pour autant si il venais à se complexifier cela deviendrait vite illisible.
voici maintenant le même scripte avec l’utilisation de la Programmation Orienté Objet :

player.py

import pygame

class Player:
    def __init__(self, x, y):
        self.image = pygame.image.load("player.png")
        self.image
        self.rect = self.image.get_rect(x=x, y=y)
        self.speed = 5
        self.velocity = [0, 0]

    def move(self):
        self.rect.move_ip(self.velocity[0] * self.speed, self.velocity[1] * self.speed)

    def draw(self, screen):
        screen.blit(self.image, self.rect)

Main.py

import pygame
from player import Player


class Game:
    def __init__(self, screen):
        self.screen = screen
        self.running = True
        self.clock = pygame.time.Clock()
        self.player = Player(0, 0)

    def handling_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.player.velocity[0] = -1
        elif keys[pygame.K_RIGHT]:
            self.player.velocity[0] = 1
        else:
            self.player.velocity[0] = 0

        if keys[pygame.K_UP]:
            self.player.velocity[1] = -1
        elif keys[pygame.K_DOWN]:
            self.player.velocity[1] = 1
        else:
            self.player.velocity[1] = 0

    def update(self):
        pass

    def display(self):
        self.screen.fill("white")
        pygame.display.flip()

    def run(self):
        while self.running:
            self.handling_events()
            self.update()
            self.display()
            self.clock.tick(60)


pygame.init()
screen = pygame.display.set_mode((1080, 720))
game = Game(screen)
game.run()

pygame.quit()

code by TNtube

La particularité ici réside dans la clarté de chaque fonction et de leur utilité respective : « display » pour l’affichage, « handling_event » pour les interactions claviers-souris, « move » pour les mouvements du joueur… De plus, le programme est divisé en deux fichiers distincts : l’un pour le programme principal et l’autre pour le joueur. Ainsi, il est possible d’ajouter aisément de nouvelles fonctions pour des améliorations futures. Par exemple, la fonction « Update », actuellement inactive, pourrait être employée pour effectuer des vérifications, telles que les collisions.

Analyse du script

Passons maintenant à l’analyse du code.

Commençons par mon fichier « player.py », avec l’appel du module Pygame, la création de la classe et la fonction d’initialisation.

import pygame #On importe le module Pygame

class Player: #On crée la classe Player
    
# La fonction init est une fonction d'initialisation qui permet de déclarer toutes nos variables.
# Elle prend comme arguments self, qui est pris dans chaque fonction de la classe, x et y qui servent à définir la position initiale du joueur sur l'écran.
def init(self, x, y):
self.image = pygame.image.load("asset/Player.png")# On charge l'image du joueur
#Pour que vous puissiez être familiarisé avec le concept de rect, ce sont des rectangles que l'on ne voit pas, qui ont une taille que l'on leur définit et c'est grâce à ces rect, que l'on pourrait appeler hitbox, que l'on peut détecter des collisions.
self.rect = self.image.get_rect(center=(x, y))# On récupère le rectangle de l'image et on le centre en (x,y)
self.velocity = [0, 0]# On initialise la vitesse à 0 dans les deux directions

Une fois la mise en place de notre classe et de la fonction d’initialisation effectuée, nous créons la fonction de mouvement du joueur appelée « move », ainsi qu’une fonction « draw » qui permettra d’afficher notre personnage avec son rectangle.

def move(self, mouse_pos):# La fonction move permet de déplacer le joueur en fonction de la position de la souris, l'argument mouse_pos représente la position de la souris sur l'écran. Cette position est utilisée pour calculer la vitesse de déplacement du joueur, en soustrayant la position de la souris à la position actuelle du joueur.
    # On calcule la différence entre la position de la souris et la position actuelle du joueur
    self.velocity[0] = (mouse_pos[0] - self.rect.centerx)
    self.velocity[1] = (mouse_pos[1] - self.rect.centery)
    self.rect.move_ip(self.velocity)# On déplace le rectangle du joueur en fonction de la vitesse calculée

def draw(self, screen):# La fonction draw permet d'afficher le joueur sur l'écran
    screen.blit(self.image, self.rect)# On blitte (st utilisée pour dessiner une surface sur une autre surface.) l'image du joueur sur le rectangle de celui-ci

Maintenait que je vous ai introduis mon fichier joueur passons au fichier jeu.

import pygame
import random
from player import Player

On importe les modules nécessaires au fonctionnement du jeu : Pygame pour gérer l’affichage graphique et l’interaction avec l’utilisateur, random pour générer des nombres aléatoires, et Player qui est une classe définie dans un fichier séparé et qui représente le joueur.

class Game:
    def __init__(self, screen):
        self.screen = screen
        self.running = True
        self.clock = pygame.time.Clock()
        self.player = Player(60, 60)
        self.background = pygame.image.load("asset/background.jpg")
        self.brique = pygame.image.load("asset/brique.jpg")
        self.brique_rects = []
        self.brique_positions = []
        self.brique_speed = 3
        self.brique_spawn_rate = 120
        self.brique_spawn_counter = 0
        self.brique_spawn_augmentation = 15
        self.brique_spawn_increase_counter = 0
        self.total_time = 0
        self.total_time_max = 0
        self.difficulté = 20
        pygame.mouse.set_visible(False)
        
        choix = input("_____________________________________________________________________________ \n choisissez votre difficulté : \n 1- Facile \n 2- Normal \n 3- Difficile \n _____________________________________________________________________________ \n Votre choix : ")
        choix = int(choix)
        if choix == 1:
            self.difficulté = 1
        elif choix == 2:
            self.difficulté = 5
        elif choix == 3:
            self.difficulté = 10
        else:
            print("Error : s'il vous plait entré un entier positif entre 1 et 3")
            self.running = False

On définit la classe Game, qui représente le jeu en lui-même. Son constructeur prend en paramètre l’objet screen qui représente la surface sur laquelle le jeu sera affiché.

On initialise différentes variables, comme self.running qui permet de savoir si le jeu est en cours d’exécution ou non, self.player qui représente le joueur, self.background qui est l’image de fond, self.brique qui est l’image représentant les obstacles à éviter, et plusieurs variables liées à ces obstacles (self.brique_positions, self.brique_speed, self.brique_spawn_rate, self.brique_spawn_counter, self.brique_spawn_augmentation, self.brique_spawn_increase_counter).

On définit également self.total_time et self.total_time_max pour gérer le temps de jeu, et self.difficulté qui est utilisé pour régler la difficulté du jeu en fonction de la réponse de l’utilisateur à une question posée par input.

Enfin, on masque le curseur de la souris avec pygame.mouse.set_visible(False).

    def gestion_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

        self.player.move(pygame.mouse.get_pos())

La méthode gestion_events permet de gérer les événements liés à l’interaction de l’utilisateur avec la fenêtre Pygame.

Le code utilise une boucle for pour récupérer chaque événement dans la liste des événements de Pygame. Si l’un des événements est de type QUIT, cela signifie que l’utilisateur a cliqué sur le bouton de fermeture de la fenêtre. Dans ce cas, la variable self.running est définie sur False, ce qui interrompt la boucle de jeu.

La méthode appelle également la méthode move de l’objet Player pour mettre à jour sa position en fonction de la position de la souris de l’utilisateur.

   def adaptative_brique_rects(self):
        self.brique_rects = []

        for pos in self.brique_positions:
            rect = pygame.Rect(pos[0], pos[1], self.brique.get_width(), self.brique.get_height())
            self.brique_rects.append(rect)

La méthode adaptative_brique_rects est appelée pour mettre à jour les rects de collision des briques en fonction de leurs nouvelles positions.

 def spawn_brique(self):
        y = random.randint(0, self.screen.get_height() - self.brique.get_height())
        self.brique_positions.append((-self.brique.get_width(), y))

La méthode spawn_brique est appelée pour générer une nouvelle brique à une position aléatoire sur l’axe y et avec une position initiale en dehors de la fenêtre sur l’axe x.

    def move_briques(self):
        for i in range(len(self.brique_positions)):
            pos = list(self.brique_positions[i])
            pos[0] += self.brique_speed
            self.brique_positions[i] = tuple(pos)

        self.adaptative_brique_rects()

La méthode move_briques met à jour la position des briques en ajoutant la valeur de self.brique_speed à la coordonnée x de chaque position dans self.brique_positions.

def update(self):
    # Incrémenter le compteur de temps de spawn des briques par la difficulté du jeu
    self.brique_spawn_counter += self.difficulté

    # Augmenter la vitesse des briques si le compteur de spawn des briques est un multiple de 120
    if self.brique_spawn_counter % 120 == 0:
        self.brique_speed += 0.2

    # Vérifier si le compteur d'augmentation de spawn des briques a atteint sa limite
    self.brique_spawn_increase_counter += 1
    if self.brique_spawn_increase_counter >= self.brique_spawn_augmentation * 60:
        self.brique_spawn_increase_counter = 0
        self.brique_spawn_rate -= 10

    # Ajouter une nouvelle brique à la liste des positions de briques si le compteur de spawn des briques a atteint le taux de spawn des briques
    if self.brique_spawn_counter >= self.brique_spawn_rate:
        self.brique_spawn_counter = 0
        self.spawn_brique()

    # Déplacer toutes les briques dans la direction de la vitesse actuelle des briques
    self.move_briques()

    # Incrémenter le temps total de jeu de 1
    self.total_time += 1  

    # Vérifier si le joueur a perdu en entrant en collision avec une brique
    for rect in self.brique_rects:
        if rect.colliderect(self.player.rect):
            print("_____________________________________________________________________________\n")
            print("    Vous avez perdu, Votre temps est de", self.total_time/100, "secondes, bien joué à vous ;)")
            print("_____________________________________________________________________________\n")
            self.running = False
            break
        else:
            pass

La méthode update est appelée à chaque boucle de jeu pour mettre à jour les positions des briques, vérifier si le joueur a perdu en entrant en collision avec une brique et pour augmenter la difficulté du jeu.

Elle commence par incrémenter le compteur de temps de spawn des briques par la difficulté du jeu, pour que les briques apparaissent plus rapidement avec des niveaux de difficulté plus élevés.

Ensuite, si le compteur de spawn des briques est un multiple de 120, la vitesse de déplacement des briques est augmentée de 0,2.

La méthode vérifie également si le compteur d’augmentation de spawn des briques a atteint sa limite, qui est définie par self.brique_spawn_augmentation * 60. Si c’est le cas, le compteur est réinitialisé et le taux de spawn des briques est diminué de 10.

Si le compteur de spawn des briques atteint le taux de spawn des briques défini par self.brique_spawn_rate, la méthode spawn_brique est appelée pour ajouter une nouvelle brique à la liste des positions de briques.

La méthode move_briques est ensuite appelée pour déplacer toutes les briques dans la direction de la vitesse actuelle des briques.

Le temps total de jeu est ensuite incrémenté de 1.

Enfin, pour chaque rect de brique dans la liste self.brique_rects, la méthode vérifie s’il y a une collision avec le rectangle de la zone de collision du joueur. Si c’est le cas, la méthode affiche le message de fin de jeu et met la variable self.running à False pour arrêter la boucle de jeu.

def display(self):
    # Afficher le fond d'écran
    self.screen.blit(self.background, (-200, -350))

    # Parcourir toutes les positions des briques et les afficher
    for pos in self.brique_positions:
        self.screen.blit(self.brique, pos)

    # Afficher le joueur
    self.player.draw(self.screen)

    # Mettre à jour l'affichage
    pygame.display.flip()

La méthode display(self) affiche les éléments du jeu sur l’écran. Elle utilise la méthode blit pour afficher le fond d’écran, chaque brique de la liste brique_positions et le joueur (player) sur l’écran. Ensuite, elle appelle la méthode flip de la classe pygame.display pour mettre à jour l’affichage.

def run(self):
    # Boucle principale du jeu
    while self.running:
        # Gérer les événements (ex: appuyer sur une touche, quitter le jeu)
        self.gestion_events()

        # Mettre à jour le jeu (ex: déplacer les briques, vérifier les collisions)
        self.update()

        # Afficher le jeu
        self.display()

        # Limiter le nombre de frames par seconde à 60
        self.clock.tick(60)

    # Réafficher la souris et quitter Pygame
    pygame.mouse.set_visible(True)
    pygame.quit()

La méthode run(self) contient la boucle principale du jeu. Elle s’exécute tant que l’attribut running est vrai. À chaque itération de la boucle, elle gère les événements (appel à gestion_events()), met à jour les éléments du jeu (appel à update()), affiche le contenu du jeu sur l’écran (appel à display()) et attend un certain temps défini par la méthode tick de pygame.time.Clock. Enfin, elle quitte le jeu (pygame.quit()) lorsque la boucle est terminée.

# Initialiser Pygame
pygame.init()

# Créer une fenêtre de jeu
screen = pygame.display.set_mode((1080, 720))

# Créer une instance de la classe Game en lui passant la fenêtre de jeu en argument
game = Game(screen)

# Lancer le jeu
game.run()

# Quitter Pygame
pygame.quit()

La partie en dehors de la classe initialise la bibliothèque Pygame (pygame.init()) et crée une fenêtre de jeu (pygame.display.set_mode((1080, 720))). Ensuite, elle crée une instance de la classe Game avec l’écran en tant qu’argument et appelle la méthode run de l’instance pour démarrer le jeu. Enfin, elle quitte la bibliothèque Pygame (pygame.quit()) après la fin du jeu.

Sources :

Conclusion

En conclusion, ce projet est un petit jeu simple mais amusant, il est sur l’univers de Mario. Si vous voulez essayer ce jeu par vous-même, vous pouvez le télécharger en cliquant sur le lien ci-dessous. Pour lancer le jeu, assurez-vous d’écrire le niveau de difficulté souhaité (1, 2 ou 3) dans la console Python. Si vous ne le faites pas, la fenêtre restera noire et le jeu ne se lancera pas. On commande le personnage avec sa souris.

Amusez-vous bien !

Tutoriels

Comment installer Linux Ubuntu sur son ordinateur, tout en…

Dans le cadre du projet « Ecrire un tutoriel en NSI« , je vous propose ce tutoriel pour apprendre simplement et efficacement comment installer correctement Linux Ubuntu sur son ordinateur tout en gardant Windows. Un tutoriel pas à pas qui aidera les plus débutants d’entre vous.

Pourquoi Installer Ubuntu ?

Premièrement, Linux est un OS/environnement de travail plus propice à une utilisation informatique poussée. Il enlève toutes les contraintes de sécurité que l’on pourrait retrouver sur Windows. Linux est bien moins gourmand en puissance de calcul que Windows, vous pourriez donc donner une seconde vie à un vieil ordinateur qui n’arrive plus à faire tourner Windows, ou bien rendre plus performant le votre. Pourquoi Ubuntu? Je conseille Ubuntu comme première version de Linux car c’est, pour moi, la distribution de Linux la plus convenable pour les premiers pas d’un(e) nouvel(le) utilisateur(trice) de Linux. Certaines distributions, comme Kali, sont compliquées à prendre en main et peuvent déstabiliser un(e) nouvel(le) utilisateur(trice).

Matérielle nécessaire :

  • Une clé vierge USB 4G minimum (possibilité de gravé un cd pour l’inhalation (fichier en .iso))
  • Disque dur / ssd avec minimum 25G de libre
  • Une connexion internet

Conseille avant de commencer :

Pour ne pas faire de mauvais manipulation ou endommagé vos appareille, je vous conseille de tester ce tuto sur un veille ordinateur, ou de faire une Back-up de votre ordinateur avant de commencé quoi que ce soit, ce maitre mon de ce tuto sera de prendre son temp.

Créer une clé USB bootable :

Télécharger Ubuntu :

Pour commencer allez sur le site officiel de Ubuntu pour téléchargé la dernier version :

Le fichier fait 3,6 Go dans sa version actuelle, il est donc normal que cela prenne un certain temps à s’installer (vous remarquerez que le fichier est en .iso, ce qui fait qu’il est possible de graver un disque pour en faire le support d’installation).

Téléchargement Rufus et son utilisation :

Rufus permet de formater et de rendre bootable n’importe quel support amovible de stockage tel que les clés USB ou les disques durs externes, et c’est cet outil que nous allons utiliser.

Commençons par téléchargé la dernier version de Rufus (ici la 3.21):

Puis lancé le .exe, accepté la demande de droit d’administrateur. La fenêtre de Rufus devrai alors souvrire et devrais ressemblé à cela :

On choisi son périphérique :

On appuie sur le bouton Sélectionner pour aller chercher le fichier de Ubuntu que l’on vient de télécharger, puis sur le bouton Démarrer. Cela va ouvrir une fenêtre où l’on laisse les paramètres par défauts et où l’on accepte avec Ok et l’on accepte encore une fois le deuxième avertissement qui nous indique que la clé USB va être formatée. Une fois cela fait, cela risque de prendre un peu de temps en fonction de votre ordinateur. Il suffit juste d’attendre la fin du chargement.

Une fois la conversion réaliser cliquez simplement sur Fermer, et c’est finit, vous venez de réalisé une clé USB bootable fonctionnelle !!!

Créer une partition dans son disque pour installer Ubuntu :

Avant de commencé quoi que ce soit sachez que cette étape peux être optionnelle si vous possédée deux disque dans votre ordinateur et que vous décidé d’utilisé l’entièreté de l’un de ces deux disque pour installer Ubuntu.

Premièrement regardez si il vous reste de l’espace disponible dans votre disque et si cette espace restant n’est essentielle. Puis allez dans la barre de recherche Windows et tapez « Partitions » et cliqué sur l’outil l’outils « Créer et formaté des partitions de disque dur« , une fois ouvert une nouvel fenêtre devrais s’ouvrir vous permettant de voir vo(s) disque(s) :

Fait clic droit sur le disque ou vous souhaitez installer Ubuntu et cliquer sur Réduire le volume ... cela vas alors calculé l’espace de stockage que Windows peut vous libéré pour faire votre installation.

Ici on me propose un espace de 69 Go mais je n’aurais besoin que de 40 Go soit 40.000 Mo, j’indique donc la valeur dans « Quantité d’espace à réduire » et j’appuis sur réduire :

On vois bien qu’est espace  à 40 Go à été libéré.

Installation et configuration de Ubuntu :

Démarre son ordinateur sur la clé USB bootable :

Premièrement braché votre clés USB à votre ordinateur. Nous arrivons maintenant sur une étape délicate ou je ne vais pas pouvoir vous guider plus que cela. l’idée pour démarré sur la clé USB est d’allé dans le Bios pour ouvrir la clé USB dans le Boots menu, il vas donc falloir ouvrir la Bios, l’ouverture du Bios est spécifique au modèle de carte mère de chaque ordinateur, pour savoir exactement comment faire, je vous conseille de regarder le guide de votre carte mère pour voir, ou bien celui de la référence de votre ordinateur pour l’ouvrir. la plus part du temp il surfil simplement de matraqua les touches F2, ou DEL l’ors de l’allumage du l’ordinateur, mais cela ne marche pas forcément est surtout ut les les ordinateur portables (fast boute empêche les raccourcis habituelle pour ceux qui connaissent), je vous propose donc cette petit vidéo pour tout les personnes qui pourrais avoir du mal.

Une fois le Bios ouvert la aussi tout vas dépendre de votre ordinateur et de ça carte mère, il y a des bios avec des interface plus ou moins graphique , pour autant le but va être d’accédé au Boot menu, puis de choisir votre clé USB qui contiens Ubuntu pour démarré dessue pour que l’installation commence, je vous met si dessous quelques screen shot d’a quoi à ressemblé mon installation :

Ouverture du Bios
ici j’ai échanger USB DISK 3.0 et Windows Boot manager ce qui fait que l’ordinateur démarrera sur la clé USB
Fermeture en enregistrement des modifications

Une fois les étapes présidentes réalisé, le Grub devrais s’ouvrir vous laissant le choix entre plusieurs lancement, vous allez choisir Try or Install Ubuntu.

Une fois cela fait un écran de chargement devrais ce lancé vous laissant apparaitre le logo de Ubuntu

Installation et Paramétrage de Ubuntu :

Bravo ! Si vous êtes à cette étapes c’est que vous avez passé la premier parti difficile de cette installation. Nous allons donc maintenant installé définitivement Ubuntu et le configure correctement.

Premièrement choisissez votre langue puis cliqué sur Install Ubuntu, ensuite choisissez quel types de configuration de clavier vous voulez (Frenche-French(legacy, alt.)), n’hésitez pas à testé toutes vos touches et tout les symboles pour vérifier que tout fonctionne correctement, puis connecté vous à votre Wi-Fi.

Nous arrivons au premier écran « important », cela vas concerné la case à cocher « Installer un logiciel pour le matériel graphique et Wi-Fi et des formats de média supplémentaire« , cela vas permettre à Ubuntu d’accepté d’installé des logicielle auquel il n’a pas acquêt, comme les pilot de carte graphique (les pilots de NVidia, qui sont des pilots propriétaires ) ou des pilots de cartes Wi-Fi. Une fois cette case cocher configure le mot de passe pour le sécure Boot ( vous n’y aurais pas recours fréquemment, voir jamais, je vous conseille de mettre le même mot de passe que celui de votre ordinateur), une fois cela fait cliqué sur « continuer »

Et nous arrivons sur l’écran LE PLUS IMPORTANT :

Ici l’on vas choisir entre une installation manuel ou automatique de Ubuntu, pour terminé rapidement, mais je ne conseille pas cette solution, pour continuer cliqué sur « Autre chose » puis continuer pour arrive à l’écran de paramétrage finale:

Premièrement regardons en fonction de l’espace disponible quelle espace faut-il alloué à chaque partie, pour cela regarde cette feuille de calcule pour comparé.

Dans l’espace libre, il vas falloir crée trois partition distincte, le Root (/), le Swap, et la Home (/home), pour cela faite un clic droit sur l’espace libre et cliqué sur « Ajouter… », une fois la fenêtre ouverte met dans point de montage un « / » et donne on fonction de l’espace souhaiter, puis refaire la même chose sauf que cette fois ici cliqué sur utilisé comme et allez chercher « espace d’échange (swap) » mettre l’espace nécessaire en fonction du tableur refaire encor une fois la manipulation, et mettre « /home » dans le point de montage.

C’est bon, vous venez de terminé la partie la plus compliqué » de l’installation de Ubuntu sur votre ordinateur, si tout c' »est bien passé vos partition devrai ressemblé à cela :

Et il ne vous reste plus continuer après les avertissement, choisir son fuseaux horaire, complété sont profile, et attendre la fin de l’installation de Ubuntu, une fois terminé, il est demander redémarré l’ordinateur et l’ors du redémarrage, quand il l’ai demander, retiré la clé USB et appuyer sur ENTER.

Choisir si l’ont démarre sur Windows ou sur Ubuntu :

Maintenant que vous avec Ubuntu sur votre ordinateur, vous souhaiter certainement retourné sur Windows pour s’assuré que tout c’est bien passé, pour cela redémarré l’ordinateur, et attendez d’arriver sur le Grub, une fois dessus avec les flèches directionnelle sélectionner « *Windows Boot Manager (on/dev/sdb1) » pour démarré sur Windows.

Merci d’avoir suivit ce tutoriel, j’espère qu’il vous aura aidez et qu’il vous aura permit de vous introduire un monde de Linux. Sur ceux que vous souhaite une bonne découverte !!!

Art

Perspective : un paysage Synthwave

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

Origines de la Synthwave

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

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

Le Projet

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

Structure du script

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

Analyse du script

Nous allons donc analyser le script.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Télécharger le .py

L’image finale