On a pas mal parlé de Processing dans le forum et dans quelques articles pour l’écriture de TCOs. On va présenter ici Processing en insistant sur les analogies et les différences entre Processing et Arduino, et en mettant l’accent essentiellement sur ce qui peut servir pour nos trains et tout particulièrement pour des TCOs.
Processing pour nos trains
. Par :
. URL : https://www.locoduino.org/spip.php?article214Processing est très semblable à l’Arduino, c’est normal car Arduino s’est fortement inspiré de Processing. Les deux sont en fait très différents vis à vis de leur utilisation, mais très complémentaires (surtout pour nous car ils communiquent entre eux très facilement (par la ligne USB/série). Mais Arduino et Processing peuvent aussi communiquer assez facilement par Ethernet ou WiFi.
Arduino est destiné à faciliter la programmation d’applications sur micro-contrôleurs. Processing est destiné à faciliter la programmation d’applications d’arts visuels numériques (dessins, animations, manipulations d’images … ) en 2D et en 3D.
Arduino nécessite d’avoir un ordinateur et un module Arduino, Processing nécessite juste un ordinateur. Dans les deux cas l’ordinateur peut être sous Windows, Mac OS ou Linux.
Il y a une différence essentielle entre Processing et Arduino : Arduino est basé sur C/C++, tandis que Processing est basé sur Java. Comme Java et C/C++ sont très proches au niveau syntaxe, il n’y a pratiquement aucune différence sur les programmes simples, mais des différences apparaissent vite sur des programmes plus élaborés comme ceux manipulant des objets. Ces différences sont surtout syntaxiques et non conceptuelles (la programmation objet reste la même). On reparlera de ces différences par la suite.
Les distributions d’Arduino et de Processing, trouvées sur l’internet, sont essentiellement constituées d’un IDE (Environnement de Développement Intégré en français), permettant la saisie, les vérifications et l’exécution de programmes, ainsi que de bibliothèques. Ces distributions intègrent un compilateur adapté (C/C++ pour Arduino, Java pour Processing). Les deux IDE sont écris en Java.
On trouvera tout ce qu’il faut savoir sur l’installation, la mise en route et l’utilisation de Processing dans l’article Démarrer en Processing (1).
L’IDE Arduino s’exécute sur un ordinateur, mais le programme qui en résulte s’exécute sur un micro-contrôleur (Arduino). L’IDE Processing s’exécute sur un ordinateur et le programme qui en résulte s’exécute aussi sur un ordinateur. Les deux IDE sont très semblables, mais l’IDE Processing est beaucoup plus élaboré, les erreurs de syntaxe sont signalées au fil de la frappe du programme (à partir de Processing3), les erreurs d’exécution sont bien repérées et commentées et il existe même un débogeur.
Voici le "programme minimum" sur les deux IDE, la filiation entre Processing et Arduino est nette :
Langage
Processing et Arduino ne sont pas des langages, mais juste une sur-couche au dessus de Java ou de C/C++. Cette sur-couche comporte :
- des constantes usuelles prédéfinies, exemples :
Processing | Arduino |
---|---|
HALF_PI | INPUT_PULLUP |
QUARTER_PI | HIGH |
- des fonctions ou méthodes prédéfinies, exemples :
Processing | Arduino |
---|---|
triangle() | digitalWrite() |
color() | delay() |
mouseClicked() | analogRead() |
- des objets prédéfinis, exemples :
Processing | Arduino |
---|---|
PShape | Serial |
PImage | String |
- des bibliothèques
Similitudes
Comme Java s’est fortement inspiré de C, beaucoup de choses ont la même syntaxe en Processing et en Arduino, c’est le cas :
- des types :
boolean
,int
,char
,byte
,float
,long
,double
. (les entiers sont obligatoirement signés en Java et le type "boolean" est une vrai type et pas un entier renommé)
- des opérateurs :
+ - >= && ++ *= …
- des structures de contrôle :
if for while …
- des fonctions
Différences
Les tableaux sont traités légèrement différemment, essentiellement au niveau des déclarations. En Java les tableaux sont une sorte d’objet, ce qui implique l’utilisation d’un new
pour les créer, l’utilisation est la même, exemples :
Processing | Arduino |
---|---|
int[] t1=new int[10] ; | int t1[10] ; int* t1=new int[10] ; |
float[][] t2=new float[3][3] ; | float t2[3][3] ; |
int[] t3=new int[n] ; | int* t3=new int[n] ; |
Ce changement de syntaxe est important, la taille d’un tableau C++ est une constante (la taille est définie à l’écriture du programme), mais on peut aussi utiliser des tableaux dynamiques (la taille est définie à l’exécution du programme) avec l’opérateur new
. La taille d’un tableau Java est une constante ou une variable et, cerise sur le gâteau, cette taille est accessible avec l’attribut length
, exemple :
int n=5;
int[] t=new int[n];
int l=t.length; // la taille du tableau
La déclaration d’un tableau dynamique à deux dimensions en C++ est trop compliquée pour être décrite ici.
En Java les chaines de caractères sont exclusivement des objets, la classe associée est String
(cette classe est apparue aussi dans les versions récentes de l’Arduino). Qui dit objet dit méthodes, la classe String
comporte effectivement quelques méthodes (voir la référence Processing).
On peut obtenir la taille d’une chaîne avec la méthode length()
, il y a aussi un opérateur de concaténation noté +
(attention sur les tableaux length
est une variable donc pas de parenthèses, sur les chaînes c’est une méthode donc parenthèses), exemple :
String s="d";
s="abc"+s+"ef"; // s = "abcdef"
int l=s.length(); // la taille de la chaîne
Au niveau de l’affichage on retrouve les fonctions/méthodes print()
et println()
, dans Arduino ces deux méthodes viennent de la classe Serial
, tandis qu’avec Processing ce sont des fonctions. Les affichages se font dans la "console" pour Processing et dans le "moniteur série" pour Arduino. En Processing on peut utiliser l’opérateur de concaténation (+) pour simplifier certaines écritures, exemple :
Processing | Arduino |
---|---|
print(x) ; | Serial.print(x) ; |
println() ; | Serial.println() ; |
println(a+b) ; | Serial.println(a+b) ; |
println("x : "+x+" y : "+y) ; | Serial.print("x : ") ; Serial.print(x) ; Serial.print(" y : ") ; Serial.println(y) ; |
Restrictions
Java se veut un langage sûr, ce qui implique que toutes les sources fréquentes d’erreurs on étés éliminées par rapport à C, il n’y a pas de goto
, surtout pas de pointeurs explicites avec leurs manipulations et rien qui puisse changer un type pour faire du "bricolage".
Java est très typé, il fait beaucoup de contrôles à la compilation et tout ce qui n’a pu être vérifié à la compilation est vérifié à l’exécution, par exemple les indices des tableaux ou les "pointeurs" nuls (pour les objets).
C/C++ a plusieurs façons de passer des paramètres à une fonction/méthode : par valeur, par référence ou par pointeur. Java n’a que des passages par valeur, ce qui implique qu’aucun résultat ne peut être transmis par les paramètres (sauf pour les objets).
Processing
On va maintenant se recentrer sur Processing, sur son fonctionnement et sur les outils disponibles en se limitant à ce qui peut servir pour le train et tout particulièrement pour dessiner des TCOs.
Fonctionnement
Les structures de base d’un programme Processing ou Arduino sont très semblables. On retrouve la fonction setup()
prévue pour les initialisations et qui n’est exécutée qu’une fois au début. Avec Arduino on a une fonction loop()
qui est exécutée indéfiniment, avec Processing on a une fonction équivalente draw()
qui est aussi exécutée indéfiniment et qui est prévue pour dessiner le "dessin" qui y est décrit dans une fenêtre. Si on change tout ou partie du "dessin" (couleur, emplacement, taille, orientation …) ces modifications sont répercutées quasi immédiatement, c’est comme cela que l’on fait des "animations". Pour nos trains on ne fait pas vraiment d’animation, mais pour un TCO il y a régulièrement des changements à répercuter : changement de position d’une aiguille, changement de couleur d’un signal ou d’une zone, avancement des trains virtuels, … .
Voici le squelette d’une application Processing pour TCO :
void setup() {
// initialisations
}
void draw() {
// décrire le dessin en faisant éventuellement les modification nécessaires
}
Outils
Pour faire des "dessins" on a besoin d’outils. La fenêtre créée et ouverte automatiquement à l’exécution par Processing est un espace graphique dans lequel on peut dessiner :
- des dessins prédéfinis : points, lignes, arcs, rectangles, triangles, ellipses, quadrilatères, … en utilisant les fonctions prédéfinies éponymes (en anglais) ;
- des "formes" diverses ("shapes" en anglais) par enchaînement de lignes et de courbes de Béziers cubiques et quadratiques en utilisant la classe
PShape
et ses méthodes ;
Dans les deux cas on peut avoir un contour dessiné ou pas, avec choix de la couleur, de l’épaisseur, etc., en utilisant les méthodes prédéfinies stroke()
, noStroke()
, ... On peut aussi avoir un remplissage ou pas, avec choix de la couleur, en utilisant les méthodes prédéfinies fill()
et noFill()
. Ces méthodes s’appliquent de façon permanente à tout l’espace graphique, il faut donc faire les changements avant de dessiner autre chose qui n’aurait pas les mêmes besoins. La classe PShape
a aussi les mêmes méthodes pour les formes.
On peut aussi faire des "transformations" : translations, rotations, zooms, … soit sur tout l’espace graphique soit sur une "forme" particulière.
On peut aussi traiter des événements issus de la souris (clic, déplacement, …) ou du clavier (frappe d’une touche, …)
Pour plus de détails sur les outils consulter le site Processing : manuel de référence.
Exemples
On va écrire en Processing une "brique" de TCO, c’est à dire un "pavé" contenant un bout de rail droit, puis on transformera ce rail droit en aiguillage et pour terminer on l’animera (mouvement de l’aiguillage). Un TCO réel se fait en juxtaposant de tels pavés, mais avec une plus grande variété de pavés.
Tous les pavés sont construits sur une grille virtuelle de 10x10 points, l’épaisseur de la voie étant de 3 (1/3 de pavé) :
Les pavés sont tout petits et un "zoom" sera nécessaire.
Généralement en informatique graphique les éléments sont repérés par le coin supérieur gauche du rectangle englobant, l’axe des abscisses (axe des x) va de gauche à droite (comme en maths), l’axe des ordonnées (axe des y) va de haut en bas ( ! inverse des maths) :
Les quatre points noirs de la grille précédente (qui forment les quatre coins du rectangle représentant le bout de rail) ont donc comme coordonnées (x,y) : 0,3 9,3 9,6 0,6 .
Et ce bout de rail s’inscrit dans un pavé carré ayant comme coordonnées : 0,0 9,0 9,9 0,9 .
Le pavé droit
On commence par un bout de rail droit, c’est en fait un rectangle horizontal dessiné dans le pavé, les coordonnées de son coin supérieur gauche dans le pavé sont (0,3) zéro en abscisse (x) et trois en ordonnée (y), sa largeur est celle d’un pavé (9) et sa hauteur 1/3 de pavé donc 3. Pour que le pavé soit bien visible on va lui appliquer un taux de zoom de 5. Cela donne le programme :
int GRIS=#7F7F7F,NOIR=#000000; // des couleurs
int zoom=5; // le taux de zoom
void setup() {
println("l : "+width+" h : "+height); // largeur/hauteur de la fenetre
}
void draw() {
scale(zoom); // zoom x5
noStroke(); // pas de bordures pour le rectangle
fill(NOIR); // remplissage du rectangle en noir
rect(0,3,9,3); // dessin du rectangle (x origine, y origine, largeur, hauteur)
}
Il y a d’abord des constantes globales : des couleurs et le taux de zoom. Puis la fonction setup()
dans lequel on affiche la taille de la partie graphique de la fenêtre, c’est dans cette fenêtre que l’on va dessiner.
La fonction draw()
est chargée de dessiner notre pavé : dans l’espace graphique de la fenêtre.
- on applique à l’espace graphique un zoom (de 5) pour que cela soit bien visible
- on ne veut pas de bordure à notre futur rectangle
- on veut que notre futur rectangle soit rempli avec la couleur noire
- on dessine le rectangle du bout de rail en (0,3) avec un largeur de 9 et une hauteur de 3
L’exécution donne :
C’est pas très joli, on va centrer notre pavé. On pourrait jouer sur les coordonnées du rectangle (0,3) mais on va le faire ici en utilisant une transformation la "translation". Comme c’est le coin en haut à gauche du pavé qui est la base du dessin alors que l’on veut que cela soit le centre du pavé qui soit au centre de la fenêtre, cela nécessite des petits calculs avec la taille de la fenêtre et la taille du futur pavé pour que le centre du pavé soit au centre de la fenêtre, en n’oubliant pas que le pavé sera zoomé. Cela donne la translation suivante qui est ajoutée comme première ligne de la méthode draw()
:
translate((width-9*zoom)/2,(height-9*zoom)/2); // centrage dans la fenetre
width
et height
sont les dimensions largeur/hauteur de l’espace graphique de la fenêtre.
Pour bien visualiser les limites du pavé on va les dessiner. Ces limites sont un carré, on va donc dessiner un carré transparent non rempli (en fait un rectangle) avec un pourtour de 1 pixel. Comme on veut garder un pourtour de 1 pixel il faut dessiner avant le zoom en tenant compte de ses conséquences. Voici les trois instructions à ajouter juste après la translation dans la méthode draw()
:
stroke(NOIR); // pourtour noir
noFill(); // pas de remplissage
rect(0,0,9*zoom,9*zoom); // dessin du pourtour du carre (epaisseur 1 pixel)
Le programme complet :
int GRIS=#7F7F7F,NOIR=#000000; // des couleurs
int zoom=5; // le taux de zoom
void setup() {
println("l : "+width+" h : "+height); // largeur/hauteur de la fenetre
}
void draw() {
translate((width-9*zoom)/2,(height-9*zoom)/2); // centrage dans la fenetre
stroke(NOIR); // pourtour noir
noFill(); // pas de remplissage
rect(0,0,9*zoom,9*zoom); // dessin du pourtour du carre (epaisseur 1 pixel)
scale(zoom); // zoom x5
noStroke(); // pas de bordures pour le rectangle
fill(NOIR); // remplissage du rectangle en gris
rect(0,3,9,3); // dessin du rectangle
}
Et le résultat d’exécution :
Aiguillage
On va passer à l’aiguillage, un aiguillage a une partie droite (voie directe) et une partie courbe (voie déviée), on a déjà une partie droite, il ne manque que la partie courbe. Pour cette partie courbe il n’y a aucune figure géométrique classique, on va devoir créer une "forme" spécifique, cette forme spécifique sera définie par son "contour" que l’on pourra remplir (ou pas). Le contour se compose de deux droites et de deux arcs de cercles. La fonction prédéfinie arc()
de Processing ne convient pas, il faut donc avoir recours aux courbes de Bezier (quadratiques ou cubiques) pour avoir des courbes pour notre contour. Les courbes de Bezier quadratiques ont un point de contrôle, les cubiques deux points de contrôle. On utilisera ici deux courbes de Bezier quadratiques (sans plus de détails concernant les courbes de Bezier). Le dessin ci-dessous montre les coordonnées des points sur la grille, ainsi que les deux points de contrôle en rouge (points d’intersection des tangentes aux deux extrémités) :
Pour décrire un contour en Processing il faut un objet PShape
avec lequel on décrit le contour point par point avec les méthodes :
-
vertex()
qui définit un nouveau point relié au précédent par un segment de droite (les paramètres sont les coordonnées du point d’arrivée) -
quadraticVertex()
qui définit un nouveau point relié au précédent par une courbe de Bezier quadratique (les paramètres sont les coordonnées du point de contrôle et les coordonnées du point d’arrivée)
Cette description n’est faite qu’une fois, elle est donc mise dans le setup()
. Le dessin de la partie courbe de l’aiguille se fera en remplissant le contour (en gris), ce dessin se fera dans la fonction draw()
après le dessin de la partie droite par appel de la méthode shape()
. Voila le programme complet :
int GRIS=#7F7F7F,NOIR=#000000; // des couleurs
int zoom=5; // le taux de zoom
PShape arc; // la partie deviee de l'aiguille
void setup() {
// size(100,100,P2D); // necessaire pour certaines versions de Processing
println("l : "+width+" h : "+height); // largeur/hauteur de la fenetre
arc=createShape(); // creation de la forme
arc.beginShape(); // debut du contour de la forme
arc.noStroke(); // pas de dessin du contour
arc.vertex(0,3); // point de depart
arc.quadraticVertex(4,3, 8,-1); // courbe Bezier quadratique
arc.vertex(10,1); // ligne droite
arc.quadraticVertex(5,6, 0,6); // courbe Bezier quadratique
arc.endShape(CLOSE); // fermeture du contour de la forme (ligne droite)
}
void draw() {
translate((width-9*zoom)/2,(height-9*zoom)/2); // centrage dans la fenetre
stroke(NOIR); // pourtour noir
noFill(); // pas de remplissage
rect(0,0,9*zoom,9*zoom); // dessin du pourtour du carre (epaisseur 1 pixel)
scale(zoom); // zoom x5
noStroke(); // pas de bordures pour le rectangle
fill(NOIR); // remplissage du rectangle en noir
rect(0,3,9,3); // dessin du rectangle
arc.setFill(GRIS); // remplissage de la forme en gris
shape(arc,0,0); // dessin de la forme (forme, x origine, y origine)
}
Ce qui donne :
Sur certaines versions de Processing, le résultat est légèrement différent comme le montre la partie droite de l’image ci-dessous.
Pour résoudre ce problème, il suffit de rajouter en première ligne du setup, l’instruction :
size(100,100,P2D);
P2D pour Processing 2D de même qu’il existe P3D. Cette instruction est mise en commentaire en première ligne du setup dans le programme proposé ; au besoin, il suffit de décommenter la ligne.
L’animation
Pour terminer on va faire une petite "animation", la manœuvre de l’aiguillage en cliquant dessus. Pour cela il faut prendre en compte les événements de souris et tout particulièrement les événements de type "clic", cela se fait avec la fonction prédéfinie mouseClicked()
qui est appelée automatiquement par Processing pour chaque clic dans la fenêtre.
On va ajouter à notre programme une variable booléenne globale bsc
(bascule) qui sera inversée à chaque clic, cette inversion se faisant dans la fonction mouseClicked()
qui gère l’événement :
void mouseClicked() { bsc=!bsc; } // evenement clic (inversion de la bascule)
Il ne reste plus qu’a prendre en compte l’état de la bascule, pour jouer sur l’ordre des dessins (de la partie droite et de la partie courbe) ainsi que sur leur couleur (noir ou gris). Voila le programme complet :
int GRIS=#7F7F7F,NOIR=#000000; // des couleurs
int zoom=5; // le taux de zoom
PShape arc; // la partie deviee de l'aiguille
void setup() {
// size(100,100,P2D); // necessaire pour certaines versions de Processing
println("l : "+width+" h : "+height); // largeur/hauteur de la fenetre
arc=createShape(); // creation de la forme
arc.beginShape(); // debut du contour de la forme
arc.noStroke(); // pas de dessin du contour
arc.vertex(0,3); // point de depart
arc.quadraticVertex(4,3, 8,-1); // courbe Bezier quadratique
arc.vertex(10,1); // ligne droite
arc.quadraticVertex(5,6, 0,6); // courbe Bezier quadratique
arc.endShape(CLOSE); // fermeture du contour de la forme (ligne droite)
}
void draw() {
translate((width-9*zoom)/2,(height-9*zoom)/2); // centrage dans la fenetre
stroke(NOIR); // pourtour noir
noFill(); // pas de remplissage
rect(0,0,9*zoom,9*zoom); // dessin du pourtour du carre (epaisseur 1 pixel)
scale(zoom); // zoom x5
noStroke(); // pas de bordures pour les formes
if (bsc) { arc.setFill(NOIR); shape(arc,0,0); fill(GRIS); rect(0,3,9,3); }
// arc puis rect
else { fill(NOIR); rect(0,3,9,3); arc.setFill(GRIS); shape(arc,0,0); }
// rect puis arc
}
boolean bsc=true; // sens de l'aiguille (bascule)
void mouseClicked() { bsc=!bsc; } // evenement clic (inversion de la bascule)
Voila ce que cela donne à l’exécution, quand on clique :
En réalité, juste pour les besoins de cet article, cette image est un GIF animé et elle n’est pas sensible aux clics.
La manœuvre de l’aiguillage se fait quelque soit l’endroit où l’on clique dans la fenêtre, on pourrait facilement la restreindre à un clic dans le pavé en utilisant les coordonnées du clic (avec les variables prédéfinies mouseX
et mouseY
).
Les deux dessins que l’on a créés précédemment (partie droite et partie courbe) plus le dessin d’une partie biaise peuvent facilement êtres utilisés pour produire tous les pavés dont on a besoin pour un TCO, juste en appliquant des transformations (symétries et rotations) à ces trois dessins. D’autres choix de dessins de base peuvent êtres faits.
Voici un exemple de palette possible :
La septième icône est une TJD alors que la huitième est une TJS.
Toutes les variantes dont on aura besoin pour un TCO peuvent êtres obtenues, à partir des éléments de la palette, par des rotations et/ou des symétries que l’on peut réaliser avec des clics en jouant (par exemple) sur des clics gauches et des clics droits (pour effectuer des rotations ou des symétries).
Voici un exemple de TCO, réalisé pour le Locodrome (pour plus d’informations à ce sujet voir l’article Un gestionnaire en C++ pour votre réseau (1) et les suivants), en suivant ces principes (des dessins ont étés rajoutés : courbes, textes, signaux, boutons, ... ) :
Objets
Dans tout ce que l’on a écrit jusqu’ici on ne se rend pas trop compte que Processing c’est en fait du Java, cela pourrait être tout aussi bien du C/C++. En passant aux objets, des différences, essentiellement de syntaxe (écriture des programmes) et un peu de sémantique (signification des programmes), vont arriver.
La lecture de cette partie peut être omise si on ne fait pas d’objets. Sinon les principes de la programmation objet restent les mêmes avec les deux langages (voir la série d’articles Le monde des objets (1)). On va insister ici sur les différences (syntaxiques et sémantiques) entre les deux langages.
classes
Commençons par la forme générales des classes :
Java | C++ |
---|---|
|
|
Pas de différences à part le " ;" en fin de classe pour C++.
Petite différence pour les classes abstraites (classes non instanciables, on ne peut pas créer d’objets directement avec elles), en Java on met le mot clé abstract
devant la classe tandis que pour C++ il doit y avoir, au moins, une méthode "virtuelle pure".
variables
Pas de différences sur l’écriture des variables.
protections
Pour la protection des variables, constructeurs et méthodes on retrouve les trois mots clés public
, protected
et private
(on peut aussi ne rien mettre) dans les deux langages. La protection en Java se fait élément par élément, tandis qu’en C++ elle se fait par paquet :
Java | C++ |
---|---|
|
|
constructeurs
Pas de différence sur l’écriture des constructeurs (sauf en cas d’héritage, voir plus loin).
méthodes
La grosse différence dans l’écriture des méthodes est que celles de C++ sont écrites en deux parties, l’en tête dans la classe et le reste en dehors, des méthodes peuvent êtres complètement dans la classe mais dans ce cas elles sont réputées "inline". En Java les méthodes sont complètement dans la classe. Exemple :
Java | C++ |
---|---|
|
|
Autre différence qui viendra avec l’héritage, en Java toutes les méthodes sont réputées "virtuelles", tandis qu’en C++ il faut utiliser le mot clé virtual
pour obtenir le même effet.
héritage
Contrairement à C/C++ Java n’a pas d’héritage multiple (qui peut être une source d’erreurs inextricables) mais un "ersatz" en remplacement : les interfaces. Cette différence conduit à une syntaxe différente pour tout ce qui a rapport à l’héritage, essentiellement au niveau de la déclaration d’héritage et au niveau des constructeurs, exemples (pour simplifier les protections ont été omises) :
Java | C++ |
---|---|
|
|
Noter l’écriture super
en Java, ici super()
est utilisé comme une méthode pour appeler le constructeur hérité (cette notation est aussi utilisable dans une méthode pour appeler la même méthode héritée void m() { … super.m(); … }
).
manipulation des objets
- C++ permet de manipuler les objets de plusieurs façons : comme des variables normales, par références ou par pointeurs, on se limitera ici à la manipulation par pointeurs qui permet de profiter pleinement des mécanismes issus de l’héritage, pour plus d’informations à ce sujet voir l’article Un gestionnaire en C++ pour votre réseau (1) et les suivants. Dans le cas de pointeurs sur les objets, l’opérateur permettant d’accéder aux composants d’un objet est
->
.
- Java n’a pas de pointeurs explicites, mais Java utilise systématiquement des pointeurs pour manipuler les objets, ces pointeurs sont implicites et ne sont pas accessibles à l’utilisateur (il n’y a pas d’opérateur
->
) et l’accès aux composants se fait avec l’opérateur.
(qui existe aussi en C++).
Le pointeur sur rien (pointeur nul) est souvent utilisé, il s’écrit null
en Java mais NULL
en C++ (on utilise aussi la notation this
pour avoir un pointeur sur l’objet dans lequel on est).
Quelques manipulations d’objets :
Java | C++ |
---|---|
|
|
autres
Il y a beaucoup d’autres différences, tant syntaxiques que sémantiques, entre Java et C++, on s’est limité ici aux choses simples servant pour le train.
Il faut signaler la souplesse de Java dans l’ordre des déclarations (surtout au niveau des objets), alors qu’en C++ il est assez difficile d’organiser des classes qui s’utilisent mutuellement, comme dans le gestionnaire du Locodrome présenté dans l’article Un gestionnaire en C++ pour votre réseau (4) (sketch Arduino à télécharger).
Un gros exemple d’un algorithme de recherche récursive d’itinéraires écrit en Java et en C++ peut être trouvé sur le forum : itinéraires (réponse #64).
Certains (des mauvaises langues) disent que Java est verbeux, sur l’exemple précédent vous pouvez constater que C++ a 50% de lignes en plus !
Bilan
Le but de cet article était de présenter Processing/Java, cela s’est fait en faisant un parallèle avec Arduino/C++, on s’est focalisé sur ce qui touche au graphisme 2D et tout particulièrement à l’écriture de TCOs, ainsi que sur la programmation objet de base.
Dans des articles à venir, on parlera de la communication (par la ligne USB/série ou autre) entre Processing et Arduino. On parlera aussi de la construction pas à pas de TCOs simples en Processing, bien évidemment en utilisant la programmation objet, ainsi que de leurs interfaces avec des "gestionnaires de réseau" sur Arduino.
Pour aller plus loin avec Processing et/ou Java, on peut consulter les documentations de ces langages.