Exercice pratique : le PONG

Utilisez la souris pour placer la raquette.

Autres exercices AS3
Informations

Voici un petit exercice pour apprendre à faire un Pong, à l’attention des débutants. Ne vous attendez pas à un tutorial décrit pas à pas, le but d’un exercice étant que le lecteur fasse l’effort de la compréhension avec toutefois des explications de base.

- Les sources sont disponibles à la fin de l’exercice.
- Retrouvez ce tutoriel sur le Wiki de Mediabox

Partagez
Etude préliminaire

Tout d’abord le PONG c’est quoi ? (merci Wikipedia)

Pong est un jeu vidéo inspiré du "tennis de table" développé par Ralph Baer et son équipe à Sanders Associates en 1967. Après y avoir joué lors d’une première démonstration en mai 1972, Nolan Bushnell, créateur de la société Atari, en fait une version améliorée : Pong. Puisque le nom Ping-Pong est déjà une marque déposée, ils l’ont simplement appelé Pong. C’est le premier jeu vidéo à connaître un succès populaire, mais la forme la plus ancienne d’un jeu électronique de ping-pong remonte à un jeu jouable sur un oscilloscope, créé par William A. Higinbotham au laboratoire national de Brookhaven en 1958. Son jeu était intitulé "Tennis for Two".

Le concept original de Pong est une simulation simpliste de tennis de table (ping-pong). Au tennis de table, les joueurs se tiennent de chaque côté d’une table et manient une raquette pour frapper une petite balle qui se déplace entre eux dans les deux sens. Une petite balle, se déplace à travers l’écran, rebondissant sur les rebords du haut et du bas, et les deux joueurs commandent chacun une raquette, la faisant glisser verticalement entre les extrémités de l’écran à l’aide des contrôles. Si la balle frappe la raquette, elle rebondit vers l’autre joueur. Si elle manque la raquette, l’autre joueur marque un point. La balle rebondit de différentes manières selon la façon dont elle touche la raquette.

Pong peut être joué seul, la raquette opposée est alors commandée par la machine ; ou à deux joueurs, chacun commandant une raquette. Sur les bornes d’arcade la raquette est habituellement commandée par un bouton rotatif (un paddle), répondant avec une vitesse variable selon la façon dont le joueur la tourne.

Son code ultra simple est à la portée de tous, mais cache également, si l’on gratte un peu la surface, des astuces spécifiques à la réalisation de jeux vidéo, c’est pourquoi tout apprenti développeur de jeu DOIT commencer par essayer de créer un simple PONG avant de tenter de placer la barre plus haut.

Mais créer un PONG est à la portée de tous avec un peu de patience, alors ce qui va nous intéresser ici c’est comment le créer en une soixantaine de lignes de code, un bloc compact où il y a peu à manger, mais du concentré qu’il faudra prendre son temps pour digérer.

Les pré-requis

Pour prendre en main ce programme vous devez connaître :

Variables et types : http://help.adobe.com/fr_FR/FlashPl...
Fonctions et paramètres : http://help.adobe.com/fr_FR/FlashPl...
Ecouteurs d’événements : http://help.adobe.com/fr_FR/FlashPl...

Si vous souhaitez plus de précisions sur ces points, je vous encourage à parcourir le Wiki de Mediabox où vous trouverez de nombreux tutoriaux détaillés.

Le code

On commence par vous donner tout le code d’un coup, histoire que vous ayez une vue d’ensemble ?

Ping !

// objets
var terrain:Sprite = new Terrain();
var joueur:Sprite = new Raquette();
var ordi:Sprite = new Raquette();
var balle:Balle = new Balle();

// paramètres des objets
joueur.x = 15;
ordi.x = terrain.width-15;
ordi.y = joueur.y = terrain.height*.5;

// liste d'affichage
addChild(terrain);
addChild(joueur);
addChild(ordi);
addChild(balle);

// écouteurs
addEventListener(Event.ENTER_FRAME, main);

// initialisation
init();

// initialisation
function init():void{
        balle.x = balle.y = terrain.width*.5;
        balle.vX = (Math.random()<.5 ? 1 : -1)*(Math.random()*6+2);
        balle.vY = (Math.random()<.5 ? 1 : -1)*(Math.random()*6+2);
}

// boucle principale
function main(e:Event):void{
        joueur.y = mouseY;
        if (balle.y<ordi.y) ordi.y -= 5;
        if (balle.y>ordi.y) ordi.y += 5;
        limites(joueur);
        limites(ordi);
        with (balle) {       
                x += vX;
                y += vY;
                if (y<10) y=10,  vY*=-1;
                if (y>470) y=470, vY*=-1;
                if (x<10) terrain.scoreO.text = Number(terrain.scoreO.text)+1, init();
                if (x>470) terrain.scoreJ.text = Number(terrain.scoreJ.text)+1, init();
                if (balle.hitTestObject(joueur)) collision(joueur);
                if (balle.hitTestObject(ordi)) collision(ordi);
        }
}

// limites des raquettes
function limites(ob:Object):void{
        if (ob.y<40)  ob.y = 40;
        if (ob.y>440) ob.y = 440;
}

// collisions balle / raquettes
function collision(ob:Object):void{
        with (balle) {
                (ob==joueur) ? x=joueur.x+10 : x=ordi.x-10;
                vX *= -1;
                vY = -Math.round((ob.y-y)*.2);
        }
}

Pong !

Oui, c’est tout ;-) , on peut faire encore beaucoup moins long, mais on va essayer de rester compréhensible pour ce premier pas que nous effectuons ensemble.

Etude du programme

Pour alléger le code et concevoir le programme j’ai utilisé l’interface du logiciel Flash, elle me permet de créer facilement tous mes objets graphiques sans avoir à passer par le code. Avant de commencer à programmer j’ai donc créé un modèle de raquette (valable pour les deux joueurs), une balle, et un terrain divisé en deux camps. En dehors du terrain, je me suis débrouillé pour que le repère de position soit au centre de tous mes objets, ceci me fera gagner encore quelques lignes de code, vous verrez pourquoi par la suite.

Chaque modèle a un nom commençant par une majuscule, c’est une convention d’écriture. Il n’y a rien sur la scène de Flash, à part une image clé comprenant le code, tous les objets sont dans la Bibliothèque et exportés pour ActionScript, ce qui les transforme automatiquement en Classes, d’où le fait qu’on leur donne un nom commençant par une majuscule.

Jetons un oeil aux première lignes de code :

// objets
var terrain:Sprite = new Terrain();
var joueur:Sprite = new Raquette();
var ordi:Sprite = new Raquette();
var balle:Balle = new Balle();

Je commence par déclarer tous mes objets utiles au programme.

"Mais on ne viens pas de le faire ?"

Non, nous avons fabriqué des modèles, à partir desquels nous allons pouvoir créer autant d’occurrence que nous voulons. Vous noterez que j’ai volontairement utilisé des noms explicites pour les objets, ceci afin de mieux les discerner dans le programme.

// paramètres des objets
joueur.x = 15;
ordi.x = terrain.width-15;
ordi.y = joueur.y = terrain.height*.5;

Je place mes deux joueurs.

Faites attention à la rédaction du code, la position des deux joueurs sur l’axe vertical ( y ) est identique, je peux donc tout coller sur une seule ligne avec une suite d’égalités. Sur deux lignes ou une seule ça ne change rien pour le programme à ce niveau là, c’est juste plus court à écrire, c’est une forme d’écriture que vous serez souvent amenés à rencontrer.

"Pourquoi au lieu de diviser par deux tu multiple par 0.5 ?"

Parce que diviser un nombre demande plus d’étapes pour le processeur que de le multiplier, c’est donc plus rapide, ici ça n’a pas une grande importance, mais si vous cherchez l’optimisation maximum dans une grande série de calculs cela sera des plus utiles, alors autant l’apprendre tout de suite.

Si vous souhaitez plus d’informations sur la manière dont votre machine effectue une division ou une multiplication :

Division : http://en.wikipedia.org/wiki/Divisi...
Multiplication : http://en.wikipedia.org/wiki/Dadda_tree et http://en.wikipedia.org/wiki/Wallac...

"Et pourquoi tu marque .5 au lieu de 0.5 ?"

Parce que je n’aime pas écrire des choses inutiles, le zéro ne sert à rien, alors je ne m’en encombre pas, cela n’a absolument aucune incidence, que vous le mettiez ou non, par habitude je ne le mets plus, sans doute parce que je suis un peu maniaque vis à vis des choses inutiles ;-)

// liste d'affichage
addChild(terrain);
addChild(joueur);
addChild(ordi);
addChild(balle);

Là j’ajoute tous mes objets fraîchement démoulés à la liste d’affichage. Vous savez ce que c’est car c’est dans les pré-requis pour lire le programme, on ne va donc pas s’étendre dessus car nous n’allons faire aucune modification à cette liste.

// écouteurs
addEventListener(Event.ENTER_FRAME, main);

J’ajoute un écouteur d’événement, basé sur un ENTER_FRAME et qui appelle la fonction "main" à chaque frame. La gestion des événements fait aussi partie des pré-requis, on ne va donc pas la détailler, cependant je souhaite m’attarder un peu sur la gestion via un ENTER_FRAME. C’est important, car vous devez comprendre que l’événement ENTER_FRAME n’est pas fiable, avec cette instruction le programme essayes d’atteindre le nombre de rafraîchissement par seconde du projet, mais n’y arrive pas toujours pour différentes raisons comme la puissance utile pour faire tourner le jeu par exemple. Selon certains facteurs le nombre de rafraîchissement par seconde peut donc être fluctuant, cela n’a pas d’incidence réelle pour cet exercice, cependant vous noterez que lorsque la balle se déplace nous avons un effet de saute à certains moment, c’est la conséquence visible de la fluctuation du rafraîchissement. Pour éviter cela on utilise généralement une cadence basée sur le temps réel qui passe, et non sur la vitesse du projet, on enregistre le temps de départ au lancement du jeu, puis on regarde le temps passé depuis l’ouverture et on en déduit le taux de rafraîchissement réel, ce n’est pas beaucoup plus compliqué mais ça ajoute des lignes de code inutiles pour l’exercice.

// initialisation
init();

// initialisation
function init():void{
        balle.x = balle.y = terrain.width*.5;
        balle.vX = (Math.random()<.5 ? 1 : -1)*(Math.random()*6+2);
        balle.vY = (Math.random()<.5 ? 1 : -1)*(Math.random()*6+2);
}

Je lance en tout premier lieu une petite fonction d’initialisation, elle place la balle au centre de l’écran, et lui affecte deux paramètres vX et vY représentant une vitesse aléatoire sur chaque axe.

La première chose à retenir c’est qu’on peut attribuer des paramètres à des objets à la volée, ici par exemple je crée à mon goût deux paramètres qui représentent la vitesse propre à la balle sur chaque axe, je choisi de les nommer "vX" pour "vitesse sur l’axe x" et "vY" pour "vitesse sur l’axe y".

La seconde chose intéressante c’est la manière dont on attribue la vitesse sur chaque axe.

"(Math.random()<.5 ? 1 : -1) * (Math.random()*6+2)"

La première partie de l’instruction me permet déterminer un sens en tirant un chiffre aléatoirement correspondant à 1 ou -1.

(Math.random()<.5 ? 1 : -1)

NOTE : Merci à Lilive pour les éclaircissement sur la grosse erreur que j’avais faite ici. Dans le programme de départ j’utilisai un opérateur binaire, je trouvais le bon résultat mais sans comprendre réellement le fonctionnement de ce que j’avais mis en place, ça arrive et ça vous arrivera sans doute plus d’une fois. Du coup j’ai opté pour sa formule qui m’oblige à vous montrer un peu plus tôt que je ne l’avais prévu l’autre manière d’écrire un "if...else", avec un opérateur. Attention, je n’ai pas pris la peine de corriger les sources, vous y trouverez donc la formule de départ, ça marche très bien, mais je ne vais pas tenter de vous l’expliquer du coup ;-)

(Math.random()*6+2)

La seconde partie de l’instruction est la vitesse de la balle, elle me renvoie un nombre aléatoire compris entre 0 et 6, auquel j’ajoute 2 afin de ne jamais avoir une vitesse proche de zéro, ce qui serait embêtant car la balle ne se déplacerait alors plus ou très lentement. Le résultat obtenu est donc un chiffre aléatoire compris entre 2 et 8.

Au final, j’ai donc une formule qui me permet de trouver un sens aléatoire que je multiplie à une vitesse aléatoire (ayant un minimum) pour chaque axe.

Pang ! (ha non zut, ça c’est un autre jeu que nous découvrirons plus tard....)

// boucle principale
function main(e:Event):void{
        joueur.y = mouseY;
        if (balle.y<ordi.y) ordi.y -= 5;
        if (balle.y>ordi.y) ordi.y += 5;
        limites(joueur);
        limites(ordi);
        with (balle) {       
                x += vX;
                y += vY;
                if (y<10) y=10,  vY*=-1;
                if (y>470) y=470, vY*=-1;
                if (x<10) terrain.scoreO.text = Number(terrain.scoreO.text)+1, init();
                if (x>470) terrain.scoreJ.text = Number(terrain.scoreJ.text)+1, init();
                if (balle.hitTestObject(joueur)) collision(joueur);
                if (balle.hitTestObject(ordi)) collision(ordi);
        }
}

"Aieuuuuu .... !"

Cette fonction est exécutée à chaque frame du programme, soit approximativement 30 fois par seconde puisque c’est la vitesse à laquelle j’ai réglé mon projet, on va se l’étudier ligne par ligne.

joueur.y = mouseY;

La position de la raquette du joueur sur l’axe y est égale à la position de la souris sur ce même axe. Petite précision, les modèles de raquette et de la balle sont centrés graphiquement, c’est à dire que le repère de position du clip utilisé comme modèle se trouve au centre de l’objet, je devrai donc dire :

"Le centre de la raquette du joueur sur l’axe y est égale à la position de la souris sur le même axe."

Avoir centré mes objets au départ me permet d’éviter de calculer où se trouve le centre de cet objet par rapport à la souris, si je ne l’avait pas fait et donc conservé mon repère de position en haut à gauche de l’objet par défaut j’aurais du écrire :

joueur.y = mouseY-joueur.height*.5;

Puisque nous sommes dans l’environnement de Flash autant se servir des petites astuces à notre disposition pour alléger le code, mais sachez que sans ces outils nous aurions du préciser où se trouve le centre des objets.

if (balle.y<ordi.y) ordi.y -= 5;
if (balle.y>ordi.y) ordi.y += 5;

Avez-vous déjà entendu parler d’Intelligence Artificielle ? Voici celle de l’ordinateur dans PONG, son cerveau, très réduit, se résume à deux simples instructions, si la balle est au dessus de son centre sur y il monte de 5 pixels, si elle est en dessous il descend de 5 pixels et, ce n’est pas dit explicitement mais c’est la seule option possible, si elle est au centre il ne bouge pas.

"Attend, je comprend pas comment une IA parfaite peut perdre, l’ordinateur est imbattable ?"

Non, il suis certes la balle, mais à sa propre vitesse limitée à 5 pixels alors que la balle peut atteindre un maximum de 8. Une balle trop rapide sur l’axe y et l’ordinateur risque de ne pas suivre assez vite pour la récupérer à temps, c’est là que réside tout le principe du jeu, plus la vitesse de l’ordinateur sera proche de la vitesse maximum de la balle, plus il sera dur à battre, voire impossible si il est plus rapide que la balle.

Ces deux lignes en disent bien plus long que ce qu’elles ne montrent, ce qu’il faut comprendre c’est qu’il est souvent plus facile de créer une intelligence artificielle parfaite pour vos jeux, et de la limiter voire de la dégrader pour obtenir des comportements plus "humain". Bien sur cela s’applique essentiellement aux comportements basiques comme des gardes qui font une ronde ou le pilote d’une voiture sur un circuit, il n’est pas question de créer une IA capable de jouer aux échecs contre Kasparov.

limites(joueur);
limites(ordi);

Ici je restreint le déplacement des raquettes à la surface du terrain. Nous étudierons cette fonction plus tard, elle n’a pas grand intérêt.

with (balle) {       
        x += vX;
        y += vY;
        if (y<10)          y=10,  vY*=-1;
        if (y>470)         y=470, vY*=-1;
        if (x<10)         terrain.scoreO.text = Number(terrain.scoreO.text)+1, init();
        if (x>470)         terrain.scoreJ.text = Number(terrain.scoreJ.text)+1, init();
        if (balle.hitTestObject(joueur))  collision(joueur);
        if (balle.hitTestObject(ordi))          collision(ordi);
}

Par contre cette partie là nous intéresse particulièrement, c’est la gestion de la balle. A l’aide de l’instruction "with()" je spécifie au programme que je souhaite travailler avec l’objet "balle". Elle me permet d’ordonner au programme de regarder en priorité si une propriété que j’utilise existe dans l’objet concerné avant de chercher cette propriété d’une manière plus globale.

Pour faire simple elle permet de passer de ce type d’écriture :

balle.x += balle.vX;
balle.y += balle.vY;

A celui là :

with (balle) {       
        x += vX;
        y += vY;
}

Attention, on ne peut pas créer de nouvelle propriété à la volée dans une instruction "with()", on ne peut que s’en servir, elles doivent donc être créées avant, c’est le cas de "vX" et "vY" par exemple, que l’on à associé à la balle dans la fonction "init()"

if (y<10)   y=10,   vY*=-1;
if (y>470)  y=470,  vY*=-1;

Ici on force la balle à rebondir sur les murs du haut et du bas.
La vitesse pouvant varier, si la balle dépasse la limite du mur on la replace précisément devant le mur.
Puis on inverse la vitesse sur l’axe y.

"Attend, c’est quoi cette écriture bizarre ?"

Vous-vous souvenez ? Je suis un maniaque qui retire tous les trucs qu’il juge inutile dans un code et qui écrit parfois plusieurs instructions sur une même ligne. Et bien en voilà un bel exemple....

Normalement on écrirait ceci :

if (y<10)
{
        y = 10;
        vY *=  -1;
}
if (y>470)
{
        y = 470;
        vY *=  -1;
}

"Mais enfin, à quoi ça te sert de compresser les choses comme ça ?"

Quand votre code fait 300 lignes ça ne pose pas de réel souci, je trouve juste ça moche tous ces blocs et ces accolades qui servent à dire où commence le bloc et où il fini, je préfères écrire des phrases, je trouve ça plus harmonieux et avec un peu d’habitude c’est plus clair lors d’une lecture rapide. Lorsque votre programme atteint les 3000 lignes ça commence à faire une sacré différence, du coup quelques règles de mise en forme perso peuvent changer la donne si tant elle qu’elles soient strictes et justifiées. Là par exemple il n’y a qu’une condition et deux instructions simples, inutile de faire tenir ça sur 10 lignes là où 2 suffisent. Par contre il est impératif que la mise en forme de la phrase soit rigoureuse, chaque instruction est alignée avec celle du dessous afin de permettre la lecture en colonne. Prenons un exemple plus parlant :

Écriture classique :

if (A = 1)
{
        B = 10;
        C = 20;
        Y = 30;
}
if (A = 2)
{
        B = 10;
        C = 32;
        Y = 30;
}
if (A = 3)
{
        B = 11;
        C = 20;
        Y = 30;
}
if (A = 4)
{
        B = 10;
        C = 45;
        Y = 30;
}
if (A = 5)
{
        B = 01;
        C = 20;
        Y = 30;
}
if (A = 6)
{
        B = 10;
        C = 20;
        Y = 64;
}
if (A = 7)
{
        B = 52;
        C = 20;
        Y = 30;
}
if (A = 8)
{
        B = 10;
        C = 20;
        Y = 98;
}
if (A = 9)
{
        B = 10;
        C = 120;
        Y = 30;
}

Ecriture condensée :

if(A=1) B = 10,  C = 20,  Y = 30;
if(A=2) B = 10,  C = 32,  Y = 30;
if(A=3) B = 11,  C = 20,  Y = 30;
if(A=4) B = 10,  C = 45,  Y = 30;
if(A=5) B = 01,  C = 20,  Y = 30;
if(A=6) B = 10,  C = 20,  Y = 64;
if(A=7) B = 52,  C = 20,  Y = 30;
if(A=8) B = 10,  C = 20,  Y = 98;
if(A=9) B = 10,  C = 12,  Y = 30;

Sous forme de tableau je trouve que ça passe beaucoup mieux, j’ai tout le bloc de code sous les yeux, pas besoin de scroller pour trouver la valeur qui m’intéresse. J’ai pris des instructions simples mais ça pourrait être n’importe quoi d’autre ça marcherai aussi. Le but de ce petit exercice de mise en forme du code est de vous montrer que l’écriture d’un programme, bien que stricte, est également assez malléable pour permettre de l’organiser selon vos besoins. Si vous arrivez à vous affranchir des conventions de base et à lire votre code d’une manière plus abstraite vous gagnerez en lisibilité au prix d’un petit effort de concentration. Dans l’exemple proposé au dessus, la disposition du code en tableau (virtuel) le rend bien plus compact et plus lisible qu’une longue série de blocs entre accolades.

Voyons si vous avez saisi le truc :

if (x<10)  T.scoreO.text = Number(T.scoreO.text)+1,  init();
if (x>470) T.scoreJ.text = Number(T.scoreJ.text)+1,  init();

C’est là qu’on détermine qui gagne la partie, si la balle se trouve derrière un joueur, l’autre joueur gagne. A ce moment là on modifie le score, on replace la balle au centre et on lui donne une nouvelle direction (appel de la fonction "init()" ).

Parlons deux minutes du score. Dans le modèle du terrain, j’ai inséré deux champs texte dynamiques "scoreO" et "scoreJ" pour indiquer les scores de chaque joueur. Sachant que ces champs texte ne seront remplis qu’avec des nombres je peux me permettre de convertir leur contenu (une String) en un nombre (Number), de lui ajouter 1 et de le réafficher, inutile d’aller s’encombrer de variables supplémentaires, une petite conversion suffit.

if (balle.hitTestObject(joueur)) collision(joueur);
if (balle.hitTestObject(ordi))         collision(ordi);

Ici on regarde simplement si la balle touche une raquette. La réaction est expliquée dans la fonction collision qui suit.

// collisions balle / raquettes
function collision(ob:Object):void{
        with (balle) {
                (ob==joueur) ? x=joueur.x+10 : x=ordi.x-10;
                vX *= -1;
                vY = -Math.round((ob.y-y)*.2);
        }
}

Vous avez remarqué ?
On passe l’objet concerné par la collision avec la balle en paramètre de la fonction.
On va se débarrasser des trucs simples :

vX *= -1;

La balle change de direction sur l’axe x.

vY = -Math.round((ob.y-y)*.2);

La balle change de vitesse sur l’axe y.

Vous ne comprenez pas la formule ?
J’ai bien envie de vous laisser chercher un peu sur ce coup.
Sachez qu’elle permet de modifier la vitesse en fonction de l’endroit où la balle touche la raquette, plus on est loin du centre et plus elle prend de l’effet.

Et attaquons la dernière "monstruosité" du programme :

(ob==joueur) ? x=joueur.x+10 : x=ordi.x-10;

"Pfff ça devient du hiéroglyphe là !"

Pourtant c’est un simple opérateur dont vous pouvez trouver l’explication dans la doc.
C’est simplement une autre manière d’écrire un "if ... else".

Ce que ça dit ?

Si l’objet touché est le joueur, replace la balle devant sa raquette, sinon (c’est donc que c’est l’ordinateur) replace la balle devant la raquette de l’ordinateur. Une fois encore, vous pouvez alléger votre code en utilisant des opérateurs simples, au prix d’un petit effort de concentration certes, mais cela vous évite tout un tas de lignes inutiles.

Replacer la balle devant la raquette en cas de collision n’a pas qu’un avantage esthétique, cela évite également des bugs possibles lorsque votre balle touche la raquette sur un bord ou trop rapidement, selon sa vitesse, au rebond elle risquerai de se trouver encore en contact avec la raquette et donc de repartir dans l’autre sens. S’en suit généralement une boucle où la balle est bloquée entre deux positions interne de la raquette, ou une perte de la balle alors que le joueur l’a bien attrapée.

Pour éviter tout risque, on replace la balle devant la raquette avant de la faire rebondir.

Allez on termine avec le dernier petit bout de code :

// limites des raquettes
function limites(ob:Object):void{
        if (ob.y<40)  ob.y = 40;
        if (ob.y>440) ob.y = 440;
}

Rappelez-vous que nous restreignons le déplacement des raquettes aux limites du terrain, c’est ici que ça se passe. L’étude de ce petit bout de code n’a pas grand intérêt en soit, donc nous en avons terminé pour cet exercice.

Conclusion

PONG est un jeu très simple au programme vraiment accessible, c’est pourquoi j’ai profité de celui-ci pour vous parler un peu de la rédaction d’un code. Les libertés que j’ai prises ne sont bien évidemment pas une obligation. Cependant en réfléchissant un peu vous trouverez tout un tas d’astuces qui vous permettrons de réduire la taille de votre code sans perdre en lisibilité (voire en y gagnant selon les cas), si pour un programme comme PONG au code simpliste, cela n’a pas un intérêt flagrant, lorsque vous allez vous attaquer à des jeux plus gros cela va rapidement devenir indispensable, notez cependant qu’il vaut mieux toujours privilégier l’optimisation du programme à la compression du code, autrement dit ce n’est pas parce qu’un code est plus court que son fonctionnement est forcément plus optimisé.

Sources

Version Flash CS5.5

Zip - 8.8 ko