images bannieres

Mathgames

Cours de mathématiques pour la programmation de jeux vidéo

Programmation

Plan de la page programmation

  1. Première étape : analyse simplifié du programme « Prototype ».
  2. Deuxième étape : analyse explicite du programme « Prototype ».
  3. Fichier qui contiendra les variables globales ainsi que les 16 méthodes.
  4. Fichier qui contiendra la classe Aircaft.
  5. Fichier qui contiendra la classe Bullet.
  6. Fichier qui contiendra la classe Formes.
  7. Fichier qui contiendra la classe Polaire_Enemy.
  8. Fichier qui contiendra la classe Scrolling.

Si vous êtes arrivé jusqu'ici en suivant le fil, c'est que vous avez suivi dans l'ordre les différents cours sur la trigonométrie, les vecteurs et l'analyse, ce n'était pas si dur que cela finalement et vous aurez appris quelque combine avec savoir pour la suite de votre jeu vidéo, c'est-à-dire savoir calculer des différents angles et distances, savoir situer dans un plan et savoir calculer avec notre dérivée pour avoir des mouvements réalistes de nos séries d'avions qui visent vers notre avion mère en utilisant notre boîte à outils des mathématiques. Nous pouvons donc poursuivre et développer votre programme en partant d'une petite base théorique, mais ce n'est pas encore fini, il vous faudra de la patiente pour assimiler le cours sur la programmation avec Processing.

Tout d'abord, avant de continuer et de vous commenter avec le plus de détail possible le code source de votre jeu vidéo que l'on va programmer ensemble, je vais vous rediriger vers le site de FLOSS MANUALS qui détaille bien mieux que moi l'environnement de Processing avec précision. N'hésitez pas à visiter les liens du site dans l'ordre si vous êtes novice en programmation ou si vous vous s'enter familier avec un langage de programmation quelconque que vous avez déjà appris ou survolé par le passé. Les langages de programmation se ressemblent tous, c'est juste la syntaxe qui change d'un langage à l'autre.

Quand vous vous sentirez à l'aise après avoir passé un peu de temps sur le site de FLOOS MANUALS, je vous détaillerai avec le plus de précision possible les différents algorithmes de votre jeu vidéo.

Suivez le lien pour le cours de programmation avec Processing: FLOSS MANUALS.


Si vous avez suivi le tutoriel de Processing de FLOOS MANUALS, vous avez peut-être téléchargé Processing et vous avez fait quelques exemples de code pour voir ce que cela donne. Alors maintenant, je me dis que vous êtes opérationnel pour ouvrir, sauvegarder et taper du code dans Processing. Nous allons y aller tranquillement pour programmer votre jeu vidéo que vous appellerez comme vous voudrez quand vous enregistrerez votre premier projet dans Processing, pour l'instant, moi, je l'ai appelé Prototype.

Note : notre objectif sera de programmé un jeu vidéo simple où il y aura un avion mère qui vise sur plusieurs séries d'avions avec tir de munitions et animation de collision. Cela ressemblera à la vidéo ci-dessous une fois finie. Vous pouvez télécharger une archive du programme « ici » pour les systèmes Linux et Windows, pour la version Mac OS X, la version Linux devrait être compatible car ces deux derniers systèmes son programmé sur un même noyau système commun qui se nomme Unix.


Prototype par himalaya2004 (2017)


Mais tout d'abord je vous laisse en premier lieu télécharger toutes les images (sprites) du jeu vidéo qui sont dans un dossier nommé data. « Écoutez bien maintenant », une fois que vous aurez téléchargé le dossier data, placer le dans le dossier du projet que vous aurez créé à l'instant avec Processing. Je vous rappelle pour créer un projet dans Processing, ouvrer Processing sur votre bureau et faite « enregistrer sous » en lui donnant un nom de projet, moi j'ai appellé le projet Prototype. C'est très important sinon vous aurez des messages d'erreur dans votre IDE* quand vous exécuterez votre programme. Les messages d'erreurs s'afficheront dans la fenêtre de console de sortie en bas de Processing et il faudra les corriger.

Note : je vous rappelle qu'IDE* veut dire environnement de développement integré, alors maintenant, je dirais soit Processing ou IDE qui veulent dire la même chose.

Lien de téléchargement du dossier data contenant toutes les images de votre jeu vidéo: data.

Note : le dossier data et sous forme compresser, il vous faudra Winrar, Winzip ou 7-Zips pour le décompresser ensuite, une fois décompresser, ouvrer le dossier à la racine et prenez le dossier qui est à l'intérieur, c'est celui-là que vous devrez mettre dans le dossier du projet que vous venez de créer dans Processing. C'est dû à la compression qu'il y a deux dossiers du même nom, c'est le deuxième en dessous qu'il faut prendre, les images et actifs du jeu sont justes en dessous de ce dossier.



Première étape : analyse simplifiée du programme « Prototype »

Tout d'abord, nous allons analyser le programme complet de votre jeu vidéo qui contient nos variables globales* de différents types au début, ensuite on a nos 16 méthodes* qui suivent et pour la fin du programme, on a nos 5 classes* orientées objets.

Les commentaires commençant par les barres obliques ne comptent pas dans le code, je vous énumère d'abord les déclarations des variables globales telles qu'elles sont dans le programme du jeu Prototype ci-dessous, ensuite viendra les 16 méthodes suivi des 5 classes pour finir le programme.

Note : en programmation informatique, une variable globale* est une variable déclarée à l'extérieur du corps de toute méthode, fonction ou classe, et pouvant donc être utilisée n'importe où dans le programme. On parle également de variable de portée globale.

Voici la liste de nos variables globales de 10 types différents du programme Prototype :
PImage, PImage[ ], PFont , boolean, int, int[ ], float, objet de classe, ArrayList et PVector :

/************************************************* Autheur de ce programme : himalaya2004 Programmation : Prototype Date le 09/11/2017 Programmation Java dans IDE Processing *************************************************/ // On définit toutes nos variables globales avant la méthode setup() PImage decor_1; // Stocke notre image décor_1 (fonds mer) PImage decor_2; // Stocke notre image décor_2 (fonds mer) PImage img_avion_mere; // Stocke notre image img_avion_mere PImage img_avion_vies; // Stocke notre image img_avion_vies PImage img_tir ; // Stocke notre image img_tir PImage img_avion_enemy; // Stocke notre image avion_enemy; PImage img_balle; // Stocke image balle des enemy PImage img_dead; // Stocke image dead (fin de partie) PFont fontA; // Stocke notre fonte (police de caractère) boolean scrolling = true; // Boolean prend soit vrai (true) soit faux (false) boolean pause = true; // Boolean à true pause ou reprise du jeu int vies = 5; // Stocke les vies du joueur int score; // Stocke le score du jeu int mem_time = 0; // Stocke variable mem_time pour tempo du tir float tempo_tir = 0; // Stocke tempo_tir pour munitions int ecart; // Différence espace entre avions ennemis et avion mère int diff; // Difference espace entre munitions ennemis et avion mère int speed_Aircraft, direction_D_G; // Vitesse et direction de l'Aircraft (avion mère) // Variables objets de type classe Scrolling Scrolling; // Objet de classe Scrolling Aircraft Aircraft; // Objet de classe Aircraft Bullet Bullet; // Objet de classe Bullet // Liste tableaux ArrayList dynamique // enemy (Nombre d'avions ennemis par trajectoires) // bullets (Tir de munitions de l'avion mère) // pole (Tir de munitions des avions ennemis) ArrayList <Formes> enemy; // Où nos avions ennemis seront stockés par trajectoire ArrayList <Bullet> bullets; // Où nos munitions seront stockées ArrayList <Polaire_Enemy> pole; // Où nos munitions des avions ennemis seront stockées Formes fx; // Variable objet de classe Formes (fx) // Animation feu avion mère et avions ennemis int numFrames_enemy = 7; // Nombre d'images pour l'animation int numFrames_aircraft = 7; // Nombre d'images pour l'animation PImage[] images_feu_enemy = new PImage[numFrames_enemy]; PImage[] images_feu_aircraft = new PImage[numFrames_aircraft]; int nb_frames_anim_enemy = 0; int nb_frames_anim_aircraft = 0; int i_anim_enemy = 0; int i_anim_aircraft = 0; int tempo_anim_enemy = 50; int tempo_anim_aircraft = 50; boolean anim_feu_enemy = false; boolean anim_feu_aircraft = false; float x_anim_enemy, y_anim_enemy, x_anim_aircraft, y_anim_aircraft; int timing_launch_polaire, last; // Pour le game over (fin de partie) boolean game_over; // Fréquence vague d'enemy avec tempo millis int frequence_espace_entre_avion = 0; int compteur_avion = 0; int vague_figure; float nb_avions; // Nombre d'avions ennemis par trajectoire boolean fin_vague = true; // Tableaux vague_formes int[] vague_forme = { 0, 2, 1 }; // Ordre rangé des trajectoires dans tableau int no_vague; // 5 booleans qui prennent soit (true) ou (false) vrai ou faut soit 2 états boolean ri, le, up, dw, sp; // Pour touche clavière appuyée // Si toucher, l'avion mère disparaît avant de réapparaitre boolean toucher; // PVector v1 pour coordonnées cartésiennes v1.x, v1.y de l'avion mère PVector v1;


Note : une méthode* est un bloc qui contient une série d'instructions que l'on souhaite réutiliser. L'intérêt des méthodes réside dans la possibilité de réutiliser du code : nous aimerions écrire une seule fois une action tout en pouvant la répéter autant de fois que nécessaire. En englobant notre code dans une méthode, il devient possible d'appeler celle-ci à différents moments de notre programme. En fait une méthode ou une fonction signifie la même chose et joue le même rôle mais en emploi plus généralement le mot méthode lorsqu'elle est encapsulée dans une classe et fonction lorsqu'elle est à l'extérieur d'une classe. Ce qu'il faut savoir aussi, c'est que les méthodes ou fonctions peuvent admettre ou pas des arguments et peuvent rendre ou pas des valeurs de retour. Là je vous ai mis les 16 méthodes avec leurs corps vides, c'est-à-dire qu'il n'y a pas de code à l'intérieur de leurs corps qui commence après la déclaration de chaque méthode de la première accolade et fini à la dernière accolade, j'ai mis 5 points à la place pour simplifier la lecture de cette première étape.

Voici la liste de nos 16 méthodes du programme Prototype :


 
// Méthode setup() appelée une seule fois au lancement du programme void setup() { ..... } // Méthode draw() appelée sans arrêt en boucle au lancement du programme void draw() { ..... } // Méthode keyPressed() // Évènement si on presse sur une touche du clavier void keyPressed() { ..... } // Méthode keyReleased() // Évènement si on relâche une touche du clavier void keyReleased() { ..... } // Méthode mousePressed() // Évènement si on clique sur la souris // Lorsque que l'on clique sur la souris on recommence une partie void mousePressed() { ..... } // Méthode Action_Aircraft() de l'avion mère void action_Aircraft() { ..... } // Méthode vies() void vies() { ..... } // Méthode score() void score() { ..... } // Méthode titre() void titre() { ..... } // Méthode bordure() void bordure() { ..... } // Méthode game_Over() void game_Over() { ..... } // Méthode frequence_Vague() void frequence_Vague() { ..... } // Méthode tab_Formes() void tab_Formes() { ..... } // Méthode animation_Tir_Munitions() void animation_Tir_Munitions() { ..... } // Méthode animation_Feu_Aircraft(float x, float y) void animation_Feu_Aircraft( float x, float y ) { ..... } // Méthode animation_Feu_Enemy( float x, float y ) void animation_Feu_Enemy( float x, float y ) { ..... }


Nous avons vu nos 16 méthodes simplifiées avec leurs corps vides qui se trouvent entre la première accolade et finissant à la dernière accolade après la déclaration de chaque méthode, j'ai mis 5 points à la place pour simplifier la lecture pour cette première étape.

Note : en programmation orientée objet, une classe* déclare des propriétés communes à un ensemble d'objets. La classe déclare des attributs représentant l'état des objets et des méthodes représentant leur comportement. Une classe représente donc une catégorie d'objets. Elle apparaît aussi comme un moule ou une usine à partir de laquelle il est possible de créer des objets. (c'est en quelque sorte une « boîte à outils » qui permet de fabriquer un objet). On parle alors d'un objet en tant qu'instance d'une classe (création d'un objet ayant les propriétés de la classe).

Voici la liste de nos 5 classes du programme Prototype :


//******************************************************************** //** //** Classe Aircraft, déplacement et collision Aircraft (avion mère) //** //******************************************************************** class Aircraft { ..... } //******************************************************************** //** //** Classe Bullet, animation tir munitions de l'Aircraft (avion mère) //** //******************************************************************** class Bullet { ..... } //************************************************************** //** //** Classe Formes, déplacement trajectoire des avions ennemis //** //************************************************************** class Formes { ..... } //********************************************************************************* //** //** Classe Polaire_enemy, tir des munitions des avions ennemis vers l'avion mère //** //********************************************************************************* class Polaire_Enemy { ..... } //******************************************** //** //** Classe Srolling, défilement décor Océan //** //******************************************** class Scrolling { ..... }


Nous avons vu nos 5 classes simplifiées avec leurs corps vides qui se trouvent entre la première accolade et finissant à la dernière accolade après la déclaration de chaque classe. j'ai mis 5 points à la place pour simplifier la lecture pour cette première étape. Toute classe a des variables membres pour les déclarations de variables de tous types différents, à un constructeur ou plusieurs constructeurs portant le même nom que la classe elle-même et à des méthodes de classe au minimum en général, avec ses ingrédients nous pouvons alors construire des objets de type classe et une fois que notre classe est prête, nous pouvons instancié* notre classe pour lui faire exécuter son rôle qu'elle doit jouer dans le programme.

Note : en programmation orientée objet, on appelle instance d'une classe, un objet avec un comportement et un état, tous deux définis par la classe. Il s'agit donc d'un objet constituant un exemplaire de la classe. Dans ce contexte, instance est un anglicisme, qui signifie « cas », « exemple ». L'instanciation est l'action d'instancier, de créer un objet à partir d'un modèle. Elle est réalisée par la composition de deux opérations : l'allocation et l'initialisation. L'allocation consiste à réserver un espace mémoire au nouvel objet. L'initialisation consiste à fixer l'état du nouvel objet. Cette opération fait par exemple appel à l'un des constructeurs de la classe de l'objet à créer. La modification de ces opérations permet de réaliser la réflexion structurelle.

En programmation orientée classe, l'instanciation est la création d'un objet à partir d'une classe.



Deuxième étape : analyse explicite du programme « Prototype »

Nous allons voir dans cette deuxième étape l'analyse du code complet du programme Prototype en plus précis. Tout d'abord voici le code source du programme complet en un seul fichier ci-dessous, regarder le bien du début jusqu'à la fin, ça commence par les déclarations de nos variables globales du programme, ensuite viennent nos 16 méthodes et pour la fin, on termine le programme avec nos 5 classes qui suivent jusqu'à la fin du programme.

Voici le code complet en un seul fichier :

/************************************************* Autheur de ce programme : himalaya2004 Programmation : Prototype Date le 09/11/2017 Programmation Java dans IDE Processing *************************************************/ // On définit toutes nos variables globales avant la méthode setup() PImage decor_1; // Stocke notre image décor_1 (fonds mer) PImage decor_2; // Stocke notre image décor_2 (fonds mer) PImage img_avion_mere; // Stocke notre image img_avion_mere PImage img_avion_vies; // Stocke notre image img_avion_vies PImage img_tir ; // Stocke notre image img_tir PImage img_avion_enemy; // Stocke notre image avion_enemy; PImage img_balle; // Stocke image balle des enemy PImage img_dead; // Stocke image dead (fin de partie) PFont fontA; // Stocke notre fonte (police de caractère) boolean scrolling = true; // Boolean prend soit vrai (true) soit faux (false) boolean pause = true; // Boolean à true pause ou reprise du jeu int vies = 5; // Stocke les vies du joueur int score; // Stocke le score du jeu int mem_time = 0; // Stocke variable mem_time pour tempo du tir float tempo_tir = 0; // Stocke tempo_tir pour munitions int ecart; // Différence espace entre avions ennemis et avion mère int diff; // Difference espace entre munitions ennemis et avion mère int speed_Aircraft, direction_D_G; // Vitesse et direction de l'Aircraft (avion mère) // Variables objets de type classe Scrolling Scrolling; // Objet Scrolling Aircraft Aircraft; // Objet Aircraft Bullet Bullet; // Objet Bullet // Liste tableaux ArrayList dynamique // enemy (Nombre d'avions ennemis par trajectoires) // bullets (Tir de munitions de l'avion mère) // pole (Tir de munitions des avions ennemis) ArrayList <Formes> enemy; // Où nos avions ennemis seront stockés par trajectoire ArrayList <Bullet> bullets; // Où nos munitions seront stockées ArrayList <Polaire_Enemy> pole; // Où nos munitions des avions ennemis seront stockées Formes fx; // Variable objet de classe Formes (fx) // Animation feu avion mère et avions ennemis int numFrames_enemy = 7; // Nombre d'images pour l'animation int numFrames_aircraft = 7; // Nombre d'images pour l'animation PImage[] images_feu_enemy = new PImage[numFrames_enemy]; PImage[] images_feu_aircraft = new PImage[numFrames_aircraft]; int nb_frames_anim_enemy = 0; int nb_frames_anim_aircraft = 0; int i_anim_enemy = 0; int i_anim_aircraft = 0; int tempo_anim_enemy = 50; int tempo_anim_aircraft = 50; boolean anim_feu_enemy = false; boolean anim_feu_aircraft = false; float x_anim_enemy, y_anim_enemy, x_anim_aircraft, y_anim_aircraft; int timing_launch_polaire, last; // Pour le game over (fin de partie) boolean game_over; // Fréquence vague d'enemy avec tempo millis int frequence_espace_entre_avion = 0; int compteur_avion = 0; int vague_figure; float nb_avions; // Nombre d'avions ennemis par trajectoire boolean fin_vague = true; // Tableaux formes int[] vague_forme = { 0, 2, 1 }; // Ordre rangé des trajectoires dans tableau int no_vague; // 5 booleans qui prennent soit (true) ou (false) vrai ou faut soit 2 états boolean ri, le, up, dw, sp; // Pour touche claviere appuyée // Si toucher, l'avion mère disparaît avant de réapparaitre boolean toucher; // PVector v1 pour coordonnées cartésiennes v1.x, v1.y de l'Aircraft PVector v1; // Méthode setup() appelée une seule fois au lancement du programme void setup() { // Taille de la fenêtre 600 par 800 pixels size(600, 800); v1 = new PVector(0,0); // PVector coordonnées cartésiennes x, y de l'Aircraft // On instancie toutes les classes Scrolling = new Scrolling(); Bullet = new Bullet(0, 0); Aircraft = new Aircraft(width/2, height/2 + 300); // On charge toutes les images img_avion_mere = loadImage("avion_mere.png"); img_avion_vies = loadImage("avion_vies.png"); fontA = loadFont("EthnocentricRg-Regular-48.vlw"); img_tir = loadImage("tir.png"); img_balle = loadImage("balle_fire.png"); img_avion_enemy = loadImage("enemy.png"); img_dead = loadImage("dead.png"); // Avions ennemis des trajectoires dans tableau dynamique enemy = new ArrayList(); // Tir des munitions de l'avion mère dans tableau dynamique bullets = new ArrayList(); // Tir des munitions des avions ennemis dans tableau dynamique pole = new ArrayList(); ecart = img_avion_enemy.width/2 + img_tir.width/2; // Écartement diff = 25; // Différence toucher = false; images_feu_enemy[0] = loadImage("feu_1.png"); images_feu_enemy[1] = loadImage("feu_2.png"); images_feu_enemy[2] = loadImage("feu_3.png"); images_feu_enemy[3] = loadImage("feu_4.png"); images_feu_enemy[4] = loadImage("feu_5.png"); images_feu_enemy[5] = loadImage("feu_6.png"); images_feu_enemy[6] = loadImage("feu_7.png"); images_feu_aircraft[0] = loadImage("fire_1.png"); images_feu_aircraft[1] = loadImage("fire_2.png"); images_feu_aircraft[2] = loadImage("fire_3.png"); images_feu_aircraft[3] = loadImage("fire_4.png"); images_feu_aircraft[4] = loadImage("fire_5.png"); images_feu_aircraft[5] = loadImage("fire_6.png"); images_feu_aircraft[6] = loadImage("fire_7.png"); game_over = false; // Boolean pour fin de partie ri = false; // Boolean pour right le = false; // Boolean pour left up = false; // Boolean pour haut dw = false; // Boolean pour bas sp = false; // Boolean pour tir de munitions direction_D_G = 0; // Direction droite ou gauche (avion mère) speed_Aircraft = 2; // Vitesse avion mère // Tirage aléatoire 5 à 7 avions ennemis par trajectoire nb_avions = int(random( 5, 8 )); } // Méthode draw() appelée sans arrêt en boucle au lancement du programme void draw() { Scrolling.scrolling(); // Lance la méthode scrolling() de la classe Scrolling Scrolling.display(); // Lance la méthode display() de la classe Scrolling if (!game_over) { Aircraft.display(); // Lance la méthode display() de la classe Aircraft Aircraft.collision(); // Lance la méthode collision de la classe Aircraft action_Aircraft(); // Lance la méthode action_Aircraft() } bordure(); // Lance la méthode bordure() vies(); // Lance la méthode vies() score(); // Lance la méthode score() titre(); // Lance la méthode titre() animation_Tir_Munitions(); // Lance la méthode animation_Tir_Munitions() if (tempo_tir + 2000 <= millis()) { for (int j = 0; j < enemy.size (); j++) { Polaire_Enemy pl = new Polaire_Enemy(); pole.add(pl); } tempo_tir = millis(); } // Polaire_enemy for ( int k = pole.size () - 1; k >= 0; k-- ) { Polaire_Enemy fx = (Polaire_Enemy) pole.get( k ); fx.move_bullets(); fx.display_bullets(); fx.test_vide_tab_Polaire_enemy(); fx.collision(); } // Frequence vague successif avec frameCount frequence_Vague(); // Lance la méthode fréquence_vagues() // Méthode tab_Formes tab_Formes(); // Lance la méthode tab_Formes() // Méthode Animation_Feu_Enemy if ( anim_feu_enemy ) { animation_Feu_Enemy( x_anim_enemy, y_anim_enemy ); } if (!game_over) { // Méthode Animation_Feu_Aircraft if ( anim_feu_aircraft ) { animation_Feu_Aircraft( x_anim_aircraft, y_anim_aircraft ); } if (millis() - last> timing_launch_polaire) { last = millis(); toucher = false; } } game_Over(); // Lance la méthode game_Over() } // Méthode keyPressed() // Évènemment si on presse sur une touche du clavier void keyPressed() { // Si on presse la touche d ou D // on enclenche le tir de munitions de l'avion mère if (key == 'd' || key == 'D') { sp = true; } // Si on presse la touche p ou P // on fait une pause dans le jeu if (( key == 'p' ) || ( key == 'P' )) { pause =! pause; noLoop(); if (pause == false) loop(); } if (key == CODED) { // On appuie sur la flèche du haut if (keyCode == UP) { up = true; } else // On appuie sur la flèche du bas if (keyCode == DOWN) { dw = true; } else // On appuie sur la flèche de gauche if (keyCode == LEFT) { le = true; } else // On appuie sur la flèche de droite if (keyCode == RIGHT) { ri = true; } } } // Méthode keyReleased() // Évènemment si on relâche une touche du clavier void keyReleased() { if (key == 'd' || key == 'D') { sp = false; } if (key == CODED) { if (keyCode == UP) { up = false; } else if (keyCode == DOWN) { dw = false; } else if (keyCode == LEFT) { le = false; direction_D_G = 0; } else if (keyCode == RIGHT) { ri = false; direction_D_G = 0; } } } // Évènement si on clique sur la souris // Lorsque l'on clique sur la souris, on recommence une partie void mousePressed() { if (mouseX > 90 && mouseX < 523 && mouseY > 425 && mouseY < 455) { game_over = false; vies = 5; score = 0; // Tirage aléatoire 5 à 7 avions ennemis par trajectoire nb_avions = int(random( 5, 8 )); } } // Méthode Action_Aircraft() de l'avion mere void action_Aircraft() { // La touche flèche droite est appuyée alors // lance la méthode move_Aircraft_D_G(2) // avec 1 argument passé de la classe Aircraft if (ri == true) { // Direction droite pour facteur (2)----- Aircraft.move_Aircraft_D_G(2); } // La touche flèche gauche est appuyée alors // lance la méthode move_Aircraft_D_G(-2) // avec 1 argument passé de la classe Aircraft if (le == true) { // Direction gauche pour facteur (-2)----- Aircraft.move_Aircraft_D_G(-2); } // La touche flèche haut est appuyée alors // lance la méthode move_Aircraft_D_G(-2) // avec 1 argument passé de la classe Aircraft if (up == true) { // Direction haut pour facteur (-2)----- Aircraft.move_Aircraft_H_B(-2); } // La touche flèche bas est appuyée alors // lance la méthode move_Aircraft_D_G(2) // avec 1 argument passé de la classe Aircraft if (dw == true) { // Direction bas pour facteur (2)----- Aircraft.move_Aircraft_H_B(2); } // La touche d ou D pour le tir de munitions // de l'avion mère est appuyée if (sp == true) { // On teste la temporisation du tir de munitions de l'avion mère à répétition if (millis() - mem_time >= 125) { // On instancie le tableau dynamique Bullet avec la variable nb_balles Bullet nb_balles = new Bullet( v1.x + 1, v1.y ); // On remplit les munitions (nb_balles) à l'intérieur du tableau dynamique bullets bullets.add(nb_balles); // On remet la variable temporisation (mem_time) à jour mem_time = millis(); } } } // Méthode vies() void vies() { fill(255); // Couleur RVB pour le texte stroke(45, 203, 102); // Couleur RVB sur bordure des dessins image(img_avion_vies, 10, 9); // Affiche l'image img_avion_vies aux cordonnées 10, 9 textFont(fontA, 25); // Donne une taille à notre fonte (police de caractère) text(int(vies), 57, 34); // Affiche la variable vies aux coordonnées 57, 34 } // Méthode score() void score() { textFont(fontA, 20); // Taille de la fonte text("Score", 485, 23); // Affiche le texte score text(int(score), 484, 47); // Affiche la variable score } // Méthode titre() void titre() { fill(255); // Couleur RVB textFont(fontA, 24); // Taille de la fonte text("Prototype", 190, 32); // Affiche le titre } // Méthode bordure() void bordure() { rectMode(CENTER); // Centre les coordonnées au milieu de la bordure fill(255, 255, 255, 50); // Couleur RVB plus canal alpha rect(300, 25, width, height - 750); // Dessine la bordure en haut de la fenêtre rectMode(CORNER); // Remets le mode rectMode par défaut } // Méthode game_Over() void game_Over() { if (game_over) { fill(255); textFont(fontA, 42); text("GAME OVER", width/2 - 170, height/2); textFont(fontA, 28); text("Rejouer une partie", width/2 - 205, height/2 + 50); image(img_dead, 43, 2); // Affiche l'icone dead (fin de partie) } } // Méthode frequence_Vague() void frequence_Vague() { if ( fin_vague == true) { if ( millis() - frequence_espace_entre_avion >= 700) { vague_forme[no_vague] = vague_forme[no_vague]; vague_figure = vague_forme[no_vague]; Formes fx = new Formes(); enemy.add(fx); frequence_espace_entre_avion = millis(); compteur_avion++; } if (compteur_avion >= nb_avions) { compteur_avion = 0; fin_vague = false; } } } // Méthode tab_Formes() void tab_Formes() { for ( int i = enemy.size () - 1; i >= 0; i-- ) { fx = (Formes) enemy.get( i ); fx.move_fx(i); fx.display_fx(); } } // Méthode animation_Tir_Munitions() void animation_Tir_Munitions() { // On parcourt le tableau dynamique <Bullet> bullets for ( int i = bullets.size () - 1; i >= 0; i-- ) { // on obtient les munitions du tableau bullets : bullets.get( i ) Bullet o = (Bullet) bullets.get( i ); o.move(); // On lance la méthode move() de Bullet o.display(); // On lance la méthode display de Bullet // Teste la coordonnée cartésienne y des munitions de l'avion mère // si ( o.y < 71 ) en haut de l'ecran if ( o.y < 71 ) { bullets.remove( i ); // Vide le tableau bullets pour ne pas avoir des fuites mémoire } else { for ( int j=0; j< enemy.size (); j++ ) { if (round( o.x ) - round( enemy.get(j).v2.x + enemy.get(j).coord_x ) <= ecart && round( o.x ) - round( enemy.get(j).v2.x + enemy.get(j).coord_x ) >= -ecart && round( o.y ) - round( enemy.get(j).v2.y + enemy.get(j).coord_y ) <= ecart && round( o.y ) - round( enemy.get(j).v2.y + enemy.get(j).coord_y ) >= -ecart ) { x_anim_enemy = round( enemy.get(j).v2.x + enemy.get(j).coord_x ); y_anim_enemy = round( enemy.get(j).v2.y + enemy.get(j).coord_y ); i_anim_enemy = 0; nb_frames_anim_enemy = millis(); anim_feu_enemy = true; if (!game_over) { score += 25 + random(0, 25); } if ( score >= 99999 ) score = 99999; enemy.remove(j); bullets.remove(i); if ( enemy.size() == 0 ) { fin_vague = true; no_vague ++; //nb_avions++; if (no_vague == vague_forme.length) { // fin du niveau no_vague = 0; } } } } } } } // Méthode animation_Feu_Aircraft( float x, float y ) void animation_Feu_Aircraft(float x, float y) { if ( millis() <= ( nb_frames_anim_aircraft + tempo_anim_aircraft )) { imageMode( CENTER ); image( images_feu_aircraft[i_anim_aircraft], x, y ); imageMode( CORNER ); } if ( millis() == nb_frames_anim_aircraft + tempo_anim_aircraft ) { nb_frames_anim_aircraft += tempo_anim_aircraft; i_anim_aircraft++; if ( i_anim_aircraft == 7 ) { i_anim_aircraft = 0; anim_feu_aircraft = false; } } } // Méthode animation_Feu_Enemy( float x, float y ) void animation_Feu_Enemy( float x, float y ) { if ( millis() <= ( nb_frames_anim_enemy + tempo_anim_enemy )) { imageMode( CENTER ); image( images_feu_enemy[i_anim_enemy], x, y ); imageMode( CORNER ); } if ( millis() == nb_frames_anim_enemy + tempo_anim_enemy ) { nb_frames_anim_enemy += tempo_anim_enemy; i_anim_enemy++; if ( i_anim_enemy == 7 ) { i_anim_enemy = 0; anim_feu_enemy = false; } } } //******************************************************************** //** //** Classe Aircraft, déplacement et collision Aircraft (avion mère) //** //******************************************************************** class Aircraft { // Variables membres de l'objet Aircraft // vide //--------------------------------------------------------- //-- Constructeur Aircraft(int x_Aircraft, int y_Aircraft) //-- qui passe 2 arguments //-- entre parenthèses x_Aircraft et y_Aircraft //--------------------------------------------------------- Aircraft(int x_Aircraft, int y_Aircraft) { v1.x = x_Aircraft; v1.y = y_Aircraft; } // Méthode display (affichage de l'avion mère) void display() { // Centre les coordonnées cartésiennes du repère au milieu de l'image imageMode(CENTER); image(img_avion_mere, v1.x, v1.y); // Remets le mode imagetMode par défaut imageMode(CORNER); } // Méthode move_Aircraft_D_G(int facteur_direction) // avec facteur_direction passé en argument // l'avion mère va à droite ou à gauche void move_Aircraft_D_G(int facteur_direction) { direction_D_G = facteur_direction; v1.x = v1.x + facteur_direction * speed_Aircraft; // Teste de sortie d'écran à droite if (v1.x < 30) v1.x = 30; // Test de sortie d'écran à gauche else if (v1.x > width - 30) v1.x = width - 30; } // Méthode move_Aircraft_H_B(int facteur_direction) // avec facteur_direction passé en argument // l'avion mère va en haut ou en bas void move_Aircraft_H_B(int facteur_direction) { v1.y = v1.y + facteur_direction * speed_Aircraft; // Test de sortie d'écran en haut if (v1.y < 71) v1.y = 71; // Test de sortie d'écran en bas else if (v1.y > height - 22) v1.y = height - 22; } void collision() { for ( int j=0; j < enemy.size (); j++ ) { if (round(v1.x)-round(enemy.get(j).v2.x+enemy.get(j).coord_x) <= ecart && round(v1.x)-round(enemy.get(j).v2.x+enemy.get(j).coord_x) >= -ecart && round(v1.y)-round(enemy.get(j).v2.y+enemy.get(j).coord_y) <= ecart && round(v1.y)-round(enemy.get(j).v2.y+enemy.get(j).coord_y) >= -ecart) { toucher = true; // L'avion mère réapparaît au bout de 500 millisecondes après avoir été toucher. timing_launch_polaire = 500; // Recentre l'avion mère aux coordonnées cartésiennes largeur/2 et hauteur/2 + 300. v1.x = width/2; v1.y = height/2 + 300; x_anim_aircraft = round( enemy.get(j).v2.x + enemy.get(j).coord_x ); y_anim_aircraft = round( enemy.get(j).v2.y + enemy.get(j).coord_y ); i_anim_aircraft = 0; nb_frames_anim_aircraft = millis(); anim_feu_aircraft = true; vies = vies - 1; if (vies < 0) { vies = 0; game_over = true; } } } } } //******************************************************************** //** //** Classe Bullet, animation tir munitions de l'Aircraft (avion mère) //** //******************************************************************** class Bullet { // Variables membres float x; // Coordonnées cartésiennes x des munitions de l'avion mère float y; // Coordonnées cartésiennes y des munitions de l'avion mère float nb; // Espacement entre les munitions de l'avion mère float speed; // Vitesse du tir //---------------------------------------------- //-- Constructeur Bullet( float tx, float ty ) //-- qui passe 2 arguments //-- entre parenthèses tx et ty //---------------------------------------------- Bullet( float tx, float ty ) { x = tx; // Coordonnées cartésiennes x des munitions de l'avion mère y = ty; // Coordonnées cartésiennes y des munitions de l'avion mère nb = 10; // Espacement entre les munitions de l'avion mère égale à nb } // Méthode display() void display() { // Centre les coordonnées cartésiennes du repère au milieu de l'image imageMode( CENTER ); // Affiche l'image des munitions aux coordonnées cartésiennes x, y image( img_tir, x, y ); imageMode( CORNER ); // Remet le mode imageMode par défaut } // Méthode move() void move() { y -= nb; // Déplacement des munitions sur les y - nb } } //************************************************************** //** //** Classe Formes, déplacement trajectoire des avions ennemis //** //************************************************************** class Formes { // PVector v2 pour coordonnées cartésiennes v2.x et v2.y des avions ennemis; PVector v2 = new PVector(0,0); float offset, coef, pile_face, fact_pos_neg, ecart; float coef_dir= -0.01; float facteur, coord_x, coord_y; float x_tireur, y_tireur, x_cible, y_cible; float x_bullet, y_bullet; float x_copy, y_copy; float vite = 1.7; //--------------------------- //-- Constructeur Forme() //-- sans passage d'argument //--------------------------- Formes() { switch( vague_figure ) { //-- Forme croisée case 0: { offset = int(random( -400, 400 )); coef = 1.7; pile_face = int(random( 1, 11 )); if ( pile_face <= 5 ) { v2.x = 0 - 50; fact_pos_neg = 1; ecart = 0; } else { v2.x = width + 50 ; ecart = width; fact_pos_neg = -1; } x_cible = v1.x; y_cible = v1.y; coord_x = 0; coord_y = 0; } break; //-- Forme square top 1 left -> right case 1: { v2.x = -width/2; facteur = 1; // int(random( 1, 6 )); offset = 0; // int(random( 0, 351)); coord_x = width/2; coord_y = height/2; } break; //-- Forme square aleatoire -> left case 2: { v2.x = -width/2; coef += random(-0.008, 0.005); coord_x = width/2; coord_y = height/2; } break; default : { v2.x = 300 + int( random( -250, 250 )); coord_x = 0; coord_y = 0; } break; } } //------------------------ //-- Méthodes move_fx --- //------------------------ void move_fx( int i ) { switch( vague_figure ) { //-- Forme croisée case 0: { v2.y = (fact_pos_neg * ( coef * int( v2.x - ecart ))) - offset; v2.x += fact_pos_neg * vite; } if ( v2.y > height ) { enemy.remove( i ); } break; //-- Forme square top 1 left -> right case 1: { v2.y = round( coef_dir * sq( v2.x ) / facteur + offset ); v2.x += vite * sqrt( facteur ); } if ( v2.x > width/2 ) { enemy.remove( i ); } break; //--Forme square aleatoire ->left case 2: { v2.y =- coef * sq( v2.x ); v2.x += vite + 1.5 ; } if ( v2.x > width/2 ) { enemy.remove( i ); } break; default : { v2.x += 0; v2.y += 3.5; if ( v2.y > height ) { enemy.remove( i ); } } break; } if ( enemy.size() == 0 ) { fin_vague = true; no_vague ++; if (no_vague == vague_forme.length) { // fin du niveau no_vague = 0; } } } //-------------------------- //-- Méthodes display_fx //-------------------------- void display_fx() { imageMode( CORNER ); pushMatrix(); translate( v2.x + coord_x, v2.y + coord_y ); switch(vague_figure) { //-- Forme croisée case 0: { rotate(( - PI/2 + atan( v2.x * ( coef_dir * 2 / facteur ))) * 0 ); } break; //-- Forme square top 1 left -> right case 1: { rotate( - PI/2 + atan( v2.x * ( coef_dir * 2 / facteur ))); } break; //-- Forme square aleatoire -> left case 2: { rotate(- PI/2 + atan( -v2.x * 2 * coef )); } break; } image( img_avion_enemy, 0, 0 ); popMatrix(); imageMode( CORNER ); } float get_x_tireur(int i) { float x_tireur = enemy.get(i).v2.x; return x_tireur; } float get_y_tireur(int i) { float y_tireur = enemy.get(i).v2.y; return y_tireur; } float get_x_cible() { float x_cible = v1.x; return x_cible; } float get_y_cible() { float y_cible = v1.y; return y_cible; } float get_coord_x() { float COORD_X = coord_x; return COORD_X; } float get_coord_y() { float COORD_Y = coord_y; return COORD_Y; } } //********************************************************************************* //** //** Classe Polaire_Enemy, tir des munitions des avions ennemis vers l'avion mère //** //********************************************************************************* class Polaire_Enemy { float x_tireur, y_tireur, x_cible, y_cible, theta, r = 0, vitesse; float x_bullet, y_bullet, x_bullet_before, y_bullet_before, coord_x, coord_y; //--------------------------------- //-- Constructeur Polaire_enemy() //-- sans passage d'argument //--------------------------------- Polaire_Enemy() { int avion = int( random ( 0, enemy.size() )); fx = ( Formes ) enemy.get( avion ); x_tireur = fx.get_x_tireur( avion ); y_tireur = fx.get_y_tireur( avion ); coord_x = fx.get_coord_x(); coord_y = fx.get_coord_y(); x_cible = fx.get_x_cible() - coord_x; y_cible = fx.get_y_cible() - coord_y; } void move_bullets() { if ( r==0 ) { if (x_cible >= x_tireur) { theta = atan((y_cible-y_tireur) / (x_cible-x_tireur)); // Calcul angle de tir theta += random(-0.5, 0.5); vitesse = random(2, 5); } else { theta = atan((y_cible-y_tireur) / (x_cible-x_tireur)); // Calcul angle de tir theta += (random(-0.5, 0.5)); vitesse = -( random( 2, 5 )); } } // Coordonnées polaires des munitions des avions ennemis r += vitesse; x_bullet = cos(theta) * r + x_tireur + coord_x; y_bullet = sin(theta) * r + y_tireur + coord_y; } // Affichage des munitions des avions ennemis void display_bullets() { imageMode(CENTER); image(img_balle, x_bullet, y_bullet); imageMode(CORNER); } // Test de sortie d'écran des munitions des avions ennemis void test_vide_tab_Polaire_enemy() { for ( int i = 0; i < pole.size (); i++ ) { if (pole.get(i).x_bullet < 0 || pole.get(i).x_bullet > width || pole.get(i).y_bullet < 0 || pole.get(i).y_bullet > height) { pole.remove(i); } } } // Test de collision de l'avion mère et des munitions des avions ennemis void collision() { for (int i = 0; i < pole.size(); i++) { if (round( v1.x ) - round( pole.get(i).x_bullet ) <= diff && round( v1.x ) - round( pole.get(i).x_bullet ) >= -diff && round( v1.y ) - round( pole.get(i).y_bullet ) <= diff && round( v1.y ) - round( pole.get(i).y_bullet) >= -diff ) { toucher = true; // L'avion mère réapparaît au bout de 500 millisecondes après avoir été toucher. timing_launch_polaire = 500; // Recentre l'avion mère aux coordonnées largeur/2 et hauteur/2 + 300. v1.x = width/2; v1.y = height/2 + 300; x_anim_aircraft = round( pole.get(i).x_bullet); y_anim_aircraft = round( pole.get(i).y_bullet); i_anim_aircraft = 0; nb_frames_anim_aircraft = millis(); anim_feu_aircraft = true; vies = vies - 1; if (vies < 0) { vies = 0; game_over = true; } pole.remove(i); } } } } //******************************************** //** //** Classe Srolling, défilement décor Océan //** //******************************************** class Scrolling { // On définit les variables membres des 2 écrans // qui défilent simultanément (x, y1, y2) int x, y1, y2; //--------------------------- //-- Constructeur Srolling() //-- sans passage d'argument //--------------------------- Scrolling() { y1 = 0; // Hauteur écran 1 y2 = -850; // Hauteur écran 2 } // Méthode init scrolling() void init_scrolling() { // Condition si scrolling égale à true alors on exécute le code // en dessous entre accolades if (scrolling) { // Assigne image (fonds_mer) à décor_1 decor_1 = loadImage("fonds_mer_1.png"); // Assigne image tirée aléatoirement (fonds_mer), 1 sur 4 à décor_2 decor_2 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } } // Méthode scrolling void scrolling() { // Condition si scrolling égale true alors on exécute le code // en dessous entre accolades if (scrolling) { // Lance la méthode init_scrolling( ) de la classe Scrolling Scrolling.init_scrolling(); } scrolling = false; // On passe la variable boolean scrolling à false (faux) Scrolling.boucle(); // Lance méthode boucle( ) de la classe Scrolling } // Méthode display() void display() { image( decor_1, x, y1 ); // Affiche décor_1 aux coordonnées x, y1 image( decor_2, x, y2 ); // Affiche décor_2 aux coordonnées x, y2 } // Méthode boucle() void boucle() { y1++; // Variable y1++ le décor_1 défile if ( y1 > height + 50) { // On teste si y1 arrive en bas de l'écran + 50 y1 = -850; // On remet y1 à -850 pour refaire un nouveau défilement // On charge aléatoirement 1 sur 4 images pour l'assigner au décor_1 decor_1 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } y2++; // Variable y2++ le décor_2 défile if ( y2 > height + 50 ) { // On teste si y2 arrive en bas de l'écran + 50 y2 = -850; // On remet y2 à -850 pour refaire un nouveau défilement // On charge aléatoirement 1 sur 4 images pour l'assigner au décor_2 decor_2 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } } }


Vous avez plusieurs choix pour recopier le code source de ce programme complet ci-dessus dans votre projet, soit vous le recopiez en une seule fois ou soit vous le recopiez en plusieurs fichiers dans votre projet, cela fonctionnera de la même manière, mais en le recopiant en plusieurs fichiers se sera meilleur pour une question de lisibilité du code source du programme dans sa globalité. Si vous choisissez le deuxième choix, je vais vous expliquer comment faire avec les captures d'écran ci-dessous.

Note : je vous rappelle pour enregistrer un projet, ouvrez Processing, il s'ouvrira avec un nom de projet par défaut, ensuite enregistrez le projet ouvert avec un nouveau nom. Cette fois-ci le projet enregistré portera le nom que vous viendrez de lui donner.

Quand vous aurez enregistré votre nouveau projet, recopiez les déclarations des variables globales ainsi que les déclarations des méthodes qui suivent dans le même fichier courant, ce sera votre premier fichier, celui ouvert avec l'onglet de votre IDE où est nommé le projet en cours, ensuite recopiez les 5 classes restantes en 5 fichiers distincts rajouter au projet.

Au total vous aurez 6 fichiers dans votre projet.

le 1er  fichier contiendra les variables globales ainsi que les 16 méthodes.
le 2e   fichier contiendra la classe Aircraft.
le 3e   fichier contiendra la classe Bullet.
le 4e   fichier contiendra la classe Formes.
le 5e   fichier contiendra la classe Polaire_Enemy.
le 6e   fichier contiendra la classe Scrolling.

Tout d'abord pour enregistrer des nouveaux fichiers avec Processing, il faut cliquer sur la petite flèche qui pointe vers le bas sur la droite à côté du nom du projet, il y aura un menu déroulant qui s'affichera, ensuite cliquer sur nouvel onglet et entrer un nouveau nom de fichier. Regarder les captures d'écran ci-dessous.


processing

processing

processing

processing

Si vous avez fait ce que je vous ai dit, vous vous retrouverez avec votre projet à 6 fichiers. Regarder la capture d'écran ci-dessous.

processing



Variables globales et les 16 méthodes du programme

Au début de notre programme, nous avons nos variables globales de 10 types différents, je vais vous les expliquer très succinctement, nous avons les types de variables globales suivantes :

PImage : nous stockons nos images dans nos variables du type PImage.

PImage[ ] : nous stockons nos tableaux d'images dans nos variables du type PImage[ ].

PFont : nous stockons notre font de caractères dans notre variable du type PFont.

boolean : nous stockons nos valeurs à deux états dans nos variables du type boolean.

int : nous stockons nos valeurs entières dans nos variables du type int.

int[ ] : nous stockons notre tableau d'entier dans notre variable du type int[ ].

float : nous stockons nos valeurs réelles dans nos variables du type float.

Là ci-dessous nous avons 3 objets de type classe.
Scrolling Scrolling;      // Objet Scrolling
Aircraft Aircraft;           // Objet Aircraft
Bullet Bullet;                // Objet Bullet

ArrayList : nous stockons nos tableaux dynamiques dans nos variables du type ArrayList.

PVector : nous stockons les coordonnées cartésiennes v1.x, v1.y de l'avion mère de notre PVector définit à v1.

/************************************************* Autheur de ce programme : himalaya2004 Programmation : Prototype Date le 09/11/2017 Programmation Java dans IDE Processing *************************************************/ // On définit toutes nos variables globales avant la méthode setup() PImage decor_1; // Stocke notre image décor_1 (fonds mer) PImage decor_2; // Stocke notre image décor_2 (fonds mer) PImage img_avion_mere; // Stocke notre image img_avion_mere PImage img_avion_vies; // Stocke notre image img_avion_vies PImage img_tir ; // Stocke notre image img_tir PImage img_avion_enemy; // Stocke notre image avion_enemy; PImage img_balle; // Stocke image balle des enemy PImage img_dead; // Stocke image dead (fin de partie) PFont fontA; // Stocke notre fonte (police de caractère) boolean scrolling = true; // Boolean prend soit vrai (true) soit faux (false) boolean pause = true; // Boolean à true pause ou reprise du jeu int vies = 5; // Stocke les vies du joueur int score; // Stocke le score du jeu int mem_time = 0; // Stocke variable mem_time pour tempo du tir float tempo_tir = 0; // Stocke tempo_tir pour munitions int ecart; // Différence espace entre avions ennemis et avion mère int diff; // Difference espace entre munitions ennemis et avion mère int speed_Aircraft, direction_D_G; // Vitesse et direction de l'Aircraft (avion mère) // Variables objets de type classe Scrolling Scrolling; // Objet de classe Scrolling Aircraft Aircraft; // Objet de classe Aircraft Bullet Bullet; // Objet de classe Bullet // Liste tableaux ArrayList dynamique // enemy (Nombre d'avions ennemis par trajectoires) // bullets (Tir de munitions de l'avion mère) // pole (Tir de munitions des avions ennemis) ArrayList <Formes> enemy; // Où nos avions ennemis seront stockés par trajectoire ArrayList <Bullet> bullets; // Où nos munitions seront stockées ArrayList <Polaire_Enemy> pole; // Où nos munitions des avions ennemis seront stockées Formes fx; // Variable objet de classe Formes (fx) // Animation feu avion mère et avions ennemis int numFrames_enemy = 7; // Nombre d'images pour l'animation int numFrames_aircraft = 7; // Nombre d'images pour l'animation PImage[] images_feu_enemy = new PImage[numFrames_enemy]; PImage[] images_feu_aircraft = new PImage[numFrames_aircraft]; int nb_frames_anim_enemy = 0; int nb_frames_anim_aircraft = 0; int i_anim_enemy = 0; int i_anim_aircraft = 0; int tempo_anim_enemy = 50; int tempo_anim_aircraft = 50; boolean anim_feu_enemy = false; boolean anim_feu_aircraft = false; float x_anim_enemy, y_anim_enemy, x_anim_aircraft, y_anim_aircraft; int timing_launch_polaire, last; // Pour le game over (fin de partie) boolean game_over; // Fréquence vague d'enemy avec tempo millis int frequence_espace_entre_avion = 0; int compteur_avion = 0; int vague_figure; float nb_avions; // Nombre d'avions ennemis par trajectoire boolean fin_vague = true; // Tableaux vague_formes int[] vague_forme = { 0, 2, 1 }; // Ordre rangé des trajectoires dans tableau int no_vague; // 5 booleans qui prennent soit (true) ou (false) vrai ou faut soit 2 états boolean ri, le, up, dw, sp; // Pour touche clavière appuyée // Si toucher, l'avion mère disparaît avant de réapparaitre boolean toucher; // PVector v1 pour coordonnées cartésiennes v1.x, v1.y de l'avion mère PVector v1;

On continue, nous avons à la suite nos 16 méthodes dans le même fichier des variables globales. je vais vous les expliquer une par une, la 1re méthode est setup( ).

// Méthode setup() appelée une seule fois au lancement du programme void setup() { // Taille de la fenêtre 600 par 800 pixels size(600, 800); v1 = new PVector(0,0); // PVector coordonnées cartésiennes x, y de l'Aircraft // On instancie toutes les classes Scrolling = new Scrolling(); Bullet = new Bullet(0, 0); Aircraft = new Aircraft(width/2, height/2 + 300); // On charge toutes les images img_avion_mere = loadImage("avion_mere.png"); img_avion_vies = loadImage("avion_vies.png"); fontA = loadFont("EthnocentricRg-Regular-48.vlw"); img_tir = loadImage("tir.png"); img_balle = loadImage("balle_fire.png"); img_avion_enemy = loadImage("enemy.png"); img_dead = loadImage("dead.png"); // Avions ennemis des trajectoires dans tableau dynamique enemy = new ArrayList(); // Tir des munitions de l'avion mère dans tableau dynamique bullets = new ArrayList(); // Tir des munitions des avions ennemis dans tableau dynamique pole = new ArrayList(); ecart = img_avion_enemy.width/2 + img_tir.width/2; // Écartement diff = 25; // Différence toucher = false; images_feu_enemy[0] = loadImage("feu_1.png"); images_feu_enemy[1] = loadImage("feu_2.png"); images_feu_enemy[2] = loadImage("feu_3.png"); images_feu_enemy[3] = loadImage("feu_4.png"); images_feu_enemy[4] = loadImage("feu_5.png"); images_feu_enemy[5] = loadImage("feu_6.png"); images_feu_enemy[6] = loadImage("feu_7.png"); images_feu_aircraft[0] = loadImage("fire_1.png"); images_feu_aircraft[1] = loadImage("fire_2.png"); images_feu_aircraft[2] = loadImage("fire_3.png"); images_feu_aircraft[3] = loadImage("fire_4.png"); images_feu_aircraft[4] = loadImage("fire_5.png"); images_feu_aircraft[5] = loadImage("fire_6.png"); images_feu_aircraft[6] = loadImage("fire_7.png"); game_over = false; // Boolean pour fin de partie ri = false; // Boolean pour right le = false; // Boolean pour left up = false; // Boolean pour haut dw = false; // Boolean pour bas sp = false; // Boolean pour tir de munitions direction_D_G = 0; // Direction droite ou gauche (avion mère) speed_Aircraft = 2; // Vitesse avion mère // Tirage aléatoire 5 à 7 avions ennemis par trajectoire nb_avions = int(random( 5, 8 )); }


La méthode setup( ) initialise toutes les variables de tous types une seule fois au lancement du programme.

Comme vous voyez, on règle la taille de la fenêtre à 600 par 800 pixels, à la suite on instancie avec new la variable v1 que l'on a déclaré plus haut dans nos variables globales, c'est notre premier PVector du programme d'où la relation des vecteurs vus à la rubrique « vecteur », on a vu que les vecteurs servaient à se repérer dans un plan, ici notre avion mère se déplacera aux coordonnées cartésiennes PVector qui contient ses coordonnées v1.x et v1.y, on les utilisera plus loin dans nos méthodes et classes.

Ensuite, on instancie nos classes dont on a besoin tout de suite au lancement du programme, c'est-à-dire la classe Scrolling pour le défilement du décor mer, la classe Bullet pour le tir de munitions de notre avion mère et la classe Aircraft pour le déplacement dans toutes les directions de notre avion mère.

À la suite, nous chargeons nos images et la fonte de police pour la typographie du jeu, ensuite, on instancie nos 3 tableaux dynamiques, enemy pour les déplacements des avions ennemis, bullets pour le tir de munitions à répétition de notre avion mère et pole pour les munitions de nos avions ennemis qui visent vers notre avion mère.

On continue avec le chargement de nos images cette fois-ci dans 2 tableaux du type PImage[ ], on charge dans le premier tableau 7 images avec la variable image_feu_enemy[ ] et dans le second tableau 7 images avec la variable image feu aircraft[ ]. Cela servira pour nos animations de feu après collision.

Pour finir, on définit nos variables du type boolean et int qu'on a déclarées plus haut dans nos variables globales et on fait un tirage aléatoire du nombre d'avions ennemis au lancement du jeu, entre 5 et 7.

Voilà nous avons fini en gros pour notre méthode setup( ), passons à la 2e méthode draw( ) ci-dessous. À la différence de la méthode setup( ), la méthode draw( ) est appeler par le système sans arrêt au lancement du programme jusqu'à l'arrêt du programme.

// Méthode draw() appelée sans arrêt en boucle au lancement du programme void draw() { Scrolling.scrolling(); // Lance la méthode scrolling() de la classe Scrolling Scrolling.display(); // Lance la méthode display() de la classe Scrolling if (!game_over) { Aircraft.display(); // Lance la méthode display() de la classe Aircraft Aircraft.collision(); // Lance la méthode collision de la classe Aircraft action_Aircraft(); // Lance la méthode action_Aircraft() } bordure(); // Lance la méthode bordure() vies(); // Lance la méthode vies() score(); // Lance la méthode score() titre(); // Lance la méthode titre() animation_Tir_Munitions(); // Lance la méthode animation_Tir_Munitions() if (tempo_tir + 2000 <= millis()) { for (int j = 0; j < enemy.size (); j++) { Polaire_Enemy pl = new Polaire_Enemy(); pole.add(pl); } tempo_tir = millis(); } // Polaire_enemy for ( int k = pole.size () - 1; k >= 0; k-- ) { Polaire_Enemy fx = (Polaire_Enemy) pole.get( k ); fx.move_bullets(); fx.display_bullets(); fx.test_vide_tab_Polaire_enemy(); fx.collision(); } // Frequence vague successif avec frameCount frequence_Vague(); // Lance la méthode fréquence_vagues() // Méthode tab_Formes tab_Formes(); // Lance la méthode tab_Formes() // Méthode Animation_Feu_Enemy if ( anim_feu_enemy ) { animation_Feu_Enemy( x_anim_enemy, y_anim_enemy ); } if (!game_over) { // Méthode Animation_Feu_Aircraft if ( anim_feu_aircraft ) { animation_Feu_Aircraft( x_anim_aircraft, y_anim_aircraft ); } if (millis() - last> timing_launch_polaire) { last = millis(); toucher = false; } } game_Over(); // Lance la méthode game_Over() }


Ici, dans la méthode draw( ), nous lançons 2 méthodes de la classe Scrolling, une s'appelle scrolling( ) et l'autre s'appelle display( ), cela servira à faire défiler et afficher le décor mer.

Ensuite, nous lançons 2 méthodes de la classe Aircraft qui s'appelle display( ) et collision( ) avec une troisième méthode qui s'appelle action_Aircraft( ), cela servira à afficher, tester les collisions avec les avions ennemis et de déplacer l'avion mère lorsque l'on presse sur les touches du clavier.

Les 3 dernières méthodes sont dans le corps d'une condition if (!game_over), si la variable game_over est égale à la négation de false, c'est-à-dire true, les méthodes sont lancées sinon on passe la variable game_over à la négation de true, c'est-à-dire false alors les méthodes ne se lancent pas et c'est la fin de la partie.

On continue en lançant 4 méthodes, bordure( ), vies( ), score( ) et titre( ), cela servira à respectivement à afficher la bordure en haut de l'écran du jeu avec les vies et scores de l'avion mère ainsi que le titre du jeu « Prototype ».

Ensuite, on lance la méthode animation_Tir_Munitions( ) qui servira à afficher l'animation des munitions et collisions de notre avion mère avec les avions ennemis.

Ensuite, on a un if (tempo_tir + 2000 <= millis( )) qui teste une temporisation si toutes les 2 secondes qui correspondent à 2000 millisecondes lancent dans son corps une boucle for qui répète tant que la variable j ai plus petite que la taille du tableau dynamique enemy.size( ). Ce tableau-là a été déclaré plus haut dans les déclarations de variables globales, c'est ArrayList <Formes> enemy et à l'intérieur du corps de la boucle for, on instancie la classe polaire_Enemy( ) qui va construire ses objets, et en dernière ligne, on a pole.add( pl ) qui va les rajouter au tableau dynamique ArrayList <Polaire_Enemy> pole. Les munitions des avions ennemis seront des objets construits de la classe polaire_Enemy( ) et avant la fin de la boucle, on a tempo_tir = millis(); qui veut dire qu'on réinitialise la tempo qui est dans la condtion au dessus qui dure 2 secondes, cela servira à lancer l'animation des munitions des avions ennemis qui visent sur l'avion mère à fréquence régulière.

On continue avec une boucle for qui parcoure le tableau dynamique à l'envers ArrayList <Polaire_Enemy> pole qu'on a rempli précédemment, il contient les munitions des avions ennemis qu'on a vu juste au-dessus, et au fur et à mesure qu'il se vide on lance les méthodes de la classe polaire_Enemy( ), c'est-à-dire, le déplacement, l'affichage, les testes pour vider la mémoire du tableau dynamique ainsi que les testes de collisions de l'avion mère.

Ensuite on lance la méthode fréquence_vague( ) et tab_Formes( ) à la suite.

On continue avec les 2 méthodes que l'on lance pour les animations de collision après impact, ce sont les méthodes animation_Feu_Enemy( x_anim_enemy, y_anim_enemy ) et animation_Feu_Aircraft( x_anim_aircraft, y_anim_aircraft ) qui admette chacun des arguments entre parenthèses. Ces arguments sont respectivement les coordonnées cartésiennes pour les avions ennemis et l'avion mère, c'est à ces coordonnées catésiennes précises qu'il y aura l'animation de feu après collision. Ces méthodes sont à l'intérieur des corps des conditions if qui teste leur variable respectif anim_feu_enemy et anim_feu_aircraft qui si elles sont égales à true, alors on lance les méthodes des animations de feu après collision sinon si elles sont égales à false alors on ne lance pas les animations, car il n'y a pas de collision.

La derniere méthode suivante est game_Over( ), elle lance l'affichage du Game Over en fin de partie, vous pourrez rejouer une nouvelle partie ensuite.

On va continuer avec les 4 méthodes suivantes qui sont similaire, c'est-à-dire la 3e, 4e, 5e et 6e méthode.
Voyez le code source ci-dessous.

// Méthode keyPressed() // Évènemment si on presse sur une touche du clavier void keyPressed() { // Si on presse la touche d ou D // on enclenche le tir de munitions de l'avion mère if (key == 'd' || key == 'D') { sp = true; } // Si on presse la touche p ou P // on fait une pause dans le jeu if (( key == 'p' ) || ( key == 'P' )) { pause =! pause; noLoop(); if (pause == false) loop(); } if (key == CODED) { // On appuie sur la flèche du haut if (keyCode == UP) { up = true; } else // On appuie sur la flèche du bas if (keyCode == DOWN) { dw = true; } else // On appuie sur la flèche de gauche if (keyCode == LEFT) { le = true; } else // On appuie sur la flèche de droite if (keyCode == RIGHT) { ri = true; } } } // Méthode keyReleased() // Évènemment si on relâche une touche du clavier void keyReleased() { if (key == 'd' || key == 'D') { sp = false; } if (key == CODED) { if (keyCode == UP) { up = false; } else if (keyCode == DOWN) { dw = false; } else if (keyCode == LEFT) { le = false; direction_D_G = 0; } else if (keyCode == RIGHT) { ri = false; direction_D_G = 0; } } } // Évènement si on clique sur la souris // Lorsque l'on clique sur la souris, on recommence une partie void mousePressed() { if (mouseX > 90 && mouseX < 523 && mouseY > 425 && mouseY < 455) { game_over = false; vies = 5; score = 0; // Tirage aléatoire 5 à 7 avions ennemis par trajectoire nb_avions = int(random( 5, 8 )); } } // Méthode Action_Aircraft() de l'avion mere void action_Aircraft() { // La touche flèche droite est appuyée alors // lance la méthode move_Aircraft_D_G(2) // avec 1 argument passé de la classe Aircraft if (ri == true) { // Direction droite pour facteur (2)----- Aircraft.move_Aircraft_D_G(2); } // La touche flèche gauche est appuyée alors // lance la méthode move_Aircraft_D_G(-2) // avec 1 argument passé de la classe Aircraft if (le == true) { // Direction gauche pour facteur (-2)----- Aircraft.move_Aircraft_D_G(-2); } // La touche flèche haut est appuyée alors // lance la méthode move_Aircraft_D_G(-2) // avec 1 argument passé de la classe Aircraft if (up == true) { // Direction haut pour facteur (-2)----- Aircraft.move_Aircraft_H_B(-2); } // La touche flèche bas est appuyée alors // lance la méthode move_Aircraft_D_G(2) // avec 1 argument passé de la classe Aircraft if (dw == true) { // Direction bas pour facteur (2)----- Aircraft.move_Aircraft_H_B(2); } // La touche d ou D pour le tir de munitions // de l'avion mère est appuyée if (sp == true) { // On teste la temporisation du tir de munitions de l'avion mère à répétition if (millis() - mem_time >= 125) { // On instancie le tableau dynamique Bullet avec la variable nb_balles Bullet nb_balles = new Bullet( v1.x + 1, v1.y ); // On remplit les munitions (nb_balles) à l'intérieur du tableau dynamique bullets bullets.add(nb_balles); // On remet la variable temporisation (mem_time) à jour mem_time = millis(); } } }


Alors là, c'est simple, on a la méthode keyPressed( ), keyReleased( ), mousePressed( ) et action_Aircraft( ), la méthode keyPressed( ) teste si l'on presse les touches du clavier, si c'est le cas, on attribue aux variables booléennes true, sinon elles sont à false et dans la méthode keyReleased( ), lorsque les touches du clavier, sont relâchées, on attribue aux variables booléennes false, ça veut dire que les touches du clavier ne sont plus pressées et donc relâchées.

La méthode mousePressed( ) teste les coordonnées délimitées dans un rectangle au centre de la fenêtre à la fin de la partie, dans ce rectangle, il y aura un message « Rejouer une partie » et en dessous de l'affichage « Game Over ». Lorsque l'on aura cliqué sur la souris dans ce rectangle, on initialisera les paramètres du jeu, c'est-à-dire la variable game_over sera à false, la variable vies sera de nouveau à 5, la variable score sera de nouveau à 0 et on tirera un nombre aléatoire entre 5 et 7 pour la variable nb_avions. Une nouvelle partie recommencera de nouveau.

La méthode action_Aircraft( ) n'est pas difficile à comprendre, rappellez-vous lorsque l'on a pressé les touches du clavier dans la méthode keypressed( ), on a passé les variables booléennes à true et bien ici dans cette méthode action_Aircraft( ), on teste ces mêmes variables booléennes si elles sont à true, alors, on lance les méthodes adéquates pour les déplacements et le tir de munitions de l'avion mère, ce sont les touches fléchées et les touches d ou D du clavier qui sont pressées.

On va continuer avec les 5 prochaines méthodes qui sont très similaire aussi, c'est-à-dire la 7e, 8e, 9e, 10e et 11e méthodes. Voyez le code source ci-dessous.

// Méthode vies() void vies() { fill(255); // Couleur RVB pour le texte stroke(45, 203, 102); // Couleur RVB sur bordure des dessins image(img_avion_vies, 10, 9); // Affiche l'image img_avion_vies aux cordonnées 10, 9 textFont(fontA, 25); // Donne une taille à notre fonte (police de caractère) text(int(vies), 57, 34); // Affiche la variable vies aux coordonnées 57, 34 } // Méthode score() void score() { textFont(fontA, 20); // Taille de la fonte text("Score", 485, 23); // Affiche le texte score text(int(score), 484, 47); // Affiche la variable score } // Méthode titre() void titre() { fill(255); // Couleur RVB textFont(fontA, 24); // Taille de la fonte text("Prototype", 190, 32); // Affiche le titre } // Méthode bordure() void bordure() { rectMode(CENTER); // Centre les coordonnées au milieu de la bordure fill(255, 255, 255, 50); // Couleur RVB plus canal alpha rect(300, 25, width, height - 750); // Dessine la bordure en haut de la fenêtre rectMode(CORNER); // Remets le mode rectMode par défaut } // Méthode game_Over() void game_Over() { if (game_over) { fill(255); textFont(fontA, 42); text("GAME OVER", width/2 - 170, height/2); textFont(fontA, 28); text("Rejouer une partie", width/2 - 205, height/2 + 50); image(img_dead, 43, 2); // Affiche l'icone dead (fin de partie) } }


Ces 5 méthodes font pratiquement la même chose, c'est-à-dire afficher les vies, le score, le titre, la bordure et le game over sur la fenêtre d'écran du jeu, on utilise dans le corps des méthodes la couleur, typographie et quelques variables différentes suivant les méthodes cité plus haut.

On continue avec les 2 méthodes suivantes, c'est-à-dire la 12e et 13e méthode. Voyez le code source ci-dessous.

// Méthode frequence_Vague() void frequence_Vague() { if ( fin_vague == true) { if ( millis() - frequence_espace_entre_avion >= 700) { vague_forme[no_vague] = vague_forme[no_vague]; vague_figure = vague_forme[no_vague]; Formes fx = new Formes(); enemy.add(fx); frequence_espace_entre_avion = millis(); compteur_avion++; } if (compteur_avion >= nb_avions) { compteur_avion = 0; fin_vague = false; } } } // Méthode tab_Formes() void tab_Formes() { for ( int i = enemy.size () - 1; i >= 0; i-- ) { fx = (Formes) enemy.get( i ); fx.move_fx(i); fx.display_fx(); } }


Là, nous avons la méthode fréquence_Vague( ) qui a pour rôle de lancer les vagues successives des avions ennemis dans le jeu, on règle les espaces entre les avions ennemis, on instancie la classe Formes et nous rajoutons à notre tableau dynamique <ArrayList Formes> enemy les objets construit de la classe Formes qu'on vient d'instancié precédemment. La classe Formes comporte ses méthodes de classe comme l'affichage et les déplacements qui s'occupe des trajectoires différentes des avions ennemis.

La méthode suivante tab_formes( ) parcoure le tableau dynamique <ArrayList Formes> enemy et récupèrent à chaque itération dans la boucle les objets qu'il contient en lui appliquant les lancements des méthodes de déplacement et d'affichage des avions ennemis.

On continue avec la méthode suivante, c'est-à-dire la 14e méthode. Voyez le code source ci-dessous.

// Méthode animation_Tir_Munitions() void animation_Tir_Munitions() { // On parcourt le tableau dynamique <Bullet> bullets for ( int i = bullets.size () - 1; i >= 0; i-- ) { // on obtient les munitions du tableau bullets : bullets.get( i ) Bullet o = (Bullet) bullets.get( i ); o.move(); // On lance la méthode move() de Bullet o.display(); // On lance la méthode display de Bullet // Teste la coordonnée cartésienne y des munitions de l'avion mère // si ( o.y < 71 ) en haut de l'ecran if ( o.y < 71 ) { bullets.remove( i ); // Vide le tableau bullets pour ne pas avoir des fuites mémoire } else { for ( int j=0; j< enemy.size (); j++ ) { if (round( o.x ) - round( enemy.get(j).v2.x + enemy.get(j).coord_x ) <= ecart && round( o.x ) - round( enemy.get(j).v2.x + enemy.get(j).coord_x ) >= -ecart && round( o.y ) - round( enemy.get(j).v2.y + enemy.get(j).coord_y ) <= ecart && round( o.y ) - round( enemy.get(j).v2.y + enemy.get(j).coord_y ) >= -ecart ) { x_anim_enemy = round( enemy.get(j).v2.x + enemy.get(j).coord_x ); y_anim_enemy = round( enemy.get(j).v2.y + enemy.get(j).coord_y ); i_anim_enemy = 0; nb_frames_anim_enemy = millis(); anim_feu_enemy = true; if (!game_over) { score += 25 + random(0, 25); } if ( score >= 99999 ) score = 99999; enemy.remove(j); bullets.remove(i); if ( enemy.size() == 0 ) { fin_vague = true; no_vague ++; //nb_avions++; if (no_vague == vague_forme.length) { // fin du niveau no_vague = 0; } } } } } } }


Ici, on parcourt le tableau dynamique ArrayList <Bullet> bullets et à chaque itération on récupère les éléments du tableau pour lancer les méthodes de déplacement et d'affichage des munitions de l'avion mère.

Ensuite, on teste si les munitions sortent de l'écran, si c'est le cas, on vide les éléments du tableau avec remove(i) pour ne pas avoir de fuite mémoire ou de bug. C'est ce que l'on appelle gérer la mémoire du programme. Sinon à la suite, on parcourt le tableau dynamique qui contient nos avions ennemis ArrayList <Formes> enemy et on teste les coordonnées cartésiennes de chaque avion ennemi avec les coordonnées cartésiennes de notre avion mère et s'il y a match (rencontre), c'est qu'il y a eu collision.

Quand il y a collision, on effectue une série de traitements à nos variables comme anim_feu_enemy qui passe à true ce qui va lancer l'animation de feu pour la collision de notre avion ennemi, on a aussi le score qui va augmenter d'un certain nombre plus un nombre aléatoire et comme il a eu collision, on fait un enemy.remove(j) et bullets.remove(i), toujours pareil pour ne pas avoir de fuite mémoire ou de bug.

On continue avec les 2 dernières méthodes suivantes, c'est-à-dire la 15e et 16e méthode. Voyez le code source ci-dessous.

// Methode animation_Feu_Aircraft( float x, float y ) void animation_Feu_Aircraft(float x, float y) { if ( millis() <= ( nb_frames_anim_aircraft + tempo_anim_aircraft )) { imageMode( CENTER ); image( images_feu_aircraft[i_anim_aircraft], x, y ); imageMode( CORNER ); } if ( millis() == nb_frames_anim_aircraft + tempo_anim_aircraft ) { nb_frames_anim_aircraft += tempo_anim_aircraft; i_anim_aircraft++; if ( i_anim_aircraft == 7 ) { i_anim_aircraft = 0; anim_feu_aircraft = false; } } } // Methode animation_Feu_Enemy( float x, float y ) void animation_Feu_Enemy( float x, float y ) { if ( millis() <= ( nb_frames_anim_enemy + tempo_anim_enemy )) { imageMode( CENTER ); image( images_feu_enemy[i_anim_enemy], x, y ); imageMode( CORNER ); } if ( millis() == nb_frames_anim_enemy + tempo_anim_enemy ) { nb_frames_anim_enemy += tempo_anim_enemy; i_anim_enemy++; if ( i_anim_enemy == 7 ) { i_anim_enemy = 0; anim_feu_enemy = false; } } }


Ici, nous avons nos 2 dernières méthodes pour les animations de feu après collision, une pour l'avion mère et l'autre pour les avions ennemis. On utilise une temporisation pour que les images s'animent vite de l'ordre de la milliseconde, si vous vous rappelez bien dans nos variables globales que l'on a déclaré plus haut, vous retrouver les images de l'animation, il y en a 14 au total, 7 pour l'avion mère et 7 autres pour les avions ennemis.



Classe Aircraft

Nous allons analyser nos 5 classes restantes et nous aurons terminé l'analyse complète du programme. Nous allons commencer dans l'ordre telles qu'elles sont dans le programme : La 1ère classe est Aircraft :


//******************************************************************** //** //** Classe Aircraft, déplacement et collision Aircraft (avion mère) //** //******************************************************************** class Aircraft { // Variables membres de l'objet Aircraft // vide //--------------------------------------------------------- //-- Constructeur Aircraft(int x_Aircraft, int y_Aircraft) //-- qui passe 2 arguments //-- entre parenthèses x_Aircraft et y_Aircraft //--------------------------------------------------------- Aircraft(int x_Aircraft, int y_Aircraft) { v1.x = x_Aircraft; v1.y = y_Aircraft; } // Méthode display (affichage de l'avion mère) void display() { // Centre les coordonnées cartésiennes du repère au milieu de l'image imageMode(CENTER); image(img_avion_mere, v1.x, v1.y); // Remets le mode imagetMode par défaut imageMode(CORNER); } // Méthode move_Aircraft_D_G(int facteur_direction) // avec facteur_direction passé en argument // l'avion mère va à droite ou à gauche void move_Aircraft_D_G(int facteur_direction) { direction_D_G = facteur_direction; v1.x = v1.x + facteur_direction * speed_Aircraft; // Teste de sortie d'écran à droite if (v1.x < 30) v1.x = 30; // Test de sortie d'écran à gauche else if (v1.x > width - 30) v1.x = width - 30; } // Méthode move_Aircraft_H_B(int facteur_direction) // avec facteur_direction passé en argument // l'avion mère va en haut ou en bas void move_Aircraft_H_B(int facteur_direction) { v1.y = v1.y + facteur_direction * speed_Aircraft; // Test de sortie d'écran en haut if (v1.y < 71) v1.y = 71; // Test de sortie d'écran en bas else if (v1.y > height - 22) v1.y = height - 22; } void collision() { for ( int j=0; j < enemy.size (); j++ ) { if (round(v1.x)-round(enemy.get(j).v2.x+enemy.get(j).coord_x) <= ecart && round(v1.x)-round(enemy.get(j).v2.x+enemy.get(j).coord_x) >= -ecart && round(v1.y)-round(enemy.get(j).v2.y+enemy.get(j).coord_y) <= ecart && round(v1.y)-round(enemy.get(j).v2.y+enemy.get(j).coord_y) >= -ecart) { toucher = true; // L'avion mère réapparaît au bout de 500 millisecondes après avoir été toucher. timing_launch_polaire = 500; // Recentre l'avion mère aux coordonnées cartésiennes largeur/2 et hauteur/2 + 300. v1.x = width/2; v1.y = height/2 + 300; x_anim_aircraft = round( enemy.get(j).v2.x + enemy.get(j).coord_x ); y_anim_aircraft = round( enemy.get(j).v2.y + enemy.get(j).coord_y ); i_anim_aircraft = 0; nb_frames_anim_aircraft = millis(); anim_feu_aircraft = true; vies = vies - 1; if (vies < 0) { vies = 0; game_over = true; } } } } }


Ici, nous avons la déclaration de notre classe Aircraft suivie de son constructeur qui porte le même nom que la classe elle-même. Dans le corps du constructeur, on initialise les coordonnées cartésiennes de l'avion mère avec un PVector v1 vu plus haut, c'est-à-dire pour les coordonnées cartésiennes v1.x et v1.y, lorsque, l'on connaît les vecteurs en mathématiques, on comprend mieux comment fonctionne ce système de coordonnées cartésiennes sur notre fenêtre d'écran pour déplacer un sprite ou une image plus précisément qui est la même chose.

Ensuite, nous avons la méthode display( ) qui suit, rien de bien compliqué, c'est juste la méthode d'affichage de l'avion mère avec ses coordonnées cartésiennes v1.x et v1.y.

La méthode suivante est move_Aircraft_D_G(int facteur_direction) qui passe un argument entre parenthèses facteur_direction. On fait passer une valeur à la variable facteur_direction qui est 1 ou -1, ensuite, on incrémente cette valeur à v1.x pour aller à droite ou à gauche suivant la valeur de facteur_direction.

La méthode suivante est move_Aircraft_H_B(int facteur_direction) qui passe aussi un argument entre parenthèses facteur_direction. On incrémente ensuite la valeur de facteur_direction à v1.y et suivant sa valeur qui est égale à 1 ou -1, l'avion mère ira cette fois-ci en haut ou en bas, c'est la même chose que ci-dessus, avec ces méthodes, l'avion mère ait en mouvement dans toutes les directions, même en diagonale.

La dernière méthode est collision( ) où il y a au début une boucle for qui parcourt le tableau dynamique ArrayList <Formes> enemy et le if en dessous est une condition qui teste dans son corps chaque élément de ce tableau si les coordonnées cartésiennes des avions ennemis rencontrent les coordonnées cartésiennes de l'avion mère, en fait, on fait ici les tests de collision de l'avion mère et des avions ennemis et dans le corps du if on réinitialise quelques variables car s'il y a eu collision, on commence par mettre true à la variable toucher qui déclencher l'animation de feu après collision, ensuite, la variable timing_launch_polaire prend 500 millisecondes qui va déclencher une temporisation très court avant l'affichage de nouveau de l'avion mère sur la fenêtre d'écran après collision, ensuite, on réaffecte les coordonnées cartésiennes v1.x et v1.y, l'avion mère reprend sa place sur la fenêtre d'écran.

Ensuite, les variables x_anim_aircraft et y_anim_aircraft récupèrent les coordonnées cartésiennes des avions ennemis du tableau enemy.size( ) qui est parcouru ci-dessus et l'animation de feu se fait après collision, comme ça les flammes seront positionnées sur les coordonnées cartésiennes des avions ennemis touchés, ensuite, i_anim_aircraft et nb_frames_anim_aircraft sont réinitialisés, ça veut dire que l'on pourra reboucler l'animation de feu à chaque fin de cycle, ensuite, anim_feu_aircraft déclenche l'animation de feu car il y a eu collision.

Ensuite, comme il y a eu collision, la variable vies décrémente de -1, ensuite, à la fin, on a une condition if qui teste si la variable vies est inférieur à 0, si c'est le cas, alors la variable vies reste à 0 et la variable game_over prend true ce qui lance l'affichage du game over, la partie est finie.



Classe Bullet

Continuons avec la 2ème classe qui est Bullet :

//******************************************************************** //** //** Classe Bullet, animation tir munitions de l'Aircraft (avion mère) //** //******************************************************************** class Bullet { // Variables membres float x; // Coordonnées cartésiennes x des munitions de l'avion mère float y; // Coordonnées cartésiennes y des munitions de l'avion mère float nb; // Espacement entre les munitions de l'avion mère float speed; // Vitesse du tir //---------------------------------------------- //-- Constructeur Bullet( float tx, float ty ) //-- qui passe 2 arguments //-- entre parenthèses tx et ty //---------------------------------------------- Bullet( float tx, float ty ) { x = tx; // Coordonnées cartésiennes x des munitions de l'avion mère y = ty; // Coordonnées cartésiennes y des munitions de l'avion mère nb = 10; // Espacement entre les munitions de l'avion mère égale à nb } // Méthode display() void display() { // Centre les coordonnées cartésiennes du repère au milieu de l'image imageMode( CENTER ); // Affiche l'image des munitions aux coordonnées cartésiennes x, y image( img_tir, x, y ); imageMode( CORNER ); // Remet le mode imageMode par défaut } // Méthode move() void move() { y -= nb; // Déplacement des munitions sur les y - nb } }


Alors ici, c'est très simple, on a notre classe Bullet avec en dessous son constructeur qui porte toujours le même nom que la classe et dans le corps du constructeur, on initialise les coordonnées cartésiennes du tir des munitions de l'avion mère avec x et y, ensuite, on a une méthode display( ) pour l'affichage du tir de munitions et une dernière méthode move( ) pour faire faire les mouvements des munitions sur les y - nb, ici nb correspond à l'espacement entre les munitions de l'avion mère.



Classe Formes

Continuons avec la 3ème classe qui est Formes :

//************************************************************** //** //** Classe Formes, déplacement trajectoire des avions ennemis //** //************************************************************** class Formes { // PVector v2 pour coordonnées cartésiennes v2.x et v2.y des avions ennemis; PVector v2 = new PVector(0,0); float offset, coef, pile_face, fact_pos_neg, ecart; float coef_dir= -0.01; float facteur, coord_x, coord_y; float x_tireur, y_tireur, x_cible, y_cible; float x_bullet, y_bullet; float x_copy, y_copy; float vite = 1.7; //--------------------------- //-- Constructeur Forme() //-- sans passage d'argument //--------------------------- Formes() { switch( vague_figure ) { //-- Forme croisée case 0: { offset = int(random( -400, 400 )); coef = 1.7; pile_face = int(random( 1, 11 )); if ( pile_face <= 5 ) { v2.x = 0 - 50; fact_pos_neg = 1; ecart = 0; } else { v2.x = width + 50 ; ecart = width; fact_pos_neg = -1; } x_cible = v1.x; y_cible = v1.y; coord_x = 0; coord_y = 0; } break; //-- Forme square top 1 left -> right case 1: { v2.x = -width/2; facteur = 1; // int(random( 1, 6 )); offset = 0; // int(random( 0, 351)); coord_x = width/2; coord_y = height/2; } break; //-- Forme square aleatoire -> left case 2: { v2.x = -width/2; coef += random(-0.008, 0.005); coord_x = width/2; coord_y = height/2; } break; default : { v2.x = 300 + int( random( -250, 250 )); coord_x = 0; coord_y = 0; } break; } } //------------------------ //-- Méthodes move_fx --- //------------------------ void move_fx( int i ) { switch( vague_figure ) { //-- Forme croisée case 0: { v2.y = (fact_pos_neg * ( coef * int( v2.x - ecart ))) - offset; v2.x += fact_pos_neg * vite; } if ( v2.y > height ) { enemy.remove( i ); } break; //-- Forme square top 1 left -> right case 1: { v2.y = round( coef_dir * sq( v2.x ) / facteur + offset ); v2.x += vite * sqrt( facteur ); } if ( v2.x > width/2 ) { enemy.remove( i ); } break; //--Forme square aleatoire ->left case 2: { v2.y =- coef * sq( v2.x ); v2.x += vite + 1.5 ; } if ( v2.x > width/2 ) { enemy.remove( i ); } break; default : { v2.x += 0; v2.y += 3.5; if ( v2.y > height ) { enemy.remove( i ); } } break; } if ( enemy.size() == 0 ) { fin_vague = true; no_vague ++; if (no_vague == vague_forme.length) { // fin du niveau no_vague = 0; } } } //-------------------------- //-- Méthodes display_fx //-------------------------- void display_fx() { imageMode( CORNER ); pushMatrix(); translate( v2.x + coord_x, v2.y + coord_y ); switch(vague_figure) { //-- Forme croisée case 0: { rotate(( - PI/2 + atan( v2.x * ( coef_dir * 2 / facteur ))) * 0 ); } break; //-- Forme square top 1 left -> right case 1: { rotate( - PI/2 + atan( v2.x * ( coef_dir * 2 / facteur ))); } break; //-- Forme square aleatoire -> left case 2: { rotate(- PI/2 + atan( -v2.x * 2 * coef )); } break; } image( img_avion_enemy, 0, 0 ); popMatrix(); imageMode( CORNER ); } float get_x_tireur(int i) { float x_tireur = enemy.get(i).v2.x; return x_tireur; } float get_y_tireur(int i) { float y_tireur = enemy.get(i).v2.y; return y_tireur; } float get_x_cible() { float x_cible = v1.x; return x_cible; } float get_y_cible() { float y_cible = v1.y; return y_cible; } float get_coord_x() { float COORD_X = coord_x; return COORD_X; } float get_coord_y() { float COORD_Y = coord_y; return COORD_Y; } }


Comme d'habitude, nous commençons notre classe avec sa déclaration Formes, en dessous, nous avons nos variables membres de cette classe suivie du constructeur qui porte le même nom que la classe Forme. Le constructeur initialise les paramètres de départ pour les différentes trajectoires des avions ennemis. Ensuite, viennent les deux méthodes suivantes, la première méthode se nomme move_fx(int i) qui passe un argument entre parenthèses et la deuxième méthode se nomme display_fx( ). Et pour la fin de notre classe Formes, nous avons six méthodes que l'on appelle des accesseurs, je vous les énumère dans l'ordre :

get_x_tireur(int i)
get_y_tireur(int i)
get_x_cible( )
get_y_cible( )
get_coord_x( )
get_coord_x( )

Alors dans le constructeur, nous avons d'abord une instruction switch avec entre parenthèses notre variable vague_figure qui déterminera laquelle des 3 trajectoires jouera dans le programme suivant les case 0, 1 ou 2. Si nous avons notre variable vague_figure égale à 1, ce sera la deuxième trajectoire qui jouera, les variables seront initialisées dans le constructeur, nous aurons nos positions des coordonnées cartésiennes de départ dans le plan avec v2.x et v2.y, ce sont les coordonnées cartésiennes PVector de nos avions ennemis. Pour cette trajectoire, il s'agit de notre fonction parabolique y(x) = coef_dir * x² avec les paramètres comme l'offset qui détermine l'ouverture de la courbe.

C'est la même chose pour les trajectoires où notre variable vague_figure est égale cette fois-ci à 0 ou 2, pour la première, 0, nous avons la fonction y(x) = ax + b, c'est une fonction affine qui trace une ligne droite avec une pente, dans le jeu, nous avons avec cette fonction, les avions ennemis qui se déplacent en ligne droite croisés et toujours dans le constructeur nous initialisons nos variables pour que les coordonnées cartésiennes PVector v2.x et v2.y soient tirés aléatoirement, si les avions ennemis se déplacent de droite à gauche ou de gauche à droite en partant du haut de notre fenêtre d'écran.

La dernière trajectoire pour notre variable vague_figure égale à 2 est la même que la trajectoire égale à 1, mais cette fois-ci la coordonnée cartésienne de v2.x est fixé pour le départ des avions ennemis sur la gauche de notre fenêtre d'écran et nous avons une variable coef qui tire aléatoirement une valeur de pente entre -0.008 et 0.005, les avions ennemis se déplacent donc de la gauche vers la droite avec des pentes différentes, ce qui fait donc, des trajectoires différentes.

Après le constructeur, nous avons nos deux méthodes, la première est move_fx(int i) qui s'occupe de faire évoluer les déplacements des avions ennemis avec v2.x qui est incrémenté à la variable fact_pos_neg, pour incrémenter une variable, on utilise += et le i passé en argument entre parenthèses sert à faire un remove( i ) sur l'avion en question et on teste si la coordonner cartésienne v2.y > height, alors ça veut dire qu'un avion ennemi est en dehors de notre fenêtre d'écran et il faut le supprimer de notre tableau d'objet que nous avons vu plus haut qui est ArrayList <Formes> enemy, comme ça le jeu ne plantera pas au bout d'un moment, la mémoire se videra bien au fur et à mesure que les objets se détruiront.

C'est la même chose plus bas pour les tests avec remove(i) pour v2.x > width/2, ici nous avons dans notre test un width/2, j'ai oublié de vous dire que dans le constructeur nous avons les variables coord_x = 0 et coord_y = 0 pour la trajectoire 0 car nous avons ici une fonction affine y(x) = ax + b et pour les deux trajectoires suivantes nous avons les variables coord_x = width/2 et coord_y = height/2 qui sert à centrer notre repère au milieu de notre fenêtre d'écran pour que les mouvements paraboliques soient présentés comme il le faut.

Ces deux variables coord_x et coord_y servent à centrer notre repère dans le plan au centre de notre fenêtre d'écran.

La méthode suivante display_fx( ) sert à l'affichage des avions ennemis tout simplement. Nous avons aussi un switch dans cette méthode qui est le même que précédemment dans la méthode move fx( ). Le translate avec entre parenthèses les coordonnés cartésiennes v2.x + coord_x et v2.y + coord_y qui se trouve au-dessus sert à translater les coordonnées cartésiennes et dans les différents case 0, 1 ou 2, on a une instruction rotate qui s'occupe de faire faire les rotations des avions ennemis et c'est à l'intérieur dù rotate que l'on met nos dérivées et plus précisément dans la fonction atan. En fait, le rotate sert à faire faire les rotations des avions ennemis sur la pente de la tangente.

Les 6 méthodes citées plus haut sont des accesseurs avec passage d'argument pour get_x_tireur(int i) et get_y_tireur(int i) servent à récupérer les coordonnées cartésiennes des avions ennemis du tableau d'objet ArrayList <Formes> enemy et on les assignes dans de nouvelles variables x_tireur et y_tireur et on fait la même chose pour les variables x_cible et y_cible assigner à v1.x et v1.y, ce sont les coordonnées cartésiennes de l'avion mère et toujours pareil pour COORD_X et COORD_Y assigner à coord_x et coord_y qui servent à translaté le repère au centre de la fenêtre d'écran.

Ces variables que l'on vient d'affecter serviront dans la classe Polaire_Enemy, on en aura besoin pour faire les calculs trigonométriques des arcs tangents pour que les munitions puissent être tirées des avions ennemis vers l'avion mère, nous utiliserons ces variables en les appelant par leurs méthodes respectives. En fait, nous avons accès à ces variables qui nous intéressent que dans la classe Formes et nul par ailleurs, car la classe est privée, c'est pour cela que l'on a développé ces méthodes que l'on nomme des accesseurs publics et ainsi, on pourra appeler ces méthodes d'accesseur dans la classe qui nous intéresse ici Polaire_Enemy.



Classe Polaire_Enemy

Continuons avec la 4ème classe qui est Polaire_Enemy :


//********************************************************************************* //** //** Classe Polaire_Enemy, tir des munitions des avions ennemis vers l'avion mère //** //********************************************************************************* class Polaire_Enemy { float x_tireur, y_tireur, x_cible, y_cible, theta, r = 0, vitesse; float x_bullet, y_bullet, x_bullet_before, y_bullet_before, coord_x, coord_y; //--------------------------------- //-- Constructeur Polaire_enemy() //-- sans passage d'argument //--------------------------------- Polaire_Enemy() { int avion = int( random ( 0, enemy.size() )); fx = ( Formes ) enemy.get( avion ); x_tireur = fx.get_x_tireur( avion ); y_tireur = fx.get_y_tireur( avion ); coord_x = fx.get_coord_x(); coord_y = fx.get_coord_y(); x_cible = fx.get_x_cible() - coord_x; y_cible = fx.get_y_cible() - coord_y; } void move_bullets() { if ( r==0 ) { if (x_cible >= x_tireur) { theta = atan((y_cible-y_tireur) / (x_cible-x_tireur)); // Calcul angle de tir theta += random(-0.5, 0.5); vitesse = random(2, 5); } else { theta = atan((y_cible-y_tireur) / (x_cible-x_tireur)); // Calcul angle de tir theta += (random(-0.5, 0.5)); vitesse = -( random( 2, 5 )); } } // Coordonnées polaires des munitions des avions ennemis r += vitesse; x_bullet = cos(theta) * r + x_tireur + coord_x; y_bullet = sin(theta) * r + y_tireur + coord_y; } // Affichage des munitions des avions ennemis void display_bullets() { imageMode(CENTER); image(img_balle, x_bullet, y_bullet); imageMode(CORNER); } // Test de sortie d'écran des munitions des avions ennemis void test_vide_tab_Polaire_enemy() { for ( int i = 0; i < pole.size (); i++ ) { if (pole.get(i).x_bullet < 0 || pole.get(i).x_bullet > width || pole.get(i).y_bullet < 0 || pole.get(i).y_bullet > height) { pole.remove(i); } } } // Test de collision de l'avion mère et des munitions des avions ennemis void collision() { for (int i = 0; i < pole.size(); i++) { if (round( v1.x ) - round( pole.get(i).x_bullet ) <= diff && round( v1.x ) - round( pole.get(i).x_bullet ) >= -diff && round( v1.y ) - round( pole.get(i).y_bullet ) <= diff && round( v1.y ) - round( pole.get(i).y_bullet) >= -diff ) { toucher = true; // L'avion mère réapparaît au bout de 500 millisecondes après avoir été toucher. timing_launch_polaire = 500; // Recentre l'avion mère aux coordonnées largeur/2 et hauteur/2 + 300. v1.x = width/2; v1.y = height/2 + 300; x_anim_aircraft = round( pole.get(i).x_bullet); y_anim_aircraft = round( pole.get(i).y_bullet); i_anim_aircraft = 0; nb_frames_anim_aircraft = millis(); anim_feu_aircraft = true; vies = vies - 1; if (vies < 0) { vies = 0; game_over = true; } pole.remove(i); } } } }


Alors pour cette classe Polaire_Enemy, nous avons comme d'habitude sa déclaration au début suivi de son corps entre accolades et tout de suite après nous avons ses variables membres. Ensuite, vient le constructeur qui porte toujours le même nom que la classe avec dans son corps entre accolades les affectations des variables membres déclarer juste avant. Tout va se jouer sur ces variables pour la partie trigonométrique pour que les munitions des avions ennemis visent dans le sens et la direction de l'avion mère. Dans le corps du constructeur, nous avons les variables suivantes :

Avion : avion tiré aléatoirement entre 0 et la taille du tableau enemy.size( ).
Ici, La variable Avion correspond pour les avions ennemis.

fx : on récupère l'indice de chaque avion dans le tableau enemy.size( ) avec un get (avion).

x_tireur : coordonnée cartésienne dans le plan de x_tireur qu'on récupère avec la méthode get_x_tireur qui est un accesseur dans la classe Forme vu plus haut par l'indice de l'avion avec fx.

y_tireur : coordonnée cartésienne dans le plan de y_tireur qu'on récupère avec la méthode get_y_tireur qui est un accesseur dans la classe Forme vu plus haut par l'indice de l'avion avec fx.

coord_x : cette variable est pour savoir si notre repère dans les x ou plus précisément l'abscisse est en haut à gauche de l'écran ou au centre de l'écran.

coord_y : cette variable est pour savoir si notre repère dans les y ou plus précisément l'ordonnée est en haut à gauche de l'écran ou au centre de l'écran.

x_cible : cette variable est la coordonnée cartésienne de notre avion mère dans les x ou l' abscisse dans le plan.

y_cible : cette variable est la coordonnée cartésienne de notre avion mère dans les y ou l'ordonnée dans le plan.

Ensuite, nous avons la méthode move_bullets( ) qui calcule l'angle de tir et s'occupe de faire faire les mouvements des munitions tirées depuis les séries d'avions. Ont calcul l'arc tangent avec la fonction atan qui fait le rapport du côté opposé par le côté adjacent, notre triangle est déjà posé puisque l'on a les coordonnées cartésiennes dans le plan des avions ennemis et de l'avion mère. Il y a plusieurs avions ennemis donc plusieurs triangles, ce qui fait que chaque avion ennemi tire au moins une fois dans le sens et la direction de l'avion mère. Nous pouvons donc avoir nos angles de viser, mais il y a un problème encore, si nos angles de viser sont négatifs les munitions des avions ennemis au lieu d'aller dans le sens et la direction de notre avion mère iront à l'opposé de l'avion mère alors on passe la variable vitesse qui fait faire les mouvements des munitions en négatif et tout ira bien. Juste en dessous on utilise la formule des coordonnées polaires vu sous la rubrique « trigonométrie » et le mouvement des munitions des avions ennemis se fera tout seul, rien de très difficile ici.

On continue avec la méthode display_bullets( ) qui s'occupe d'afficher l'image des munitions tirée aux coordonnées x_bullet et y_bullet.

Ensuite, on a notre méthode test_vide_tab_Polaire_enemy( ), cette méthode parcoure le tableau pole.size( ) avec une boucle for et teste en même temps si les coordonnées stockées dans ce tableau que l'on récupère avec un get(i) dans le tableau pole.size( ) sorte de l'écran, si c'est le cas on fait un remove(i) du tableau pole.size(), c'est-à-dire que l'on détruit un élément du tableau pour pas qu'il ne se sature et avoir des fuites mémoire ou des bugs par la suite.

La dernière méthode de cette classe est collision( ), ici on parcoure d'abord une boucle for du tableau pole.size( ) et on teste si les coordonnées cartésiennes de l'avion mère son égale aux coordonnées cartésiennes des munitions des avions ennemis, c'est-à-dire à peu près superposées avec une tolérance entre les tailles des deux images que sont la munition de l'avion ennemi et l'avion mère. Si c'est le cas, c'est qu'il y a eu collision alors on réaffecte quelques variables pour le bon fonctionnement du programme.

La variable toucher prend true, timing launch polaire = 500 veut dire que l'avion mère réapparaît au bout de 500 millisecondes après avoir été toucher, ensuite comme l'avion mère a été toucher ses coordonnées cartésiennes sont de nouveau recentrés sur la fenêtre d'écran avec v1.x = width/2 et v1.y = height/2 + 300.

Ensuite, x_anim_aircraft et y_anim_aircraft sont affectés aux coordonnées cartésiennes des munitions des avions ennemis, c'est à la position de ces coordonnées cartésiennes qu'il y a l'animation de feu après collision sur la fenêtre d'écran, les 3 variables en dessous que sont i_anim_aircraft = 0; frames_anim_aircraft = millis(); anim_feu_aircraft = true; servent à bien faire fonctionner l'animation de feu. bien sûr, on décrémente, la vie du joueur de -1 avec vies = vies - 1, on aurait pu écrire aussi, vie -= 1, c'est la même chose. Et si la variable vies est inférieure à 0 alors on a perdu la partie et il y a la variable game_over qui prend true ce qui lance la méthode d'affichage du game over. et on n'oublie pas comme il y a eu collision de faire un remove(i) du tableau pole.size( ) pour vider l'élément en question et donc éviter les fuites mémoire dans le programme.



Classe Scrolling

Continuons avec la 5ème et derniere classe qui est Scrolling :


//******************************************** //** //** Classe Srolling, défilement décor Océan //** //******************************************** class Scrolling { // On définit les variables membres des 2 écrans // qui défilent simultanément (x, y1, y2) int x, y1, y2; //--------------------------- //-- Constructeur Srolling() //-- sans passage d'argument //--------------------------- Scrolling() { y1 = 0; // Hauteur écran 1 y2 = -850; // Hauteur écran 2 } // Méthode init scrolling() void init_scrolling() { // Condition si scrolling égale à true alors on exécute le code // en dessous entre accolades if (scrolling) { // Assigne image (fonds_mer) à décor_1 decor_1 = loadImage("fonds_mer_1.png"); // Assigne image tirée aléatoirement (fonds_mer), 1 sur 4 à décor_2 decor_2 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } } // Méthode scrolling void scrolling() { // Condition si scrolling égale true alors on exécute le code // en dessous entre accolades if (scrolling) { // Lance la méthode init_scrolling( ) de la classe Scrolling Scrolling.init_scrolling(); } scrolling = false; // On passe la variable boolean scrolling à false (faux) Scrolling.boucle(); // Lance méthode boucle( ) de la classe Scrolling } // Méthode display() void display() { image( decor_1, x, y1 ); // Affiche décor_1 aux coordonnées x, y1 image( decor_2, x, y2 ); // Affiche décor_2 aux coordonnées x, y2 } // Méthode boucle() void boucle() { y1++; // Variable y1++ le décor_1 défile if ( y1 > height + 50) { // On teste si y1 arrive en bas de l'écran + 50 y1 = -850; // On remet y1 à -850 pour refaire un nouveau défilement // On charge aléatoirement 1 sur 4 images pour l'assigner au décor_1 decor_1 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } y2++; // Variable y2++ le décor_2 défile if ( y2 > height + 50 ) { // On teste si y2 arrive en bas de l'écran + 50 y2 = -850; // On remet y2 à -850 pour refaire un nouveau défilement // On charge aléatoirement 1 sur 4 images pour l'assigner au décor_2 decor_2 = loadImage("fonds_mer_" + int( random( 1, 5 )) + ".png"); } } }


Nous voici avec la dernière classe du programme complet, ici notre classe se nomme Scrolling qui s'occupe du défilement du décor verticalement sur la fenêtre d'écran.

Notre classe comporte un constructeur du même nom que la classe comme toujours et dans son corps il y a 2 variables y1 = 0 et y2 = -850, lorsque la classe scrolling est appelée dans le programme ces 2 variables sont affectées chacune de leur valeur respective.

Ensuite, nous poursuivons avec la méthode init_ scrolling( ) qui contient une condition avec un if (scrolling) qui teste si la variable booléenne scrolling entre parenthèses est égale à true, si c'est le cas dans son corps, nous chargeons une image que l'on assigne à la variables decor_1 et une seconde image tirée aléatoirement sur quatre à la variable decor_2.

Nous continuons avec la méthode qui suit scrolling( ) qui teste la variable booléenne scrolling si elle est égale à true, la méthode init_scrolling( ) de la classe Scrolling est lancée, ensuite à l'extérieur du corps de la condition if, la variable booléenne scrolling prend comme valeur false et juste en dessous on lance la méthode boucle( ) de la classe scrolling avec Scrolling.boucle( ).

Je vais vous expliquer ces 2 méthodes vues précédemment, la méthode de classe init_scrolling( ) est lancé depuis la méthode scrolling( ) car la variable booléenne scrolling dans la condition if prend comme valeur true, une fois lancé init_scrolling( ) charge les images du décor, l'écran 1 dans la variable decor__1 et l'écran 2 dans la variable decor _2 (pour decor _2 il y a 1 image sur 4 qui est tiré aléatoirement) ensuite dans la méthode scrolling( ) nous passons la variable booléenne scrolling à false pour ne plus lancer la méthode init_scrolling( ) sinon cette méthode continuerait à charger sans fin les images du décor et nous nous voulons charger les images qu'une seule fois au début du jeu.

La méthode suivante display( ), s'occupe de l'affichage du décor, ici nous avons deux lignes pour decor _1 et decor _2 qui sont affiché sur la fenêtre d'écran à leur coordonnées cartésiennes respective.

La dernière méthode de la classe scrolling se nomme boucle( ), nous avons dit au début que quand la classe scrolling est invoquée ou appelée dans le programme son constructeur initialise les variables dans son corps et ici nous avons 2 variables y1 = 0 et y2 = -850, et bien ici dans cette méthode boucle( ) on incrémente ces 2 variables de 1 avec y1++ et y2++ et on teste y1 et y2 si elles sont plus grandes qu'height + 50, c'est-à-dire la hauteur de l'écran qui est égal à 800 pixels + 50 pixels, si c'est le cas dans le corps de la condition if, on charge une nouvelle image tirée aléatoirement pour les deux écrans decor_1 et decor_2, ainsi le décor défile sur la fenêtre d'écran, ce n'est pas plus difficile que ça.


Conclusion

Voici ce cours de programmation fini, j'ai fait au mieux pour les explications de ces codes sources complets pour que vous puissiez programmer votre jeu vidéo, je sais que ce n'est pas si facile à assimiler tout ce contenu surtout pour des novices en programmation, mais avec de la patiente, de la volonté et de la persévérance et surtout d'avoir envie d'apprendre quelque chose de nouveau, vous devriez y arriver avec le temps. Voici terminé ce site web de cours de mathématiques pour la programmation de jeu vidéo qui m'a pris 17 mois à le développer plus les mises à jour du site web, jusqu'à aujourd'hui ou vous lisez ces lignes. J'ai été heureux d'avoir partagé mon travail sur le petit niveau que j'ai en mathématiques et en programmation pour vous avoir éclairé sur ces connaissances de base et vous avoir fait voir comment on développe un jeu vidéo que vous pourrez modifier par la suite.

Et pour finir, je remercie pour la partie mathématique l'aide des professeurs François Foucaut et mon ami d'enfance Ali Kaced, pour la partie programmation, je remercie mon ami d'enfance Carlos qui est autodidacte et qui est un programmeur averti m'ayant aidé, vérifié et corrigé des fois la cohérence des codes sources de mes projets informatiques et je remercie aussi Claire Méjean qui assure une remarquable aptitude dans son métier d'infographiste qui m'a développé les images du jeu vidéo UNITÉ-1 ainsi que les images des figures géométriques des applications MathGéo et MathGéometrie.

Je vous souhaite à tous et à toute-bonne continuations.

Merci.


himalaya2004.


Flèche pour remonter la page