Version en ligne

Tutoriel : L'Axe Parser

Table des matières

L'Axe Parser
Information et installation
Présentation
Les outils
Notion de compilation
Mon premier programme
Créer le programme source
Afficher du texte
Faire une pause
Variables et calculs
Les variables et quelques notions de mathématiques
Calculs booléens
Exercice
Résultat
Les conditions
Explication de la condition
Les structures conditionnelles classiques
? ?? une autre structure !
Les conditions décrémentées
Les boucles
La boucle Repeat
La boucle While
La boucle For
EndIf et End!If
Le getKey
Explication
Le getKey en action
Exercice
Résultat
TP n°1 : la pluie de numéro
Quelques consignes
Les commandes à connaitre
Correction
Les ajouts possibles
Les pointeurs
La théorie
La pratique
Évolution possible
Les fonctions
Les labels
Appeler une fonction
Les variables temporaires
Exercice d'application
Dessiner c'est gagner !
Plusieurs écrans en un seul
Pixels et Géométrie
Le troisième écran
Les Datas 1/2
Le binaire
L’hexadécimal
Une histoire d'octets
Les Datas : de simples données
Les Datas 2/2
Mon premier sprite
Le tilemapping
Encore plus de Data !
Les listes
présentation des listes
Les tableaux
D'autres commandes utiles
TP n°2 : en quête de l'échec
Présentation du jeu
Quelques commandes et conseils utiles
Correction
Les ajouts possibles
Les caractères ASCII et les tokens
Les caractères ASCII
Les tokens
La commande input
Les niveaux de gris
3 niveaux de gris
4 niveaux de gris
Le tilemapping avec grayscales
Optimiser son code
Généralités
Le registre HL et ses usages
Le dilemme entre la taille et la vitesse du programme
Autres conseils
Manipuler les variables de la calculatrices
Appvars et programmes
Les "vraies" variables et plus encore...
Les variables cachées
Maîtriser les fonctions
Un peu plus sur les arguments
L'adresse des fonctions
Lambda
La récursivité
Utilisation de TI-Connect
Installer TI-Connect
Brancher sa calculatrice
Transférer ses programmes
Autres outils
Tableau des erreurs et émulation
Les erreurs
Utiliser un émulateur
Liste des commandes
Système
Ecran et mémoire tampon
Blocs de contrôle
Labels et fonctions
Math (base)
Math (avancé)
Dessin
Sprites
Texte
Data et stockage
Variables externes
Interruptions
Port de liaison
Autres

L'Axe Parser

Vous possédez une calculatrice TI-83+ ou TI-84+ (Silver Edition comprise) ? Vous voulez apprendre à programmer dessus ?

Ne partez pas, vous êtes au bon endroit :D , dans ce cours je vais vous présenter comment faire toutes sortes de programmes sur votre calculatrice, grâce à l'Axe Parser (prononcez axe parseur).

FAUX, vous découvrirez ici qu'on peut les faire non seulement rapides, mais également beaux.
Quelques exemples de programmes faits en Axe :

Image utilisateur
Image utilisateur

A gauche le jeu pokemon TI (de finale TI) et à droite le jeu axe snake (de ztrumpet)
http://www.youtube.com/v/OA-Z1DcjBSg

Où est l'utilité de faire cela ? Sans compter que vous pourrez faire de beaux programmes pour votre calculatrice ^^ , vous aurez des bases solides pour programmer dans d'autres langages par la suite (sur ordinateur par exemple ;) ).

Donc, l'Axe Parser se résume à deux choses : facilité d'utilisation et rapidité.
A la fin de ce tuto, vous serez en mesure de :

Le tout à la même vitesse que n'importe quel programme fait en ASM.

Information et installation

Présentation

Avant de commencer à programmer en Axe, il faut savoir dans quoi vous vous lancez. Tout d'abord, ce cours s'adresse :

De plus, je tiens à rappeler que l'on peut coder en Axe uniquement sur les calculatrices z80 munies de mémoire flash (ROM), qui sont :

Mais si ma calculatrice n'est pas un de ces modèles, ça veut dire que je ne peux vraiment rien faire avec l'Axe Parser ?

Pas tout à fait, il est encore possible de développer ses programmes à partir d'émulateurs (voir annexe).

Présentation

Information et installation Les outils

Présentation

La naissance d'un langage

Pour programmer sur calculatrice à processeur z80, il existe 2 langages officiels :

La nécessité d'un troisième langage s'imposait. Plusieurs tentatives plus ou moins abouties existent (voir tableau plus bas), mais celle qui ressort de plus en plus du lot est l'Axe Parser.

A seulement 19 ans, Kevin Horowitz (alias Quigibo), étudiant en génie électrique et informatique, a eu l'idée de créer un langage qui allait mettre tout le monde d'accord. Le premier février 2010 sort une première version de l'Axe Parser. C'est un succès sur le forum omnimaga qui va en faire un de ses intérêts principaux.
Dès lors, les versions du compilateur se succèdent et se perfectionnent (encore aujourd'hui). Les possibilités de ce langage sont effarantes pour un résultat indiscutable.

Avantages et désavantages

TI-Basic

xLIB/Celtic

BBC Basic

Grammer

Asm z80

Axe

Difficulté du langage

Facile

Facile

Moyen

Moyen

Difficile

Moyen

Vitesse

Lent

Moyen

Rapide

Très Rapide

Très rapide

Très rapide

Éditable sur la calculatrice?

Oui

Oui

Avec un éditeur spécial

Oui

Avec un éditeur spécial

Oui

Exécution

Interprété

Interprété

Interprété

Interprété

Compilé

Compilé

Support des sprites ?

Non

Oui

Oui

Oui

Oui

Oui

Variable nécessaire pour être exécuté

Pic, Lists, Strings,...etc

Pareil qu'en Basic avec
16ko d'application en plus

16Ko d'application

49ko d'application

Aucun

Aucun

Compatible avec les shells ?

Oui

Quelques

Aucun

Aucun

Oui

Oui

Spécialité

Math

Jeux

Varié

Varié

Tout

Jeux principalement

Voir le code source

Toujours

Toujours

Toujours

Toujours

Optionnel

Optionnel

Il n'y a pas de langage de programmation parfait. Chacun a ses avantages et inconvénients. C'est à vous de décider ce qui convient le mieux à vos besoins. Si vos priorités sont la rapidité, la facilité d'utilisation, et la capacité à faire beaucoup de choses, alors l'Axe Parser est fait pour vous.

Seulement, à chaque bon côté en Axe, il y a un mauvais côté (bon ok, il y a quand même plus de bons cotés :lol: ). Il arrive de temps en temps que votre code contienne une erreur où vous risquez le Ram Cleared ou le freeze de la calculatrice. Il est même possible de corrompre la mémoire flash de la calculatrice (mais là, faut le chercher >_ ).

Image utilisateur

Ici on peut admirer un magnifique ram cleared sur une TI 84+SE (tout ce qu'il y a de plus classique).

Image utilisateur

Ici on a affaire à deux variables Pic1, un prodige que seul l'Axe Parser peut expliquer.

Heureusement sur TI-83+ et TI-84+ vous disposez d'une mémoire flash vous permettant d'archiver vos programmes :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

puis appuyez sur

Image utilisateur

pour archiver/désarchiver.

Il est également recommandé de bien sauvegarder vos codes sources sur un ordinateur en cas de problèmes. De plus, vous pouvez utiliser un émulateur (voir annexe).


Information et installation Les outils

Les outils

Présentation Notion de compilation

Les outils

Tout d'abord il faut télécharger la dernière mise à jour : ici.
Dézippez le fichier zip.
Puis on va un peu décortiquer de quoi il est composé :

Ce dont on va avoir besoin pour l'instant est le fichier Axe.8xk. Mettez-le sur votre calculatrice.

Euh.. comment je peux mettre un fichier de mon ordi sur ma calculatrice ? o_O

Une annexe est prévue pour ça en fin de tutoriel : ici.

Maintenant il vous suffit d'aller dans le menu des applications avec la touche

Image utilisateur

, puis vous verrez Axe rajouté dans la liste. Démarrez-le, et vous devriez voir ça :

Image utilisateur

Maintenant nous allons nous intéresser aux réglages. Allez dans option, et là un sous-menu apparaît :

Image utilisateur

Shell : Permet de choisir pour quel shell on compilera le programme source, on peut soit mettre : : Permet de choisir pour quel shell on compilera le programme source, on peut soit mettre :

Alpha : Permet d'activer ou non les minuscules (lowercase en anglais).

Safety : Permet de sauver le code source lors de la compilation en cas d'éventuels bugs du programme (très utile !).

Back : Retour au menu principal

Qu'est ce qu'un shell ? :euh:

Un shell est un programme ou une application ayant une interface améliorée pour démarrer des programmes ASM prévus pour ce shell. Ici les programmes seront compilés à peu près comme pour l'ASM, donc on laisse le choix du type de shell.

Si vous préférez utiliser un shell, je vous conseille l'application noshell qui permet d'exécuter les programmes ASM qui ne nécessitent pas de shell, ainsi que certains nécessitant un shell (MirageOS et Ion notamment). Il s'installe via le menu de l'application et les programmes s'exécutent comme normalement dans le menu programme (archivé ou non).

Maintenant retournez dans le menu principal, puis allez dans compile. Pour l'instant vous n'avez peut-être aucun programme affiché, mais il peut y en avoir de 2 sortes :

Image utilisateur

Présentation Notion de compilation

Notion de compilation

Les outils Mon premier programme

Notion de compilation

"Compilation", "compiler", on ne parle que de ça, mais qu'est ce que c'est?

On a vu plus haut que les programmes sur la TI peuvent être soit "interprétés", soit "compilés".

Seulement, pour que les actions comme "allumer un pixel à tel endroit" ou encore "stocker la valeur 4" soit réalisée, il faut que la calculatrice puisse lire un langage qui est propre à elle, le langage machine.

Un programme est interprété quand la calculatrice lit, ligne par ligne, le code source du programme, l'interprète en langage machine et l'exécute en même temps. C'est le cas du Ti-Basic.
Autres exemples de langages interprétés : le Javascript, le PHP, le Python, etc.

En revanche, un programme est compilé lorsque le code source est préalablement transformé en langage machine, afin d'être directement exécuté par la TI. La calculatrice n'a plus besoin de lire ligne par ligne votre code pour l'interpréter et ensuite l'exécuter ; un programme compilé est donc en général bien plus rapide ! ;)
Autres exemples de langages compilés : le C, le java, etc.

En Axe, c'est l'application Axe.8xk qui va transformer le code source en langage machine ; on l’appelle le compilateur.

Il faut savoir que lorsque vous compilez un code source contenant une erreur, une erreur de compilation apparaît.

Nous verrons l'utilité du contenu du reste du fichier zip plus tard (mais je ne vous interdis pas de le regarder ;) ).

Bon, je ne vous retiens pas plus, rendez-vous au prochain chapitre !


Les outils Mon premier programme

Mon premier programme

Notion de compilation Créer le programme source

Maintenant que vous avez bien réglé vos options préférées, on va pouvoir commencer à programmer en Axe (enfin ! :magicien: ). Dans ce chapitre vous apprendrez à afficher du texte à l'écran. C'est un début, mais c'est de fil en aiguille que vous allez apprendre à programmer en Axe, il est donc nécessaire de commencer par le commencement. :D

Créer le programme source

Mon premier programme Afficher du texte

Créer le programme source

Créez un nouveau programme

Image utilisateur
Image utilisateur
Image utilisateur

, puis indiquez le nom de votre programme source. Ensuite sur la première ligne de ce programme, mettez un point suivi du nom de votre programme exécutable (8 caractères maximums):

PROGRAM:AXESOURC
:.AXEEXEC

Ici j'ai créé le programme AXESOURC et lorsqu'il compilera il créera AXEEXEC.

Autre chose avant de commencer à programmer : quand vous allez compiler votre source non archivé et que vous avez une erreur de compilation, vous pouvez voir à quelle ligne se trouve précisément l'erreur en appuyant sur la touche

Image utilisateur

.


Mon premier programme Afficher du texte

Afficher du texte

Créer le programme source Faire une pause

Afficher du texte

Commençons par ce qu'il y a de plus simple, écrire du texte.
Il existe 3 commandes pour afficher du texte en Axe, celles-ci sont très similaires au TI-Basic mais ne vous fiez pas aux apparences :
- La commande Text(

Image utilisateur
Image utilisateur
Image utilisateur

et la commande Text

Image utilisateur
Image utilisateur
Image utilisateur
:Text(X,Y,"MON TEXT
:.ou
:Text(X,Y
:Text "MON TEXT
Image utilisateur

La commande Text( affichera directement à un point (X,Y) le texte, alors que la commande Text nécessite qu'on ait préalablement mis un curseur pour savoir où placer le texte, cela peut être utile dans certains cas.

- La commande Disp

Image utilisateur
Image utilisateur
Image utilisateur
:Disp "MON TEXT
Image utilisateur

La commande Disp va afficher le texte en haut à gauche de l'écran. Quand le texte est trop long, il saute la ligne. Quand on enchaîne deux Disp dans un code, le deuxième s'affichera à la suite du premier.

- La commande Output(

Image utilisateur
Image utilisateur
Image utilisateur
:Output(X,Y,"MON TEXT
Image utilisateur

Ici on peut placer à un point donné notre texte.

Oui, c'est possible, surtout si vous utilisez un shell (comme MirageOS ou Ion), cela vient du fait que le programme a affiché le texte, mais qu'il s'est ensuite éteint, il faut donc mettre une pause.


Créer le programme source Faire une pause

Faire une pause

Afficher du texte Variables et calculs

Faire une pause

Rah.. vous pouviez pas attendre que j'explique? :diable:

Donc, je disais qu'il fallait faire une pause pour nous laisser le temps de voir, seulement la commande Pause utilisée en TI-Basic n'a pas la même utilisation en Axe!
La commande Pause se trouve ici :

Image utilisateur
Image utilisateur

La pause en Axe est une durée pendant laquelle le programme va être arrêté. Cependant le nombre indiqué doit être au minimum de 1, donc les codes suivants ne sont pas bons :

:Pause
:Pause 0

Une seconde correspond environ à un Pause 1800. Donc deux secondes de pause reviendrait au code suivant :

:Pause 3600
:.Car 1800 fois 2 = 3600 = 2 seconde

:o Pourquoi ce commentaire apparaît dans le code ?

Comme dans tout langage qui se respecte, l'Axe Parser possède une commande pour inclure des commentaires dans le source.
Pour commenter sur une seule ligne, on placera un point "." en début de ligne, sauf la première réservée au nom de l'exécutable.
On peut également faire des commentaires sur plusieurs lignes. Pour cela il faut commencer la première ligne par "..." et terminer la dernière de la même façon :

:...
:Ici un commentaire
:sur plusieurs lignes
:...

Ce qu'il faut retenir de ce chapitre, c'est surtout qu'il y a plusieurs commandes pour afficher du texte, et qu'il ne faut pas oublier qu'elles ont chacun des avantages qui fait qu'on les utilisera plus dans certaines situation que dans d'autres.
Rien de difficile encore, mais je vous préviens... le prochain chapitre relève un peu la barre. ;)


Afficher du texte Variables et calculs

Variables et calculs

Faire une pause Les variables et quelques notions de mathématiques

Que ce soit pour le nombre de vies dans un jeu, les nombres des coordonnées X et Y sur un plan, les points gagnés, etc. Tous ces nombres sont des valeurs que l'on manipule grâce aux variables. Dans tout langage de programmation il y a des variables, on ne peut pas y échapper.

Les variables et quelques notions de mathématiques

Variables et calculs Calculs booléens

Les variables et quelques notions de mathématiques

Des maths ? je peux m'en aller?

Ahah je vous ai enfin piégés :pirate:
Mais non ne vous inquiétez pas, ce ne sera pas bien compliqué :-° . Il est nécessaire de comprendre quelques notions pour la suite des choses, donc autant s'y attaquer dès le début !

Les opérations de base et les variables

Une variable est une valeur que l'on peut modifier durant un programme. Celle-ci est enregistrée dans un endroit très précis dans la calculatrice que l'on verra plus loin dans le cours.

Pour définir une variable, rien de plus simple :

:0→A

Ici on a donné 0 comme valeur à la variable A.

Maintenant je veux donner 0 aux variable A et B :

:0→A→B

Vous avez remarqué qu'il n'est pas nécessaire de réécrire à chaque fois la valeur 0, mais on peut faire mieux encore. Si je veux donner comme valeur 4 à A et 8 à B :

:4→A+4→B
:.Ou encore
:4→A*2→B
:.Dans le même genre
:8→B/2→A
:8→B-4→A

Jusque là ça va, non ? :-°

Maintenant si je veux faire respectivement une addition, une soustraction, une multiplication, une division et un modulo :

:1+1→A       :.A=2
:2-1→A       :.A=1
:2*2→A       :.A=4
:5/5→A       :.A=1
:4^3→A       :.A=1

Modulo? :o kesako?

Le modulo est une opération mathématique qui permet d'obtenir le reste d'une division euclidienne, donc ici 4/3 = 3*1+1, reste 1.

D'autres opérations

Maintenant on va voir quelques opérations plus complexes, et toujours utiles à savoir :

La valeur absolue :

:abs(A)→A
:.Si A est négatif, il devient positif

Il faut savoir que c'est utile que pour les nombres compris entre -32768 et 32767, donc 65535 sera considéré comme -1 :

:abs(65535)→A
:.A=1
:abs(A-101)→A
:.A=100

Le maximum des deux expressions :

:12→A+6→B
:max(A,B)→C
:.Ici C=B car B=18

Le minimum des deux expressions :

:12→A+6→B
:min(A,B)→C
:.Ici C=A car C=12

Le carré de l'expression :

:3→A
:A²→A
:.A est égale à 9

La racine de l'expression :

:9→A
:√(A)
:.A=3

N'ignorez pas cette ligne car cela pourrait vous causer plein de problème par la suite. :-°

En effet, lorsque l'on fait le calcul 1+1*2 sur sa calculatrice, on obtient 3, mais en Axe on obtiendra 4. D'où vient le problème ?
En fait l'Axe Parser lit le calcul comme il vient, sans prendre compte des règles de priorités... SAUF les parenthèses quand il y en a.

Donc pour avoir le bon résultat de 1+1*2 en Axe on écrira 1+(1*2), mais le plus simple reste d'organiser son calcul comme cela : 1*2+1.


Variables et calculs Calculs booléens

Calculs booléens

Les variables et quelques notions de mathématiques Exercice

Calculs booléens

Encore du calcul ? AAAargh..

Oui encore du calcul, mais celui ci est plus simple à comprendre, car il n'y a que 2 résultats possibles dans un calcul booléen (prononcer "boule et un") :
0 (on dira que c'est FAUX)
1 (on dira que c'est VRAI)

Cette étape est très importante pour comprendre les chapitres suivants.

Les symboles tests

Un symbole test va en fait tester soit l'infériorité, soit la supériorité, soit l'infériorité/égale, soit la supériorité/égale, soit l'inégalité ou encore l'égalité de 2 expressions. Si le test de ces deux expressions est VRAI, il renverra 1. Si il est FAUX, il renverra 0. (tout compris ? :euh: )

Je suis sûr que vous comprendrez mieux avec ce code, en commençant avec le symbole égale :

:2→A+1→B
:.A vaut 2 et B vaut 3
:A=B→C
:.C vaut 0 car A n'est pas égal à B

Maintenant avec d'autres symboles :

Maintenant, petit test, trouvez quelle est la valeur de X dans ce code :

:2→A*4→B^3→C
:A<C→D≥0→X+B→X

Vous ne trouvez pas ? :-°
Voici la correction :
D'abord il faut comprendre quelles sont les valeurs que l'on a données à A, B et C :

:2→A*4→B^3→C
:.A vaut 2
:.B est égal à 2*4 soit 8
:.8 modulo 3 vaut 2, donc C vaut 2
:.(8 divisé par 3 a pour quotient 2 car il y a 2 fois 3 dans 8, mais il a pour reste 2 (8-(2*3)))

Ensuite on calcul avec attention :

:A<C→D≥0→X+B→X
:.A vaut B (=2), A n'est pas plus petit que 0 (c'est FAUX) donc D vaudra 0
:.D égal 0 (c'est VRAI) donc X est égal à 1
:.Seulement on rajoute la valeur de B à X (X+B) comme B vaut 8, 8 plus 1 est égal à 9, au final X vaudra 9.
Les opérateurs logiques

Un opérateur logique est un moyen de comparer plusieurs expressions testées, par exemple :

Tout cela paraît compliqué, mais en réalité c'est de la logique appliquée avec des 0 et des 1. :zorro:


Les variables et quelques notions de mathématiques Exercice

Exercice

Calculs booléens Résultat

Exercice

Ce n'est pas le tout de lire, mais pour comprendre il n'y a pas meilleur moyen que de pratiquer.

Ici, l'exercice va être d'afficher 0 quand A est égal à 1 (quand A est VRAI), et 1 quand A est égal à 0 (quand A est FAUX) avec un seul calcul qui aura le rôle d'inverseur. Vos deux résultats seront affichés une seconde chacun au centre de l'écran à peu près.

Euh.. afficher une variable ?

Oui, je ne vous ai pas encore donné la commande pour afficher une variable. Il suffit de mettre la variable sans guillemets suivi de la commande ►Dec, par exemple pour afficher la variable A avec la commande Disp :

:Disp A►Dec

donc je récapitule :

:On initialise A à 0
:On fait le fameux calcul qui donnera la valeur 1 à A
:On affiche A vers le milieu de l'écran
:On attend une seconde
:On refait le fameux calcul qui cette fois donnera 0 à A
:On affiche A une ligne en dessous du premier résultat (toujours vers le centre de l'écran)
:On attend une seconde encore

Calculs booléens Résultat

Résultat

Exercice Les conditions

Résultat

Maintenant que vous avez bien cherché et bien trouvé le résultat :-° , je vais vous montrer les possibilités qui s'offrent à vous :

Tout d'abord le principal code sans le calcul :

:0→A
:.Calcule→A 
:Output(6,3,A►Dec
:Pause 1800
:.Même calcul→A
:Output(6,3,A►Dec
:Pause 1800

La Pause 1800 pour une seconde et la commande Output( car elle sera plus facile à utiliser que Text( dans ce cas (il suffit de rajouter 1 à l'axe Y pour sauter une ligne).

Pour le calcul, on pouvait soit faire avec un symbole :

:A<1→A
:...
:Quand A vaut 1, il n'est pas plus petit que 1, donc il vaut 0
:Quand A vaut 0, il est plus petit que 1 donc il vaut 1
:...
:A=0→A
:.Et c'est le même principe ici aussi
:A≠1→A
:.ainsi que là
:A≤0→A

On pouvait également faire par une astuce de calcul :

:1-A→A

Quand A est égale à 1, le calcule fait 1-1=0. Quand A est égale à 0, le calcule fait 1-0=1.

La solution retenue

La façon la plus optimisée de faire ce calcul est d'utiliser la commande xor. En effet on a vu que 0 xor 1 vaut un et 1 xor 1 vaut zéro :

:A xor 1→A

Donc voici le code final :

:0→A
:A xor 1→A 
:Output(8,4,A►Dec
:Pause 1800
:A xor 1→A
:Output(8,5,A►Dec
:Pause 1800

Relisez bien ce chapitre, c'est LE chapitre important pour cette première partie. Une fois que vous aurez compris l'intérêt des variables et des booléens, vous aurez compris beaucoup de choses. :ninja:


Exercice Les conditions

Les conditions

Résultat Explication de la condition

On retrouve les conditions dans beaucoup de langages, mais que sont exactement les conditions ?
C'est ce que nous allons essayer de comprendre durant ce chapitre.

Explication de la condition

Les conditions Les structures conditionnelles classiques

Explication de la condition

Une condition sert à tester une variable. Dans votre vie de tous les jours vous êtes confrontés à de nombreuses conditions, plus ou moins sympathiques, par exemple :

Citation

Si j'ai donné deux euros à la boulangère, alors j'ai du pain.

Ou encore :

Citation

Si je n'ai pas donné deux euros à la boulangère, alors je n'ai pas de pain.

Cette deuxième condition va être une conséquence de la première et vice versa.

Donc dans un programme de jeu ça pourrait donner :

Si je meurs
Alors j'ai perdu la partie

Ici en Axe avec V qui est égal à 1 s'il reste une vie, ou V est égal à 0 s'il ne reste aucune vie :

:If V=0                 :.La condition commence ici ou on teste si V=0
:Disp "Game Over"       :.Si cette expression est VRAIE alors on affiche "Game Over"
:End                    :N'oubliez pas le End pour marquer la fin

Toute structure conditionnelle se termine par un End. Celui ci est présent pour signaler à notre programme que notre condition est terminée, et que le code reprend son cours normal. Si il n'y a pas de End, ou qu'il y a un End en trop, vous aurez une erreur ERR:BLOCK lors de la compilation.

"V=0" ? ça ressemble drôlement à des booléens !

C'est là que je voulais en venir, le principal intérêt sera d'utiliser des booléens dans des conditions, et croyez moi ça facilite vraiment la vie ! :D


Les conditions Les structures conditionnelles classiques

Les structures conditionnelles classiques

Explication de la condition ? ?? une autre structure !

Les structures conditionnelles classiques

On a vu précédemment les conditions les plus courtes :

:If (Ma Condition)
:.le code à exécuter
:End
:.toujours terminer par un End!
If...Else...End

Maintenant, si l'on veut exécuter un code quand la condition est vraie, et un autre quand elle est fausse, on utilisera Else de la façon suivante :

:If (maCondition)
:.le code à exécuter si la condition est VRAI
:Else
:.sinon on exécute le code suivant
:."code suivant"
:End
:.(on oublie pas le End)

Je vais devoir mettre des conditions partout alors ? :euh:

Oui ! C'est un programme !
Mais je vous rassure, on peut organiser ces conditions, grâce à une autre commande : ElseIf.

If...ElseIf...Else...End

Elseif sera utilisé comme ceci :

:If (maPremièreCondition)
:.le code à exécuter si la condition est vraie
:Elseif (maDeuxièmeCondition)
:.sinon si la deuxième condition est vraie, on exécute le code suivant
:."code suivant"
:Else
:.sinon ce code est exécuté.
:End

Par exemple je reprends notre système de vie :

:If V=0
:Disp "Game over"
:Elseif V=1
:Disp "Il ne vous reste plus qu'une vie !"
:Else
:Disp "Vous êtes en parfaite santé"
:End

En fait les conditions vérifient si les tests booléens sont vrais, donc en reprenant nos symboles tests :

:If A=0
:.Mon code
:End

:If A≠0
:.Mon code
:End

:If A<0
:.Mon code
:End

:If A>0
:.Mon code
:End

:If A≥0
:.Mon code
:End

:If A≤0
:.Mon code
:End

Puis les comparateurs logiques :

:If (A=0) and (B≠8)
:.Mon code
:End

:If (A<0) or (B>8)
:.Mon code
:End

:If (A≥0) xor (B≤8)
:.Mon code
:End

Une autre particularité des booléens, on peut simplifier l'écriture suivante :

:If A=1
:.le code s'exécutera si A est VRAI
:End

En celle ci :

:If A
:.le code s'exécutera si A est VRAI
:End

Et si A est négatif, il n'y a pas un moyen plus simple que If A≠0 ?

Si, il existe les conditions inversées ! :-°

Les conditions inversées

En fait, les conditions inversées sont exactement pareilles que les conditions normales. On rajoutera juste le point d'exclamation ! :

Image utilisateur
Image utilisateur
Image utilisateur
:!If A
:.Si A est FAUX, on exécute ce code
:End

Il marchera donc pour toutes les variantes de la structure conditionnelle vue précédemment :

:!If (maCondition)
:.le code à exécuter si la condition est FAUX
:Else
:.sinon on exécute ce code
:End
:!If V
:Disp "Game over"
:Else!if V>1
:Disp "Il ne vous reste plus qu'une vie !"
:Else
:Disp "Vous êtes en parfaite santé"
:End
:!If (A=0) and (B≠8)
:.Mon code
:End

:!If (A<0) or (B>8)
:.Mon code
:End

:!If (A≥0) xor (B≤8)
:.Mon code
:End

Explication de la condition ? ?? une autre structure !

? ?? une autre structure !

Les structures conditionnelles classiques Les conditions décrémentées

? ?? une autre structure !

Sachez qu'il existe une autre structure pour diminuer la taille de vos conditions dans votre code source. Tout d'abords regardons une condition simple comme on vient de le voir :

:If A<2
:6→A
:End

Ici, il y a deux choses intéressantes : A<2 et 6→A. On utilisera le point d'interrogation ? (

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

) pour réduire cette condition à :

:A<2?6→A

Maintenant si on veut l'équivalent avec la commande Else :

:If A<2
:6→A
:Else
:3→B
:End

On ajoutera une virgule après la première expression :

:A<2?6→A,3→B

Est ce qu'il existe un moyen de réduire les conditions inversées ?

Oui, et c'est tout aussi simple : il suffit de mettre deux points d'interrogation :

:A<2??3→B

De même avec le Else :

:A<2??3→B,6→A

Les structures conditionnelles classiques Les conditions décrémentées

Les conditions décrémentées

? ?? une autre structure ! Les boucles

Les conditions décrémentées

Ce type de condition est plus dur à comprendre car, en plus de tester une condition, elle va agir sur la variable testée en la décrémentant de 1 à chaque fois qu'elle est testée. Quand cette variable atteint 0, elle est restituée à sa valeur maximum que l'on aura définie.

:DS<(VARIABLE,VALEURMAXIMUM) 
:.code1 
:End

Un exemple de condition décrémentée :

:DS<(X,3) 
:.code1 
:End

La première fois que la condition sera testée, X=3, comme X n'est pas égal à 0 on enlève 1 à X et le code1 est ignoré, la deuxième fois X=2, pareil on enlève 1 et on ignore code1, la troisième fois X=1, on enlève 1 et on ignore toujours le code1. La quatrième fois X=0, le code1 est exécuté, et X=3.

Mais comment cette condition peut être testée plusieurs fois dans le même code? o_O

Cela tombe bien, c'est le sujet de notre prochain chapitre : Les boucles.

Normalement beaucoup de choses devraient s’éclaircir dans votre tête, mais je suis sûr qu'en lisant le chapitre suivant, vous aurez la tête... encore plus clair ! :ange:


? ?? une autre structure ! Les boucles

Les boucles

Les conditions décrémentées La boucle Repeat

Une boucle consiste à répéter une partie de code en fonction d'une expression.
Omniprésentes dans tout programme, les boucles se ressemblent à travers les langages, et l'on retrouve en Axe les 3 principales boucles utilisées dans la plupart des langages :

La boucle Repeat

Les boucles La boucle While

La boucle Repeat

La boucle Repeat se traduit par : "répéter jusqu'à ce que telle condition soit vraie"

Syntaxe :

:Repeat condition
:.code à exécuter
:End
:.On n'oublie pas le End !

Le code exécuté sera répété tant que la boucle n'est pas terminée.
Par exemple, je veux répéter jusqu'à ce que le nombre de vies soit égal à 0 :

:Repeat V=0
:.code à exécuter
:End
:Disp "PERDU!"

Maintenant, imaginez le code pour faire un compteur, jusqu'à ce que V=0, avec un départ de 5 vies. :euh:

Non, pas trouvé ?
Bon OK je vous le donne :

:5→V
:Repeat V=0
:V-1→V
:End
:Disp "PERDU!"

Mieux encore, on peut mettre la ligne :V-1→V directement au début de la boucle :

:5→V
:Repeat V-1→V=0
:End
:Disp "PERDU!"

Et il n'y a pas, comme pour les conditions, un moyen plus simple d'exprimer V=0 (V est FAUX)?

Si, grâce à la boucle While. ;)


Les boucles La boucle While

La boucle While

La boucle Repeat La boucle For

La boucle While

La boucle While se traduit par : "répéter tant que telle condition est vraie".
Syntaxe :

:While condition
:.code à exécuter
:End
:.Toujours le End !

Contrairement au Repeat, le code s'exécutera tant que la condition sera vraie :

:While V
:.code à exécuter
:End
:Disp "PERDU!"

On reprend notre compteur de tout à l'heure, mais en simplifié bien sûr : :-°

:5→V
:While V-1→V
:.Tant que V est différent de 0
:End
:Disp "PERDU!"

La boucle Repeat La boucle For

La boucle For

La boucle While EndIf et End!If

La boucle For

Bon, certes les boucles Repeat et While sont utiles, mais pour faire un compteur, rien de plus utile que la boucle For(.

La syntaxe est la suivante :

:For(Variable,ValeurInitiale,ValeurDeFinDeBoucle)
:.code à exécuter
:End
:.Et bien sûr, le End.

Une variable choisie va être initialisée à la valeur initiale, et la boucle va être exécutée en incrémentant 1 à cette variable à chaque fois que le code est exécuté. Lorsque la boucle est terminée, la variable utilisée sera supprimée.

Dans un exemple concret ; je veux écrire le même texte mais en sautant une ligne à chaque fois, à l'aide de la commande Output( :

:For(A,0,7)
:Output(0,A,"Même texte
:End

Maintenant avec la variable derrière, cela pourrait donner :

:For(A,0,7)
:Output(0,A,"Choix")
:Output(6,A,A+1►Dec)
:End

La boucle While EndIf et End!If

EndIf et End!If

La boucle For Le getKey

EndIf et End!If

Voici une autre manière d'utiliser les boucles Repeat et While, en mettant la condition à la fin de la boucle. Pour cela il y a les commandes EndIf et End!If qui testent exactement de la même manière qu'une condition afin de quitter le programme ou non.

Par exemple, étudions le code suivant avec la boucle While :

:While 1
:.Code
:End!If V

While 1 sera toujours vrai car l'expression est égale à 1, donc la seule façon de quitter la boucle est de n'avoir plus aucun vie (ici la variable V).

Et on peux faire de même avec la boucle Repeat :

:Repeat 0
:.Code
:EndIf A>50

Repeat 0 est toujours faux car l'expression vaut zéro, cette fois il faudra attendre que A soit supérieur à 50 pour quitter la boucle.

Je ne comprend vraiment pas ce qu'il y a de différent à utiliser une boucle ainsi. o_O

En fait lorsque vous faites ce code :

:1→A
:Repeat A=1
:.Code A
:End
:.Fin

Seulement la partie surlignée (en jaune) sera exécutée, et le Code A sera ignoré. Or si vous mettez la condition à la fin :

:1→A
:Repeat 0
:.Code A
:EndIf A=1
:.Fin

Tout le code sera exécuté, même le Code A qui se trouve à l'intérieur de la boucle !

Cela est du au fait que la condition teste seulement à la fin de la boucle, donc le Code A est exécuté une fois avant que la boucle s'arrête. ;)

Maintenant on peux faire encore mieux, par exemple en combinant des conditions au début et à la fin :

:Repeat A<3 and (B<5
:.Code A
:End!If A

D'abord on teste si A est plus petit que 3 et qu'en même temps B est plus petit que 5. Si ce n'est pas le cas on exécute le Code A et à la fin de la boucle on test si A est égale à zéro. Si ce n'est pas le cas la boucle recommence, et ainsi de suite. :)

Arrivés ici, vous pensez avoir fait le tour des boucles. Pourtant, ce n'est pas fini ! Vous verrez que l'on peut faire encore plus avec les boucles : dans le prochain chapitre bien évidemment. :p


La boucle For Le getKey

Le getKey

EndIf et End!If Explication

C'est bien beau, vous pouvez calculer pendant un programme, mettre des conditions, le faire tourner dans une boucle, afficher plein de choses à l'écran, etc.. Mais ça ne ressemble en rien à un jeu, pour l'instant on se contente de regarder notre programme.
Le but de ce chapitre est de vous apprendre à manipuler le getkey, fameuse commande qui repère si une touche est pressée, et l'assimiler à toutes les choses que l'on a vues jusque là.

Explication

Le getKey Le getKey en action

Explication

La commande getKey, comme en TI-Basic, repère si une touche à été pressée. On peut donc utiliser la même syntaxe qu'en TI-Basic :

:getKey→K

Donc la variable K va contenir la valeur d'une touche pressée.

Mais comment savoir quelle valeur appartient à quelle touche ?

Souvenez-vous ! Dans le dossier zip que vous avez téléchargé au début :

Citation

Je vous enlève la tâche de double cliquer dessus pour voir l'image :ange: :

Image utilisateur

Cela veut dire qu'à chaque fois que j'aurai besoin de la commande getKey, je devrai avoir sous la main cette image?

Non pas forcément, car si K est une simple valeur, on peut l'afficher sur la calculatrice, avec un programme !
Je vous laisse chercher comment faire :-° .

:-° Après quelques secondes vous aurez trouvé ce code :

:.GETKEY
:0→K
:Repeat K
:getKey→K
:End
:Text(0,0,K►Dec
:Pause 2000

Mais on peut l'optimiser en utilisant dès maintenant la commande getkey :

:.GETKEY
:0→K
:Repeat K=15
:getKey→K
:If K
:Text(0,0,K►Dec
:End
:End

Le programme affichera la dernière touche pressée, et s'éteindra quand la touche 15 aura été pressée :

Image utilisateur

Mieux encore, getKey→K peut être mis directement au début de la boucle !

:.GETKEY
:0→K
:Repeat getKey→K=15
:If K
:Text(0,0,K►Dec
:End
:End

:magicien:


Le getKey Le getKey en action

Le getKey en action

Explication Exercice

Le getKey en action

Hormis les codes touches différents, c'est exactement la même commande qu'en TI-Basic?

En fait il y a 2 commandes getKey en Axe, la première va retourner un nombre pour une touche qui aurait été pressée (voir plus haut). Et la deuxième va retourner un booléen si une touche précise a été pressée.
Reprenons notre code pour les vies. Je veux que l'on quitte quand la touche

Image utilisateur

a été pressée :

:Repeat getKey(15)
:.mon code de jeu.
:End

L'avantage ? Grâce à cette commande, on peut repérer si plusieurs touches on été pressées en même temps !

:Repeat getKey(15)
:If getKey(9) or getKey(54)
:.code
:End
:If getKey(33) and getKey(25)
:.code
:End
:End

Mieux encore, on peut mettre le numéro de la touche dans une variable :

:15→X
:If getKey(X)
:End

Et si on fait getKey(0), il se passe quoi ?

En fait, il va repérer si une touche (n'importe laquelle) a été pressée, mais il est surtout utilisé pour savoir si aucune touche n'a été pressée :

:!If getKey(0)
:.Code à exécuter quand aucune touche n'a été pressée.
:End

Quoi ? vous pensiez que c'était plus compliqué que cela ? :lol: Que nenni !


Explication Exercice

Exercice

Le getKey en action Résultat

Exercice

Énoncé

Pour vous échauffer pour le prochain chapitre, je vais donner un petit exercice sur la commande getKey.

Donc le but de l'exercice va être de faire bouger la lettre 'O' à travers l'écran de la calculatrice en fonction des touches :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

.
Le 'O' ne doit pas sortir de l'écran (96*64 pixels je le rappelle).
Le programme se ferme en appuyant sur

Image utilisateur

.

Astuce

Avant de vous lancer, je vais vous donner une commande pour incrémenter et décrémenter vos variables de 1. En gros, X+1→X et X-1→X deviennent respectivement :

:X++
:X--

J'en dis pas plus, à vos caltos ! :zorro:


Le getKey en action Résultat

Résultat

Exercice TP n°1 : la pluie de numéro

Résultat

Vous êtes sûrs d'avoir bien cherché ? o_O

D'abord, il fallait choisir la commande pour afficher la lettre 'O'. La plus adaptée ici est la commande Text( car vue la rapidité du programme, vous n'auriez pas le temps de voir le 'O' se balader avec la commande output(.
Seulement, il y a une difficulté qui se pose ici ; lorsque l'on déplace le 'O', celui-ci va laisser des traces derrière lui en allant de gauche à droite et de bas en haut. Il fallait donc chercher une méthode plus ou moins efficace. Je vous propose de mettre un espace avant le 'O' et d'en mettre 5 autres, 6 pixels en dessous des coordonnées normales (X,Y).

Donc en ajoutant la boucle qui se termine en appuyant sur

Image utilisateur

, on aura ce code :

:0→X→Y
:.On initialise les variable X et Y à 0 (X = largeur et Y = hauteur)
:
:Repeat getKey(15)
:.ici la boucle repeat sera préférable
:Text(X,Y+6,"     "
:Text(X,Y," O
:.code pour modifier X et Y
:End

Bon, c'est un peu tiré par les cheveux je vous l'accorde. Mais si vous avez abandonné votre programme en rencontrant ce problème, retournez à votre calculatrice et revenez quand vous aurez vraiment fini. :pirate:

Maintenant, on doit modifier X et Y en fonction des touches directionnelles, sans oublier les "murs" virtuels :

:If getKey(2) and (X≠0
:X--
:ElseIf getKey(3) and (X≠91
:X++
:End
:If getKey(4) and (Y≠0
:Y--
:ElseIf getKey(1) and (Y≠58
:Y++
:End

En tâtonnant vous aurez sûrement trouvé les valeurs 91 (pour la largeur) et 58 (pour la hauteur), qui correspondent à la place que prend la lettre 'O'.

Donc le code final :

:0→X→Y
:.On initialise les variable X et Y à 0 (X = largeur et Y = hauteur)
:
:Repeat getKey(15)
:.ici la boucle repeat sera préférable
:Text(X,Y+6,"     "
:Text(X,Y," O
:If getKey(2) and (X≠0
:X--
:ElseIf getKey(3) and (X≠91
:X++
:End
:If getKey(4) and (Y≠0
:Y--
:ElseIf getKey(1) and (Y≠58
:Y++
:End
:End

Et voilà, vous avez terminé la première partie de ce cours.. ah non j'oubliais, un petit TP vous attend au prochain chapitre :D , relisez bien ce cours (comme d'habitude), vérifiez que vous avez du temps libre, et allez-y ! ;)


Exercice TP n°1 : la pluie de numéro

TP n°1 : la pluie de numéro

Résultat Quelques consignes

Pour ce dernier chapitre, je fais une pause, et je vous laisse travailler un peu :-° . Ce TP aura pour but de créer un jeu complet : la pluie de numéro.

Quelques consignes

TP n°1 : la pluie de numéro Les commandes à connaitre

Quelques consignes

Menu principale

Tout d'abord, le jeu doit démarrer sur un menu avec 3 choix :

fonction de jeu

Le principe est le suivant : un chiffre entre 0 à 9 (choisi au hasard) tombe de l'écran (du haut vers le bas) et le joueur doit appuyer sur la touche correspondant à ce chiffre :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

Lorsqu'un numéro a atteint le bas de l'écran, le joueur a perdu, et on peut le lui dire. ;)

Bien sûr n'importe quel joueur peut quitter à tout moment le jeu avec la touche :

Image utilisateur

La vitesse du jeu doit être croissante. A chaque numéro trouvé par le joueur, la vitesse doit augmenter.

Quand vous aurez fait tout cela, on pourra encore faire quelques ajouts sympas, par exemple :


TP n°1 : la pluie de numéro Les commandes à connaitre

Les commandes à connaitre

Quelques consignes Correction

Les commandes à connaitre

Mais comment effacer l'écran d'un coup ? comment créer un nombre aléatoire ?

J'allais vous le dire :ninja: .

Pour effacer l'écran, vous utiliserez la commande ClrHome :

Image utilisateur
Image utilisateur
Image utilisateur

.

Pour créer un nombre aléatoire, il faudra utiliser la commande rand. Celle-ci va créer un nombre aléatoire entre 0 et 65 535.

:o Mais comment faire pour que ce nombre soit entre 0 et 9 ?

C'est là qu'intervient le super modulo :zorro: , cette tâche fait partie de ses spécialités :

:rand→A
:A^10→A

Et en simplifié :

:rand^10→A

En fait, le reste de la division euclidienne de n'importe quel entier par 10, sera toujours compris entre 0 et 9 (car 10 est divisible par 10), de même si je veux créer un nombre aléatoire entre 0 et 95 :

:rand^96→A

Pour le reste vous savez faire (si si, je vous assure ! :waw: ). Sur ce, prenez bien votre temps pour faire ce TP, (plusieurs jours/semaines si il faut), et lisez la suite SEULEMENT quand vous aurez fini.


Quelques consignes Correction

Correction

Les commandes à connaitre Les ajouts possibles

Correction

Après avoir amélioré votre programme mieux que je ne saurais le faire, vous venez ici pour voir ma modeste correction ? :p

Le menu et le crédit

Soit, commençons par le commencement : il vous faut un menu qui réagisse en fonction des touches choisies.
Ici j'ai choisi la touche

Image utilisateur

pour jouer,

Image utilisateur

pour le crédit et

Image utilisateur

pour quitter :

:.PLUIENUM
:.Le menu principal
:Repeat getKey(15)
:Text(20,10,"2nd : Jouer
:Text(20,20,"Alpha : Credits
:Text(20,30,"Clear : Quitter
:
:If getKey(54)
:.Mes fonctions de jeu
:End
:
:If getKey(48)
:.Le credit du jeu
:End
:End

Il n'y a pas de suprise, tout ça a déjà été vu.

Ensuite je fais mon crédit, qui revient au menu après avoir appuyé sur la touche

Image utilisateur

:

:ClrHome
:Text(0,0,"Jeu Creer par
:Text(0,8,"Kindermoumoute
:Text(0,16,"Octobre 2010
:Text(0,30,"Merci a Wag1 pour la 
:Text(0,38,"correction de ce tutoriel
:Repeat getKey(9)
:End
:ClrHome

J'efface l'écran au début et à la fin de mon crédit, via la commande ClrHome vue plus haut. Et j'attends que la touche

Image utilisateur

soit pressée avec une boucle avec rien dedans.

Le jeu

Passons aux choses sérieuses.

D'abord, comment choisir un nombre aléatoire :

:!If T
:rand^10→N
:1→T
:End

Il suffira de donner 0 comme valeur à T pour créer un nouveau nombre aléatoire (entre 0 et 9) dans la variable N (avec la commande rand vu plus haut).

Ensuite, pour savoir si la touche pressée correspond au nombre N, on peut faire :

:If getKey(33) and (N=0)
:1→I+S→S
:ElseIf getKey(34) and (N=1)
:1→I+S→S
:
:.[etc]
:
:Else getKey(20) and (N=9)
:1→I+S→S
:End

Quand la touche appuyée correspond à N, on rajoute 1 à I (devient VRAI), puis met la valeur I+S (1+S) dans la variable S. La variable I va servir à initialiser le numéro, et la variable S va être la somme des points.

Cependant, comme vu dans le QCM précédent, on peut simplifier ce code :

:getKey(33) and (N=0)→I
:getKey(34) and (N=1)+I→I
:getKey(26) and (N=2)+I→I
:getKey(18) and (N=3)+I→I
:getKey(35) and (N=4)+I→I
:getKey(27) and (N=5)+I→I
:getKey(19) and (N=6)+I→I
:getKey(36) and (N=7)+I→I
:getKey(28) and (N=8)+I→I
:getKey(20) and (N=9)+I→I+S→S

Comme N n'aura qu'une valeur à chaque fois, il n'y a pas de risque que I soit égal à 2 ou plus.

Et encore amélioré :magicien: :

N=0 and getKey(33) or (N=1 and getKey(34)) or (N=2 and getKey(26)) or (N=3 and getKey(18)) or (N=4 and getKey(35)) or (N=5 and getKey(27)) or (N=6 and getKey(19)) or (N=7 and getKey(36)) or (N=8 and getKey(28)) or (N=9 and getKey(20))→I+S→S

Mais dans ce code il suffirait d'appuyer sur toutes le touches en même temps pour pulvériser les scores :p , donc je suis obligé de mettre un code anti-triche en remplaçant les or par des xor :

:N=0 and getKey(33) xor (N=1 and getKey(34)) xor (N=2 and getKey(26)) xor (N=3 and getKey(18)) xor (N=4 and getKey(35)) xor (N=5 and getKey(27)) xor (N=6 and getKey(19)) xor (N=7 and getKey(36)) xor (N=8 and getKey(28)) xor (N=9 and getKey(20))→I+S→S

Le ou exclusif (xor) va obliger qu'une seule touche soit pressée. Quand celui-ci retourne 1 (VRAI), on regarde si il y a également une touche correspondant à la valeur de N. Si il y en a une, alors I=1 (VRAI), et on incrémente S bien entendu.

On affiche N, qui descend de l'écran plus ou moins rapidement :

:Text(40,B,N►Dec
:Pause W
:B++

Maintenant, on va utiliser la variable I, qui détecte quand une touche correspond à N. Quand I est égale à 1, la vitesse du jeu doit augmenter et le numéro déjà à l'écran doit s'effacer :

:Text(40,B,N►Dec
:If I
:W>1?W--
:ClrHome
:0→I→T→B
:.T=0, on recréé un nombre aléatoire
:.B=0, N est affiché en haut de l'écran
:End
:Pause W
:B++

Toute la partie de jeu :

:.On initialise nos variables (ici le temps W commence à 100 ms)
:0→I→T→B+100→W
:.On efface le menu précedent
:ClrHome
:
:.Le jeu commence, et s'arrête quand la lettre touche le bas de l'écran
:Repeat B=60 or getKey(15)
:.On choisi un nombre N aléatoire
:!If T
:rand^10→N
:1→T
:End
:.On affiche N en fonction de B
:Text(40,B,N►Dec
:.On vérifie si la touche pressée correspond à N (avec un code anti-triche)
:N=0 and getKey(33) xor (N=1 and getKey(34)) xor (N=2 and getKey(26)) xor (N=3 and getKey(18)) xor (N=4 and getKey(35)) xor (N=5 and getKey(27)) xor (N=6 and getKey(19)) xor (N=7 and getKey(36)) xor (N=8 and getKey(28)) xor (N=9 and getKey(20))→I+S→S
:.Si cela correspond, on initialise les variables et le temps W diminue
:If I
:W>1?W--
:ClrHome
:0→I→T→B
:End
:
:Pause W
:B++
:End
:.On efface l'écran
:ClrHome
:.Le score s'affiche dans le menu principal
:Text(0,0,"Score : 
:Text(26,0,S►Dec

Les commandes à connaitre Les ajouts possibles

Les ajouts possibles

Correction Les pointeurs

Les ajouts possibles

Vous avez fini votre programme, mais deux forces en vous se combattent encore : Le bien et le mieux. :diable:

Ici je montrerai 3 améliorations pour rendre votre jeu un peu mieux (mais il n'y a jamais de limite dans les améliorations) :

L'intro que j'ai choisie de faire fait défiler le titre du jeu de gauche à droite, et fait apparaître très brièvement des tas de numéros sur l'écran. :ninja:
Ce n'est qu'un exemple, et vous êtes libre de faire l'intro que vous voulez :

:For(Z,0,60)
:ClrHome
:Text(Z,2," PLUIE
:Text(Z,10," DE
:Text(Z,18," NUMERO
:Text(rand^92,Z-(rand^45→B),rand^7→A►Dec
:Text(rand^92,Z+(B-5),A+1►Dec
:Text(rand^92,Z-(B+7),A+2►Dec
:Text(rand^92,Z+(B-7),A+3►Dec
:End
:ClrHome

Lorsque l'on utilise la commande ClrHome pour effacer l'écran constamment dans une boucle, le bas de l'écran sera plus clair (gris clair) et le haut plus foncé (gris noir) lors de l'affichage du texte.

Il suffit de rajouter une variable A lors de l'affichage du texte Text(A,B,N►Dec qui sera choisi au hasard dans notre fonction déjà présente :

:!If T
:rand^10→N
:rand^92→A
:1→T
:End

Dans mon exemple, il y a le niveau 0 (avec 1 numéro) et le niveau 1 (avec 2 numéros). :soleil:
Le but va être de rajouter un deuxième numéro, sans que cela ne perturbe le premier code. On va donc être obligé de recopier le même code mais avec des noms de variables différents. Il faudra que ce code soit pris en compte seulement lorsque le joueur l'a choisi (via un menu) :

:ClrHome
:Repeat getKey(9)
:Text(0,10,"Niveau :
:Text(28,10,L►Dec
:L<1 and getKey(4)-(L>0 and getKey(1))+L->L
:End

Bien sûr vous êtes incollable sur l'incrémentation et la décrémentation, ce code n'a rien de difficile à vos yeux. :-°

Maintenant on reprend toutes les fonctions de notre premier code, mais avec d'autres variable, et seulement si il y a L :

:Repeat Y=60 or (B=60) or getKey(15)
:.Code
:If L
:!If U
:rand^10→M
:rand^92→X
:1→U
:End
:End
:.Code
:If L
:Text(X,Y,M►Dec
:End
:If getKey(33) xor getKey(34) xor getKey(35) xor getKey(36) xor getKey(26) xor getKey(27) xor getKey(28) xor getKey(18) xor getKey(19) xor getKey(20)
:.Ici on laisse la condition, car ça raccourcit le code, vu que l'on a 2 fois le code, mais avec N et devient M
:If L
:(getKey(33) and (M=0)) or (getKey(34) and (M=1)) or (getKey(26) and (M=2)) or (getKey(18) and (M=3)) or (getKey(35) and (M=4)) or (getKey(27) and (M=5)) or (getKey(19) and (M=6)) or (getKey(36) and (M=7)) or (getKey(28) and (M=8)) or (getKey(20) and (M=9))→J+S→S
:End
:End
:.Code
:If J
:W>1?W--
:End
:ClrHome
:0→J→U→Y
:End
:.Code
:L?Y++

Le code final :

:.PLUIENUM
:
:.Une petite intro pour le fun
:For(Z,0,60)
:ClrHome
:Text(Z,2," PLUIE
:Text(Z,10," DE
:Text(Z,18," NUMERO
:Text(rand^92,Z-(rand^45→B),rand^7→A►Dec
:Text(rand^92,Z+(B-5),A+1►Dec
:Text(rand^92,Z-(B+7),A+2►Dec
:Text(rand^92,Z+(B-7),A+3►Dec
:End
:ClrHome
:0→S→I→J→T→U→A→B→X→Y+1→L→W
:
:.Le menu principal
:Repeat getKey(15)
:Text(20,10,"2nd : Jouer
:Text(20,20,"Alpha : Credits
:Text(20,30,"Clear : Quitter
:
:.Mes fonctions de jeu
:If getKey(54)
:ClrHome
:.Choix niveau
:Repeat getKey(9)
:Text(0,10,"Niveau :
:Text(28,10,L►Dec
:L<1 and getKey(4)-(L>0 and getKey(1))+L->L
:End
:100→W
:0→S
:ClrHome
:
:Repeat Y=60 or (B=60) or getKey(15)
:!If T
:rand^10→N
:rand^92→A
:1→T
:End
:If L
:!If U
:rand^10→M
:rand^92→X
:1→U
:End
:End
:Text(A,B,N►Dec
:L?Text(X,Y,M►Dec
:If N=0 and getKey(33) xor (N=1 and getKey(34)) xor (N=2 and getKey(26)) xor (N=3 and getKey(18)) xor (N=4 and getKey(35)) xor (N=5 and getKey(27)) xor (N=6 and getKey(19)) xor (N=7 and getKey(36)) xor (N=8 and getKey(28)) xor (N=9 and getKey(20))→I+S→S
:If L
:M=0 and getKey(33) xor (M=1 and getKey(34)) xor (M=2 and getKey(26)) xor (M=3 and getKey(18)) xor (M=4 and getKey(35)) xor (M=5 and getKey(27)) xor (M=6 and getKey(19)) xor (M=7 and getKey(36)) xor (M=8 and getKey(28)) xor (M=9 and getKey(20))→J+S→S
:End
:End
:If I
:W>1?W--
:ClrHome
:0→I→T→B
:End
:If J
:W>1?W--
:ClrHome
:0→J→U→Y
:End
:Pause W
:B++
:L?Y++
:End
:ClrHome
:Text(0,0,"Score : 
:Text(26,0,S►Dec
:0→I→J→T→U→A→B→X→Y+1→L→W
:End
:
:.Le credit du jeu
:If getKey(48)
:ClrHome
:Text(0,0,"Jeu Cree par
:Text(0,8,"Kindermoumoute
:Text(0,16,"Octobre 2010
:Text(0,30,"Merci a Wag1 pour la 
:Text(0,38,"correction de ce tutoriel
:Repeat getKey(9)
:End
:ClrHome
:End
:End

Lien de téléchargement (source et exécutable) : LIEN
Petit screenshot :

Image utilisateur

Pour ce chapitre, je vous passe de QCM (vous vous êtes déjà assez creusé les méninges :) ).
Je ne reparlerai pas de ce TP dans les chapitres suivants, néanmoins vous allez apprendre de nouvelles choses dans la prochaine partie (des tas de nouvelles choses :waw: ) qui pourront être utilisées dans ce programme pour l'optimiser encore plus, le rendre encore plus beau, plus rapide, plus jouable... (plus parfait ?).
Je vous mets l'eau à la bouche?
Bon OK, allez-y ;) .

Ici vous avez principalement vu les bases nécessaires pour faire tourner tout programme. Elles sont souvent similaires entre chaque langage de programmation. Avant d'aller lire la deuxième partie, relisez bien cette partie, vérifiez que vous avez tout saisi, faites des petits programmes pour vous entraîner, retenez votre respiration.. et direction la prochaine partie ==> [].


Correction Les pointeurs

Les pointeurs

Les ajouts possibles La théorie

Vous ne les connaissez peut être pas, mais les pointeurs remplissent une bonne partie des langages de programmation. En Axe on n'y échappe pas, mais je suis convaincu que vous allez bientôt les adopter dans tous vos programmes. ^^

La théorie

Les pointeurs La pratique

La théorie

Vous devez comprendre ce qu'est un pointeur ! Si vous n'avez jamais utilisé de langage de programmation utilisant les pointeurs avant, soyez très attentifs. Les pointeurs sont des outils puissants et utiles que vous allez utiliser dans pratiquement tous vos programmes. Ils permettent d'organiser la RAM.

Qu'est-ce que la RAM?

Littéralement Random-access memory : mémoire à accès aléatoire.
C'est de la mémoire vive alimentée constamment par vos piles qui est constituée environ de :

Sur tous les modèles vous ne verrez que 24Ko d'affiché dans le menu mémoire (

Image utilisateur
Image utilisateur
Image utilisateur

), c'est en fait la mémoire allouée pour stocker vos programmes et autres données. ;)

Un octet ? qu'est ce que c'est ?

Un octet est constitué de 8 bits. Un bit est une partie modifiable de la mémoire dans lequel on peut stocker une valeur égale à 0 ou 1. Donc un octet est égale à 8 bits de valeur 0 ou 1.
Voici quelques exemples de combinaisons d’octets :
00000000
00000001
00000011
00000110
10010101
00101100
00000111
00001000
01010000
Il y a beaucoup de combinaisons possibles, mais je n'en dis pas plus pour l'instant. ;)

Mais comment peut-on gérer toute cette RAM ? :waw:

Par le moyen le plus simple : donner à chaque octet de RAM sa propre adresse.
L'octet 0 a l'adresse 0, l'octet 1 a l'adresse 1, et ce jusqu'au dernier octet 32 767 de l'adresse 32 767 (pour une TI-83+).

Donc lorsque vous démarrez votre programme, celui ci doit être mis dans la RAM.
C'est là qu'intervient le pointeur, celui ci va également être dans la RAM, mais sa valeur va être l'adresse d'un endroit dans le programme (dans la RAM également).


Les pointeurs La pratique

La pratique

La théorie Évolution possible

La pratique

Voici un exemple de pointeur sur une chaîne de caractères :

:.HELLO
:"Hello World"→Str1
:Disp Str1

Faux !
Cela donne l'impression de fonctionner pareil. Regardons ce qui se passe réellement.

Tout d'abord, Str1 est un pointeur qui est un nombre, pas une chaîne réelle.
Donc, la phrase "Hello World" est stockée dans l'exécutable à une certaine adresse et le pointeur Str1 est juste un nombre qui nous indique où cette chaîne se trouve dans le programme.

La fonction d'affichage prend un certain nombre comme argument. Ce nombre va indiquer une adresse, et c'est comme cela qu'il sait où trouver la chaîne de caractère à afficher.

Seulement, la chaîne de caractère "Hello world" ne peut pas tenir en un seul octet, il faut donc répartir chaque caractère dans un octet. Plus précisément, il y a une lettre par octet.

Imaginons que la lettre H soit dans l'octet 1200, Str1 va donc contenir le nombre 1200, et quand on fait appel à lui il va lire la chaîne en lisant les octets aux adresses qui suivent 1200 :

Lettre stockée

Adresse contenant la lettre

"H"

1200

"e"

1201

"l"

1202

"l"

1203

"o"

1204

" "

1205

"W"

1206

"o"

1207

"r"

1208

"l"

1209

"d"

1210

0

1211

Que vient faire un 0 à l'adresse 1211 ? o_O

En fait, ce 0 est mis automatiquement à chaque fois qu'une chaîne de caractère est pointée. Son rôle n'est pas négligeable : il permet d'arrêter la lecture des octets. Imaginez, sans lui votre Disp afficherait toute la mémoire vive de votre calculatrice sous forme de caractères. :waw:

En Axe, Str1 est ce que l'on appelle un pointeur statique. Cela signifie qu'une fois qu'il est déclaré, sa valeur ne peut pas changer par la suite dans le programme.

Les pointeurs statiques sont Str, Pic, et GDB. Vous pouvez les utiliser comme vous voulez. Ce sont de simples numéros, mais c'est par convention qu'on utilise Str pour les chaînes de caractères (string), Pic pour les sprites, et GDB pour les Data. En aucun cas ce ne sont les variables utilisées en TI-Basic.

Qu'est-ce que c'est que les sprites et les Data?

:ange: Pas maintenant, cela fera l'objet d'un prochain chapitre !


La théorie Évolution possible

Évolution possible

La pratique Les fonctions

Évolution possible

Mais si le pointeur est juste un nombre, on peut faire des maths avec ?

Oui on peut faire des maths avec un pointeur ! Observons ce code par exemple :

:.HELLO
:"Hello World"→Str1
:Disp Str1+6

Cela affichera juste "World", car la chaîne est stockée dans l'ordre dans des adresses. Reprenons nos adresses de tout à l'heure, 1200+6= 1206 :

Lettre stockée

Adresse contenant la lettre

Statut

"H"

1200

Ignoré

"e"

1201

Ignoré

"l"

1202

Ignoré

"l"

1203

Ignoré

"o"

1204

Ignoré

" "

1205

Ignoré

"W"

1206

Pris en compte

"o"

1207

Pris en compte

"r"

1208

Pris en compte

"l"

1209

Pris en compte

"d"

1210

Pris en compte

0

1211

Pris en compte

Donc, au moment où nous arrivons à l'adresse 1206, nous sommes à "W". C'est pourquoi l'affichage de la partie "Hello " sera sautée.

Un petit exercice de recherche qui va vous aider à comprendre tout ça : lorsque je démarre mon jeu, je veux faire apparaître un "chargement" avec les petits points derrière qui défilent : d'abord aucun, puis le premier apparaît, le deuxième, le troisième, enfin on efface les 3 d'un coup pour n'avoir que le texte "chargement". On peut bien entendu répéter cela plusieurs fois, voire même jusqu'à ce qu'une touche soit pressée.

Dans une une boucle For( on mettra une condition décrémentée :

:.LOAD
:
:"CHARGEMENT"→Str0LOAD                      :.Initialisation des chaînes de caractères
:"...."→Str4PTS
:4→Y                                        :.Initialisation de Y
:
:For(Z,0,10)                                :.Cette boucle For va se répéter 11 fois
:DS<(Y,4)                                   :.Quand Y vaut 0, le code suivant est exécuté, mais Y est ensuite initialisé à 4
:ClrHome                                    :.Quand Y est égale à 0, on efface l'écran pour empêcher d'afficher toujours 3 points
:End
:
:Output(0,0,Str0LOAD                        :.On affiche le chargement
:Output(10,0,Str4PTS+Y                      :.avec le nombre de points voulu
:
:Pause 600                                  :.Sans pause le programme irait trop vite et l'on ne verrait rien
:End

Je ne vous laisserai pas passer si vous n'avez pas compris. :colere2:
Sans ces pointeurs vos programmes seraient beaucoup moins marrants à lire, c'est un outil indispensable pour la suite du cours.


La pratique Les fonctions

Les fonctions

Évolution possible Les labels

Indispensables pour organiser son code, les fonctions ont un rôle très important pour l'optimisation du code. Ce chapitre n'a rien de compliqué, mais il est important d'en avoir compris tout les intérêts.

Les labels

Les fonctions Appeler une fonction

Les labels

Maintenant que vous savez ce qu'est un pointeur, il vous sera plus facile de comprendre ce qu'est un label (littéralement une étiquette). C'est en fait un repère placé dans votre programme, auquel on peut faire appel lorsque l'on en a besoin.

Dans un programme en Axe, on utilisera la commande Lbl suivi du nom du label. Ce nom est composé de 5 caractères (lettre majuscule et minuscule et chiffres) maximum :

:.code A
:Lbl Label
:.code B
:Lbl Test1
:.etc

Mais comment peut-on retrouver ce repère dans le programme ? o_O

Par les adresses pardi ! :D
Il suffit d'indiquer l'adresse où l'on veut aller (l'adresse est notre repère) et en un rien de temps notre programme bascule vers le code qui commence à partir de cette adresse.

Heureusement les commandes pour faire cela sont très simples à utiliser, et le compilateur va remplacer tout seul les noms des labels par leur adresse correspondante. :)

La première façon de l'utiliser avec la commande Goto, celle-ci permet d'aller au label par un aller simple :

:Goto HEY
:.code A
:Lbl HEY
:.code B

Le code A sera donc sauté, et l'on passera au code B directement.
Le problème c'est que l'on est vite rempli de Goto :

:Lbl 0
:Goto HEY
:Lbl CO
:Goto F
:Lbl HEY
:Goto CO
:Lbl F
:Goto 0

Donc ils peuvent être utiles, mais il ne faut pas en abuser !
Les goto peuvent donner de mauvaises habitudes de programmation, si vous les utilisez trop, vous risquerez de faire du code rempli de label et de goto, au détriment des boucles, ce qui rendra votre code illisible et très mal optimisé ! :colere2:


Les fonctions Appeler une fonction

Appeler une fonction

Les labels Les variables temporaires

Appeler une fonction

Pour éviter de remplir vos codes de Goto, il existe une autre commande très pratique, qui fait appelle à vos label comme des fonctions !

o_O C'est quoi une fonction ?

Une fonction va être une partie de code qui va faire une action bien précise, par exemple, si dans mon code principal je dois afficher à plusieurs endroits le même code, je peux créer une fonction pour appeler ce code à ma guise (oui, à ma guise :lol: ).

Le code d'une fonction est encadré par 2 commandes, la première est le Lbl déjà vu, et la deuxième est un Return, que l'on trouve ici :

Image utilisateur
Image utilisateur
Image utilisateur

Donc on aura ce code pour une fonction :

:Lbl Fnct
:.Code de la fonction
:Return

Et comment fait-on appel à cette fonction ?

Il existe deux manière d'appeler une fonction, soit avec la commande sub( suivi du label, soit en marquant directement le label mais en rajoutant des parenthèses :

:Code A
:sub(Fnct)
:Fnct()
:.Code C
:
:Lbl Fnct
:.Code B
:Return

Dans l'ordre on exécutera le code A, le code B deux fois, puis le code C et une troisième fois le code B.

En fait, le programme précédent s'arrêtera au Return de la dernière ligne, car celle ci ne sert pas qu'à terminer les fonctions, elle ferme le programme si aucune fonction n'est en cours. Pour éviter de passer toujours par les fonctions avant de quitter le programme, on mettra le Return après le code C :

:Code A
:sub(Fnct)
:Fnct()
:.Code C
:Return
:
:Lbl Fnct
:.Code B
:Return

Le Return va également renvoyer la dernière valeur modifiée ou lue dans la fonction. Par exemple :

:Fnct()→B
:.On récupère la valeur de retour, B vaut donc 1
:
:Lbl Fnct
:.Code
:1
:Return

Mais aussi de cette manière en l'indiquant directement derrière le Return :

:Fnct()→B
:.B vaut donc 5
:
:Lbl Fnct
:.Code
:Return 5

Il existe également deux instructions de retour conditionnel : ReturnIf EXP pour simplifier le code suivant :

:If EXP
:Return
:End

En celui-ci :

:ReturnIf EXP

Bien sûr il existe le complément Return!If EXP qui s'utilise de la même manière :

:Return!If EXP

Autre chose à savoir : la fin d'un programme est elle-même un Return !
Donc exceptionnellement, pour les fonctions situées en fin de programme, on peut s'abstenir de Return.

On peut donc organiser notre code avec les fonctions, à peu près comme sur ce schéma :

:.MONPROGR
:
:sub(ZZZ)
:
:sub(A1)
:
:sub(ZZZ)
:
:Return
:
:Lbl A
:.Code A
:Return
:
:Lbl A1
:.Code B
:Return
:
:.Vous mettez toutes les fonctions dont vous avez besoin
:
:Lbl ZZZ
:sub(A)
:.Code Z
:.La fin du programme est un Return

:waw: Une fonction qui appelle une autre fonction ! C'est possible ça ?

Et oui, comme une fonction n'est que du code, on peut y appeler d'autres fonctions !


Les labels Les variables temporaires

Les variables temporaires

Appeler une fonction Exercice d'application

Les variables temporaires

Parfois, vous faites plusieurs fois les mêmes calculs mais avec des variables différentes, par exemple :

:A*2+8/255→A
:B*2+8/255→B
:.Ou encore
:Text(cos(X+3),sin(Y-3),"A
:Text(cos(A+3),sin(B-3),"A
:

Pour vous simplifier la vie on a créé des variables dites temporaires ; mais en réalité ce sont de simples variables : r1, r2, r3, r4, r5 et r6.

De ce fait, on peut faire tout ce que l'on fait avec les autres variables avec :

:r1*2+8/255
:Text(cos(r1+3),sin(r2-3),"A

Mais leur particularité est que l'on peut les utiliser facilement dans les fonctions en tant qu'arguments. Pour cela il faut rajouter les valeurs à envoyer après le label, en ajoutant une virgule :

:sub(FX,A,B,C)
:.Ou encore
:FX(A,B,C)
:.On peut mettre jusqu'à 6 arguments
:Return
:
:Lbl FX
:.r1 vaut A, r2 vaut B, r3 vaut C

En reprenant les exemples plus haut :

:Calc1(A)→A
:Calc1(B)→B
:
:sub(TEXT,X,Y)
:sub(TEXT,A,B)
:Return
:
:Lbl Calc1
:r1*2+8/255
:Return
:
:Lbl TEXT
:Text(cos(r1+3),sin(r2-3),"A

Faux, en apparence votre code paraît plus important, mais en réalité il est simplifié. Je suis sûr que vous vous rendrez compte très rapidement de l'importance des fonctions quand celles ci feront plusieurs lignes. :diable:


Appeler une fonction Exercice d'application

Exercice d'application

Les variables temporaires Dessiner c'est gagner !

Exercice d'application

Pour vous entraîner, voici un code à simplifier à l'aide de tous les outils que vous avez vus jusqu'à présent :

:.SRC
:rand^500*14-13→A
:rand^500*14-13→B
:rand^500*14-13→C
:rand^500*14-13→D
:rand^500*14-13→E
:Disp "HEY WORLD
:Repeat getKey(9)
:End
:While getKey(9)
:End
:ClrHome
:rand^10→W
:rand^11→X
:rand^12→Y
:rand^13→Z
:Output(0,0,W►Dec
:Output(0,1,X►Dec
:Output(0,2,Y►Dec
:Output(0,3,Z►Dec
:Repeat getKey(9)
:End
:While getKey(9)
:End

Vous aurez peut être trouvé d'autres simplifications que celle ci, mais j'ai préféré supprimer les variables W, X, Y et Z :

:.Src
:Rand1()→A
:Rand1()→B
:Rand1()→C
:Rand1()→D
:Rand1()→E
:Disp "HEY WORLD
:Pause()
:ClrHome
:For(Z,10,13)
:Output(0,Z-10,rand^Z►Dec
:End
:Pause()
:Return
:
:Lbl Pause
:Repeat getKey(9)
:End
:While getKey(9)
:End
:Return
:
:Rand1
:Return rand^500*14-13

Ce code paraît plus long, mais il réduit presque de moitié la taille de votre programme !

Ce chapitre est peut être le plus facile à comprendre pour cette partie, relisez le bien, mettez des fonctions partout où vous le pouvez et entraînez vous bien !


Les variables temporaires Dessiner c'est gagner !

Dessiner c'est gagner !

Exercice d'application Plusieurs écrans en un seul

J'imagine que vous êtes impatient de pouvoir faire de beaux dessins sur l'écran de votre calculatrice. Dans ce chapitre vous verrez qu'il existe plusieurs écrans et qu'ils ont chacun une utilité particulière. :zorro:

Plusieurs écrans en un seul

Dessiner c'est gagner ! Pixels et Géométrie

Plusieurs écrans en un seul

Vous voyez 96 pixels par 64 pixels, et vous croyez avoir fait le tour de votre écran ? :-°
Techniquement oui, cependant, il existe plusieurs écrans temporaires prêts à être affichés à tout moment.

Le fonctionnement

Tout d'abord le vrai écran existe (si si croyez moi :p ), c'est celui que vous voyez, il est composé de 96*64 (=6144) pixels : à chaque pixel on donne un statut : 1=allumé, 0=éteint.

Ensuite il y a l'écran temporaire, c'est une mémoire dans votre calculatrice spécifiée pour enregistrer le statut d'un écran, que l'on peut afficher sur le vrai écran quand on veut. Pour une meilleur compréhension, on appellera cet écran le buffer (du mot anglais qui veut dire écran tampon).

Il sert à quoi ce buffer ?

Le problème du vrai écran, c'est qu'il affiche les pixels en temps réel. Ce n'est donc pas très pratique de changer de décor si l'on doit observer tous les pixels changer un par un, cela enlève tout suspens (c'est plus simple à dire comme ça). :p
Grâce au buffer, on va pouvoir dessiner entièrement l'image voulue, puis l'afficher.

Par exemple, à gauche le buffer et à droite l'écran :

Image utilisateurImage utilisateur

le vrai écran affiche "bonjour"

Image utilisateurImage utilisateur

Pour l'instant je n'ai rien dans le buffer

Maintenant, j'affiche "tout le monde" dans le buffer :

Image utilisateurImage utilisateur

le vrai écran affiche toujours "bonjour"

Image utilisateurImage utilisateur

J'affiche "tout le monde" dans le buffer

Puis j'affiche le buffer à l'écran :

Image utilisateurImage utilisateur

le vrai écran affiche "tous le monde"

Image utilisateurImage utilisateur

"tout le monde" est toujours dans le buffer

Afficher et effacer les différents écrans

Pour effacer le vrai écran, on connait déjà la commande : ClrHome.
Maintenant, si on veut afficher le buffer sur le vrai écran, il y a la commande DispGraph :

Image utilisateur
Image utilisateur
Image utilisateur

.
Puis, si on veut afficher le vrai écran sur le buffer on utilisera la commande StoreGDB qui se trouve ici :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

.
Enfin, pour effacer le buffer, on peut utiliser la commande ClrDraw qui se trouve ici :

Image utilisateur
Image utilisateur
Image utilisateur

.
On peut également simplifier le code :

:DispGraph
:ClrDraw

On obtient le code suivant :

:DispGraphClrDraw

Ce dernier est environ deux fois plus rapide que le précédent.

Pour donner un simple exemple d'utilisation, un programme qui sauve l'écran temporairement :

:Text(20,20,"PLOP"
:.PLOP apparaît sur le vrai écran
:StoreGDB 
:.PLOP apparaît également sur le buffer
:ClrHome
:.On efface le vrai écran
:Repeat getKey(0)
:.L'écran reste blanc tant qu'on appuie pas sur une touche
:End
:DispGraphClrDraw
:...
:On affiche le buffer sur le vrai écran, on retrouve donc notre PLOP
:Puis on efface le buffer, mais PLOP est toujours sur le vrai écran
:...
:Pause 2000

Dessiner c'est gagner ! Pixels et Géométrie

Pixels et Géométrie

Plusieurs écrans en un seul Le troisième écran

Pixels et Géométrie

Pour dessiner sur cet écran intermédiaire, on aura ici une palette d'outils géométriques qui sont :

Afficher un pixel

Pour afficher un pixel, on utilisera la commande Pxl-On( :

:30→X→Y
:Pxl-On(X,Y)
:DispGraph
:Pause 1800
Image utilisateur

Les axes X et Y sont évidemment compris en 0 et 95 pour X et 0 et 63 pour Y.

On peut également effacer un pixel avec la commande Pxl-Off( :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
:30→X→Y
:Pxl-Off(X,Y)
:DispGraph
:Pause 1800

Dans le même principe, on peut inverser un pixel avec la commande Pxl-Change( :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Afficher un cercle

Pour afficher un cercle on utilise la commande Circle( (

Image utilisateur
Image utilisateur
Image utilisateur

). Le centre du cercle a pour centre les coordonnés X et Y et a pour rayon R en pixels.

:30→X→Y
:5→R
:Circle(X,Y,R)
:60→X
:10→R
:Circle(X,Y,R)
:DispGraph
:Pause 1800
Image utilisateur
Afficher un rectangle

La commande utilisée pour le rectangle normal est Rect( (

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

). Les coordonnées X et Y se situent en haut à gauche du rectangle, W est la largeur (comme width en anglais) et H est la hauteur (comme height en anglais) :

:30→X→Y→W→H
:Rect(X,Y,W,H)
:DispGraph
:Pause 1800
Image utilisateur
Afficher un rectangle inversant

La commande utilisée pour le rectangle inversant est RectI( (

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

). Les coordonnées X et Y se situent en haut à gauche du rectangle, W est la largeur (comme width en anglais) et H est la hauteur (comme height en anglais) :

:30→X→Y→W→H
:Rect(X,Y,W,H)
:W/2+X→X→Y
:RectI(X,Y,W,H)
:DispGraph
:Pause 1800
Image utilisateur
Inverser l'écran

C'est très facile, il faut utiliser la commande DrawInv :

Image utilisateur
Image utilisateur
Image utilisateur
:DrawInv 
:DispGraph
Image utilisateur

Plusieurs écrans en un seul Le troisième écran

Le troisième écran

Pixels et Géométrie Les Datas 1/2

Le troisième écran

Quoi encore un écran ? Mais ça n'en finit donc jamais ? o_O

Promis, c'est le dernier ! :-°

Celui ci s'appelle le back-buffer, il ne peut pas être affiché directement sur le vrai écran ! Il peut être affiché entièrement seulement en passant par le buffer.

Bon, bah, à quoi il sert ce back-buffer ? :D

Il peut avoir de nombreuses utilisations dans un programme, mais sa principale utilité fera l'objet d'un prochain chapitre sur les niveaux de gris. :ange:

En attendant on peut toujours apprendre à le manipuler.

Modifier et exporter le back-buffer

Pour copier le back-buffer sur le buffer, on utilisera la commande RecallPic :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

.

Pour effacer le back-buffer, on utilisera la commande ClrDrawʳ, composé de ClrDraw déjà vu (

Image utilisateur
Image utilisateur
Image utilisateur

) et du ʳ :

Image utilisateur
Image utilisateur
Image utilisateur

Et pour copier le buffer dans le back-buffer, on utilisera la commande StorePic :

Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

Et peut-on utiliser les fonctions de géométrie directement sur le back-buffer ?

Bien évidemment, il suffit de reprendre toutes les commandes vues précédemment et d'y rajouter le petit ʳ :
Pxl-On(X,Y)ʳ
Pxl-Off(X,Y)ʳ
Pxl-Change(X,Y)ʳ
Line(X1,Y1,X2,Y2)ʳ
Circle(X,Y,R)ʳ
Rect(X,Y,W,H)ʳ
RectI(X,Y,W,H)ʳ
DrawInv ʳ

En conclusion, chaque écran a ses avantages et ses défauts, mais je suis sûr que vous saurez rapidement comment les exploiter au maximum. :)
Je tiens à remercier mdr1 pour certaines précisions qu'il m'a apporté sur ce chapitre. ;)
Aller, chapitre suivant !


Pixels et Géométrie Les Datas 1/2

Les Datas 1/2

Le troisième écran Le binaire

Je vous ai parlé précédemment d'octets, dans ce chapitre on va essayer d'éclaircir un peu tout cela. Vous allez devoir apprendre des nouvelles notions ; vous saurez ce qu'est l’hexadécimal, le binaire et comment faire rentrer des valeurs dans un octet (qui sera ensuite pointé bien évidemment ;) ).

Le binaire

Les Datas 1/2 L’hexadécimal

Le binaire

Pour pouvoir comprendre la suite du cours, vous devez connaître quelques notions : le binaire et l’hexadécimal.

Et alors ? un petit rappel ne fera pas de mal. :p

Apprenons à compter

Tout d'abord il faut savoir ce qu'est une base numérique. La base la plus répandue aujourd'hui est la base 10 ; l'évolution a fait que l'homme a eu 10 doigts et qu'il a appris à compter avec ses 10 doigts. Donc, cette base 10 (appelée aussi base décimale), est constituée de 10 numéros :

0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

Une fois que nous atteignons le dernier numéro, nous créons un nouvel emplacement en face du premier, et en incrémentant de 1 à chaque fois que l'emplacement précédent arrive à plus de 9 (il faut donc créer une dizaine) :

8, 9, 10, 11, 12, ..., 19, 20, ...

Et ainsi de suite pour les centaines, les milliers, etc.

Si l'on étudie notre façon de compter, on se rend compte que chaque emplacement ajouté est une puissance de 10 en plus :

10^3

10^2

10^1

10^0

chiffre

chiffre

chiffre

chiffre

*1000

*100

*10

*1

En fait, lorsque l'on change de base, ce tableau restera le même : on changera juste le nombre 10 par celui de la base voulue.

Le binaire

Le binaire (ou base 2) n'est constitué que de 2 numéros : 0 et 1. On y compte comme dans toutes les bases, en rajoutant un emplacement une fois que le précédent atteint le maximum de la base :
0, 1, 10, 11, 100, 101, etc.

Un petit tableau s'impose pour comparer le binaire et le décimal :

Pour le décimal :

0

1

2

3

4

5

6

7

8

9

10

Pour le binaire :

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

Ici, je laisse les 0 en trop pour une meilleure vue d'ensemble.

:waw: Et si je veux trouver un nombre binaire comme 101010, il n'y a pas un moyen plus simple que d'écrire toute la suite jusqu'à arriver à ce nombre ?

Si, pour cela reprenons le tableau précédent adapté à la base 2 :

2^5

2^4

2^3

2^2

2^1

2^0

chiffre

chiffre

chiffre

chiffre

chiffre

chiffre

*32

*16

*8

*4

*2

*1

Pour le nombre 101010 :

2^5

2^4

2^3

2^2

2^1

2^0

-

1

0

1

0

1

0

-

*32

*16

*8

*4

*2

*1

-

1*32

+0*16

+1*8

+0*4

+1*2

+0*1

=42

Il suffit de connaître votre table de 2 et le tour est joué ! :soleil:

Quoi ? Vous ne la connaissez pas ? Je suis sûr que vous trouverez votre bonheur ici.

Et si je veux convertir un nombre décimal en binaire ?

C'est encore plus simple, la méthode consiste à décomposer le nombre décimal en plusieurs puissances de 2. Je prends le nombre 87 par exemple ; la puissance de 2 inférieure à 87 la plus proche est 64 :

87-64=23

On commence donc le nombre binaire par 1. Ensuite si on essaye avec le multiple en dessous :

23-32

Cela n'est pas possible car 32 est supérieur à 23, notre nombre binaire est de 10. Essayons avec la puissance en dessous :

23-16=7

Notre nombre binaire est de 101.

7-8

Pas possible, 8 est plus grand que 7. Donc en binaire on a 1010.

7-4=3

En binaire 10101.

3-2=1

En binaire 101011.

1-1=0

En binaire 1010111.

Maintenant, quelques conversions pour vous entraîner, remplissez le tableau ci dessous :

-

Décimal

Binaire

Expression 1

?

1011

Expression 2

?

10011001

Expression 3

?

1111

Expression 4

15

?

Expression 5

128

?

La correction :
Pour l'expression 1, on a 4 chiffres binaires. On met tout ça dans notre tableau :

2^3

2^2

2^1

2^0

-

1

0

1

1

-

*8

*4

*2

*1

-

1*8

+0*4

+1*2

+1*1

=11

Dans l'expression 2, on a 8 chiffres binaires. Pareil qu'au dessus :

2^7

2^6

2^5

2^4

2^3

2^2

2^1

2^0

-

1

0

0

1

1

0

0

1

-

*128

*64

*32

*16

*8

*4

*2

*1

-

1*128

+0*64

+0*32

+1*16

+1*8

+0*4

+0*2

+1*1

=153

Dans l’expression 3, vous pouviez faire de nouveau un tableau, mais il y a d'autres méthodes plus simples. On calcule facilement que 10000 en binaire est égale à 16 en décimal (2^4). Donc 16-1=15, on peut donc dire que 1111=15.

Si vous aviez trouvé l'expression 3, vous n'avez sûrement rien eu à calculer pour l'expression 4, car on a vu que 1111=15.

L'expression 5 est également très facile à trouver, 128 étant une puissance de 2, il fallait juste ne pas se tromper sur le nombre de zéro à rajouter :
128=10000000

Vous retrouverez d'autres façons de faire sur ce site (pour votre culture personnelle :) ).


Les Datas 1/2 L’hexadécimal

L’hexadécimal

Le binaire Une histoire d'octets

L’hexadécimal

Je ne ferai pas complètement le tour du sujet, mais seulement la partie qui nous intéresse autour de l'hexadécimal.

L’hexadécimal par rapport au décimal

L'hexadécimal est en fait la base 16. Seulement, il manque des chiffres pour arriver jusqu'à 16. On a donc utilisé des lettres, en l’occurrence ici les 6 premières lettres de l'alphabet :
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F,...

Puis on passe à l'emplacement suivant (comme dans toutes les bases) :
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20,..., A0,..., 100,..., A00, etc.

:o Mais que valent A, B, C, D, E et F ?

En décimal, ils valent respectivement : 10, 11, 12, 13, 14 et 15.
Un tableau s'impose :

En décimal

En hexadécimal

0

0

1

1

2

2

3

3

4

4

5

5

6

6

7

7

8

8

9

9

10

A

11

B

12

C

13

D

14

E

15

F

Et quand on arrive à F, on passe à 10 :

En décimal

En hexadécimal

15

F

16

10

17

11

18

12

19

13

20

14

21

15

...

...

25

19

26

1A

27

1B

28

1C

29

1D

30

1E

31

1F

32

20

Et ainsi de suite !

Je ne vais pas m'attarder plus sur la conversion de l'hexadécimal en décimal, je vous conseillerai juste de convertir l'hexadécimal en binaire, puis en décimal.

L’hexadécimal par rapport au binaire

La conversion de l'hexadécimal en binaire (et vice versa) est très simple ! Il vous suffit de connaître la tableau suivant :

hexadécimal

binaire

décimal

0

0000

0

1

0001

1

2

0010

2

3

0011

3

4

0100

4

5

0101

5

6

0110

6

7

0111

7

8

1000

8

9

1001

9

A

1010

10

B

1011

11

C

1100

12

D

1101

13

E

1110

14

F

1111

15

Vous devez connaître ce tableau ; prenez quelques minutes, heures s'il le faut pour apprendre ce tableau par cœur.

Mais ce tableau ne convertit que les 16 premiers chiffres (0 à 15), comment faire pour la suite ?

C'est là qu'il faut observer quelque chose d'important sur le tableau : lorsque l'on arrive à F en hexadécimal on arrive à 1111 en binaire. Il y a une relation qui fait qu'à ce moment les deux bases vont augmenter d'un emplacement. Je suis sûr que vous avez deviné la relation entre ces deux bases, non ? :euh:

Je vous aide un peu :
Parce que 16 est une puissance de 2 !

Et que peut-on en conclure ? o_O

On peut en conclure que 1 chiffre hexadécimal est égal à 4 chiffres binaires !
Donc, si vous connaissez le tableau plus haut par cœur, vous arriverez à convertir le nombre 1BF5A0 très rapidement :
0001 1011 1111 0101 1010 0000
Ou plus clairement :
1BF5A0000110111111010110100000

(Soit 1832352 en décimal)

De même, pour trouver la valeur hexadécimal de 010111011011101000110010 :
0101110110111010001100105DBA32

(Soit 6142514 en décimal)

En fait, pour comprendre la suite du cours, vous aurez besoin de convertir le binaire en hexadécimal (très souvent), et l’hexadécimal en décimal (peu souvent).


Le binaire Une histoire d'octets

Une histoire d'octets

L’hexadécimal Les Datas : de simples données

Une histoire d'octets

Revenons à nos octets, et particulièrement à la question "qu'est ce qu'un octet ?".
Un octet est composé de 8 bits. Un bit a deux valeurs possibles : 0 ou 1. (une impression de déjà vu ? :D )

Maintenant on assimile cela aux connaissances vues précédemment ; un bit est un chiffre binaire ; un octet est un nombre binaire de 8 chiffres maximum.

Petit exercice maintenant : déterminez la valeur maximale d'un octet en décimal.

Un indice :
11111111 en Binaire.

Réponse :
255 en décimal.

Ce nombre vous évoque des choses ?
Maintenant, calculez la valeur maximale de deux octets :

Un indice :
11111111 11111111 en Binaire.

Réponse :
65535 en décimal.

C'est maintenant que vous vous rappelez ; cette valeur est celle que l'on obtient quand on fait 0-1→A.
Cela signifie que votre variable est en fait composé de 2 octets.

Mais si un octet c'est 8 chiffres binaires, alors à quoi va servir l’hexadécimal ?

Rappelez vous, 1 chiffre hexadécimal vaut 4 chiffres binaires. On pourra donc écrire un octet sous forme de 2 caractères hexadécimaux. :)

Il y a un truc que je ne comprends pas : avec les chaînes de caractères on arrive pourtant à enregistrer des lettres dans un octet, comment est-ce possible ?

En gros chaque lettre correspond à un nombre, et lors de l'affichage, la calculatrice va convertir ce nombre en lettre. Mais patience, cela fera l'objet d'un prochain chapitre. :ange:


L’hexadécimal Les Datas : de simples données

Les Datas : de simples données

Une histoire d'octets Les Datas 2/2

Les Datas : de simples données

Maintenant que vous connaissez vos octets sur le bout des doigts, vous allez pouvoir étudier ce qu'il retourne des Datas. :-°

Une liste de données

La commande Data( va créer une liste de valeurs que l'on utilisera pendant le programme. Chaque valeur sera en fait stockée dans un octet, et vous l'aurez deviné, on assimilera tout cela avec des pointeurs :

:Data(42,12,13,7)→GDB1

Quand on fait cela, le pointeur statique GDB1 va pointer l'octet contenant la valeur 42, et comme pour les chaînes de caractères, le reste des valeurs se place à la suite de cet octet.

Comment peut-on lire ces valeurs ?

Pour manipuler un seul octet à partir d'une adresse, il faut utiliser les accolades :

:{GDB1}

En fait, {GDB1} se manipule comme une variable d'un octet, sa valeur est toujours comprise entre 0 et 255.

En effet, si vous ne pouvez pas changer la valeur d'un pointeur statique, vous pouvez changer la valeur de l'octet pointé :

:Data(42,12,13,7)→GDB1
:Disp {GDB1}►Dec
:.Affiche 42
:1→{GDB1}
:Disp {GDB1}►Dec
:.Affiche 1

Et amusons nous à passer d'un octet à un autre :D :

:Data(42,12,13,7)→GDB1
:Disp {GDB1+2}►Dec
:.Affiche 13
:{GDB1}+{GDB1+1}→A
:.42+12=54
:Disp A►Dec
:.Affiche 54

Ce tableau devrait vous rappeler quelque chose :

Valeur stockée dans l'octet

Adresse contenant la lettre

42

1200

12

1201

l3

1202

7

1203

Transformer de l'hexadécimal en Data

Maintenant, nous allons transformer des chiffres hexadécimaux en Data. Cela n'a rien de compliqué ; c'est même fait pour. ;)

Toute data hexadécimale doit se mettre entre crochets :

:[2A0C0D07]→GDB1
:For(Z,0,3)
:Disp {GDB1+Z}►Dec
:End

Comme dit plus haut, deux caractères hexadécimaux valent un octet, il faut donc lire les datas ci dessus de la manière suivante :
2A ; 0C ; 0D ; 07
Mais maintenant vous savez trouver (très rapidement :-° ) le résultat en décimal :
42 ; 12 ; 13 ; 7

Je pense que vous savez ce qu'il vous reste à faire : pratiquer dès maintenant. :)

Bien sûr cette partie n'est qu'un avant goût de ce qui vous attend au prochain chapitre ; je vous demanderais de ne pas cliquer sur suivant tant que vous ne vous êtes pas entraîné sur la création et la manipulation des datas vus dans ce chapitre, c'est nécessaire pour pouvoir suivre le chapitre suivant ! :pirate:


Une histoire d'octets Les Datas 2/2

Les Datas 2/2

Les Datas : de simples données Mon premier sprite

Pour faire un bon programme, il ne faut surtout pas négliger les graphismes ; nous verrons dans ce chapitre comment approfondir l'utilisation des Datas, notamment avec la découverte de nouvelles notions : les sprites et les tiles, puis le tilemapping.

Mon premier sprite

Les Datas 2/2 Le tilemapping

Mon premier sprite

Avec toutes les connaissances que vous avez vues dans les chapitres précédents, nous allons continuer d'explorer l'univers des datas ; en commençant par les sprites et les tiles.

:euh: Qu'est ce qu'un sprite ou une tile?

En Axe, les sprites et les tiles sont des images 8*8 pixels que l'on peut manipuler pour faire un personnages ou des décors.

La théorie

Pour créer un sprite, il faut vous munir d'un éditeur de sprite : autrement dit juste de quoi dessiner. ;)
Vous pouvez donc prendre une feuille et un crayon ou dans mon cas j'utilise paint (il existe des éditeurs de sprites sur calculatrice également).
Le principe est simple : créer une feuille de dessin de 8*8 pixels :

Pxl

1

2

3

4

5

6

7

8

1

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

2

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

3

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

4

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

5

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

6

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

7

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

8

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

Dans mon cas, je vais dessiner une émoticône souriante :) en noir et blanc

Image utilisateur

:

Pxl

1

2

3

4

5

6

7

8

1

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

2

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

3

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

4

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

5

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur

6

Image utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateurImage utilisateur