IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API standards et tierces Java Discussion :

[Exception]Double buffering & NullPointerException


Sujet :

API standards et tierces Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut [Exception]Double buffering & NullPointerException
    J'avais posté à propos d'un problème de scrolling, ça été résolu avec le double buffering. c'était ici :
    http://www.developpez.net/forums/viewtopic.php?t=218987

    Mais depuis l'appel à update(g) provoque une NullPointerException, qqs secondes après le démarrage du programme (qui affiche juste un écran).

    J'avais cette erreur qd je faisais repaint() pour rien, mais même en les enlevant, ça fait l'erreur (qui ne stoppe pas le prog).

    J'ai fait comme ça :

    Dans la classe Jeu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private Image backbuffer = null;
    private Graphics backg = null;
    Dans le construteur Jeu() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    backbuffer = createImage(largeur, hauteur);
    backg = backbuffer.getGraphics();
    backg.setColor(Color.black);
     
    afficheEcranTitre(backg);
    Dans afficheEcranTitre(backg), je dessine dans backg.
    Et à la fin je fais un repaint();

    Et c'est la-dedans que l'exception apparaît :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public void paint(Graphics g) {
    	update(g);          // bug après qqs secondes
    }
     
    public void update(Graphics g) {
    	g.drawImage(backbuffer, 0, 0, this);
    }

    L'exception complète :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    java.lang.NullPointerException
    	at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
    	at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
    	at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
    	at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
    	at Jeu.update(Jeu.java:146)
    	at Jeu.paint(Jeu.java:139)
    	at sun.awt.RepaintArea.paint(Unknown Source)
    	at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    	at java.awt.Component.dispatchEventImpl(Unknown Source)
    	at java.awt.Container.dispatchEventImpl(Unknown Source)
    	at java.awt.Window.dispatchEventImpl(Unknown Source)
    	at java.awt.Component.dispatchEvent(Unknown Source)
    	at java.awt.EventQueue.dispatchEvent(Unknown Source)
    	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.run(Unknown Source)

    merci

  2. #2
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2003
    Messages : 69
    Points : 59
    Points
    59
    Par défaut
    C'est ton contexte graphique bakg qui génère un NullPointerException parce qu'il n'existe pas !

    Il faut utiliser la méthode createGraphics(); :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    /**
     * Crée le contexte graphique
     */
    private void initializeBackBuffer(){
    backBuffer = new      BufferedImage(this.FRAME_WIDTH,this.FRAME_HEIGHT,BufferedImage.TYPE_INT_ARGB);
    backg =  backBuffer.createGraphics();
    }
    A noter que dans cet exemple, FRAME_WIDTH et FRAME_HEIGHT ne sont pas des constantes prédéfinies...
    Pascal

  3. #3
    Membre actif
    Avatar de narkotik
    Inscrit en
    Mai 2004
    Messages
    117
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 117
    Points : 229
    Points
    229
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void paint(Graphics g) { 
       update(g);          // bug après qqs secondes 
    }
    deja on appelle jamais la méthode update() directement, c'est java qui s'en charge lorsqu'on appelle repaint()

    pour le reste la solution a été posté précédemment par Pascmar
    (+mitch): nan mais nanar j'préfère mourir contre un platane apres un accident de voiture plutot que d'une rupture d'anévrisme devant mon ecran d'pc

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Merci !

    J'ai changé ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private Image backBuffer = null;
    backBuffer = createImage(largeur, hauteur);
    backg = backBuffer.getGraphics();
    En ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private BufferedImage backBuffer = null;
    backBuffer = new BufferedImage(largeur, hauteur, BufferedImage.TYPE_INT_ARGB); 
    backg = backBuffer.createGraphics();
    La seule chose qui a changé c'est la fluidité : c'est bcp moins bien avec une BufferedImage... Donc j'ai remis une Image.

    Mais j'ai supprimé la redéfinition de paint() qui appelle update(g) : là ça marche ! Il n'y a plus d'erreur, ouf !


    Au fait, j'ai pas très bien compris le rôle de paint, repaint et update... Quand on ne les redéfinit pas, elles font quoi ?

  5. #5
    Membre actif
    Avatar de narkotik
    Inscrit en
    Mai 2004
    Messages
    117
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 117
    Points : 229
    Points
    229
    Par défaut
    c'est moins bien avec ta bufferedImage car tu l'as mis en ARGB hors Java ne met pas directement d'accelération sur une bufferedImage avec une couche Alpha
    fais la passer en transparency.OPAQUE tu vas voir la différence
    carrément mieux qu'avec une image

    si tu définis paint() tu peux afficher ce que tu veux sur ton objet
    si tu définis update() tu peux gerer le nettoyer de ton objet
    la méthode repaint() est comprise dans java pour faire passer les graphismes par pipelines

    l'affichage d'un objet se déroule ainsi:

    paint() // initialisation de la partie graphique de ton objet
    repaint() // appelle de la mise a jour de l'affichage
    repaint()
    repaint()
    etc.......

    repaint() appelle => update()
    ce qui donne réellement a l'écran:
    paint()
    update()
    update()
    update()
    etc......

    heureusement update() est redéfinissable et on peut rappeler paint() pour limiter le clignottement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void update(Graphics g)
    {
            paint( g );
    }
    ce qui fait:
    repaint() appelle => update() -> paint()
    ce qui donne réellement à l'écran:
    paint()
    update()
    paint()
    update()
    paint()
    etc......

    voila j'espere avoir été assez simple car c'est pas la partie la plus facile de java a comprendre étant donné que c'est implicite à chaque objet graphique.
    (+mitch): nan mais nanar j'préfère mourir contre un platane apres un accident de voiture plutot que d'une rupture d'anévrisme devant mon ecran d'pc

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Ahhhhhhhh c'était donc ça le "A" de ARGB !! thanx

    J'ai remis la BufferedImage, mais en RGB. En effet, c'est mieux ! Peut-être même mieux qu'une Image, mais là c'est à cause de mon code que je ne voit pas trop la différence : je redessine à chaque keyPressed, je pense plutôt lancer le scrolling sur un keyPressed et l'arrêter sur un keyReleased, comme ça je ne dépendrai plus de la vitesse max du clavier qd on laisse appuyée une touche. Enfin, je pense, je dois essayer !

    Petit à petit, ça avance...

    Merci aussi pour tes explications sur paint et cie, je vais relire ça, faut le temps de digérer ! lol

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2003
    Messages : 69
    Points : 59
    Points
    59
    Par défaut
    je ne sais pas exactement l'usage que tu va faire de ton code, mais quoi qu'il en soit, il est toujours plus avantageux d'utiliser une BufferedImage pour ce genre de problèmes car son contenu peut provenir de plusieurs threads chargés de dessiner différents éléments à intervalles réguliers à l'aide de backg passé en paramètre par exemple => le contenu de l'image doit être modifiable => BufferedImage...
    Pascal

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Je veux faire un jeu de rôle (plein écran).

    Merci du conseil. Justement, ça me fait penser à une autre question... Si je veux faire une scène nocturne à partir d'images de jour, c'est mieux de modifier à chaque frame la BufferedImage (baisse de luminosité + filtre bleu foncé) ou bien de mettre carrément par dessus une image bleue très foncée en transparence ?

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2003
    Messages : 69
    Points : 59
    Points
    59
    Par défaut
    bonne question, je sais pas vraiment, essaies les deux options et regardes laquelle est la plus rapide. Mais la manière la plus juste conceptuellement et peut-être de créer un nouveau thread de dessin qui va se charger de dessiner par dessus un rectangle bleu en transparence variable. Cependant attention, dès que tu manies plusieurs threads qui ont accès aux mêmes données en même temps, il faut être sûr de l'ordre dans lequel les actions se produisent : si le thread "de nuit" dessine son rectangle avant celui qui dessine le reste de l'image, on n'y voit rien. Les méthodes sychronisées sont plus lentes, il est peut-être judicieux de gérer manuellement l'état du thread de dessin (dessine - ne dessine pas) avec un boolean interne modifiable par la classe qui se charge de l'affichage final et qui donne la main au thread voulu au moment voulu...
    Pascal

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Ok. Bon, avant de m'attaquer aux threads, je dois me documenter ! Je plongerai dans le code après...


    En fait, mon projet est assez vieux, j'avais commencé fin 2001... Et jusqu'à qqs semaines, je le faisais en... JavaScript !!! lol ! (je ne savais faire que du html à mes débuts...) D'ailleurs j'ai été surpris d'aller aussi loin, ça ressemblait presque à un vrai jeu... Et là j'ai une révélation : il faut que je le fasse en Java ! Et je viens encore de trouver un énorme avantage à ça : plus besoin de découper mes lieux en plein de petites images ! Je viens de tester avec tout un village, une big image 1920*3136 pixels ! Et le tout défile parfaitement à l'écran... impressionnant ! Je l'ai d'abord mis en gif : 1.75 Mo... Puis j'ai essayé le png : 993 Ko !! youpi !!! Et en plus, la qualité est meilleure, en gif je perdais des couleurs...

    Question au passage : en gif, on est limité à 256 couleurs... En png, que je ne connais pas du tout, pas de limite ?? ce sont les couleurs exactes ?

  11. #11
    Membre actif
    Avatar de narkotik
    Inscrit en
    Mai 2004
    Messages
    117
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 117
    Points : 229
    Points
    229
    Par défaut
    BufferedImage (baisse de luminosité + filtre bleu foncé) ou bien de mettre carrément par dessus une image bleue très foncée en transparence ?
    tu affiches ta bufferedImage
    tu passes en transparence style 0.8f
    tu passes en couleur noire
    tu mets un fillRect(x, x, x, x)

    une big image 1920*3136 pixels
    j'serais curieux de voir le nombre de FPS

    J'ai remis la BufferedImage, mais en RGB. En effet, c'est mieux ! Peut-être même mieux qu'une Image
    c'est normal beaucoup de programmeurs de jeu sur Java se plaignent que l'ajout de la couche Alpha des bufferedImage ne permet pu de bénéficier de l'accélération graphique
    heureusement y'a des solus, les p'tits gars de Sun ont laissé ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            System.setProperty("sun.java2d.translaccel", "true");
            System.setProperty("sun.java2d.accthreshold", "0");
    sur windows ca permet de passer par les pipelines de directX et sur linux, solaris de passer par ceux de DGA

    je redessine à chaque keyPressed, je pense plutôt lancer le scrolling sur un keyPressed et l'arrêter sur un keyReleased, comme ça je ne dépendrai plus de la vitesse max du clavier qd on laisse appuyée une touche
    pas bonne idée, redessine en permanence à l'aide d'un timer(un Thread) qui rappelle tout l'temps ta fonction repaint()

    si t'as d'autres questions, j'suis dans l'coin
    bonne chance
    (+mitch): nan mais nanar j'préfère mourir contre un platane apres un accident de voiture plutot que d'une rupture d'anévrisme devant mon ecran d'pc

  12. #12
    Membre confirmé
    Avatar de Glob
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Avril 2002
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Avril 2002
    Messages : 428
    Points : 630
    Points
    630
    Par défaut
    En vrac, mon expérience dans le Java2D... ce fut une tentative de voir si un jeu de plateforme à la Mario serait difficile à réaliser.

    keywords: 2D, vue latérale, tiles de 32x32, déplacement d'un "sprite" à coup de flèches haut bas gauche droite, scrolling.

    Je me suis fait un "monde" d'environ 20'000 x 10'000 px, en dessinant à chaque fois toutes les tiles (optimisations niveau 0)... et bien ça scroll super fluide.

    J'avais désactivé les appels update/repaint (que je gérais donc) et je n'avais qu'un seul thread, celui qu'on arrive dedans avec le main() .
    Principe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    init()
    while(not quit) {
      mesureTempsEcouléDepuisDernièreBoucle
      traiteTouches()
      bougeObjets/événementsDuMonde // (en fonction du temps écoulé)
      dessineMonde()
      dessineObjets()
      attendre10ms() // pour éviter un CPU à 100%, pas très élégant :mrgreen:
    }
    Voilà...
    Ma question: pourquoi, systématiquement, vouloir faire des thread dans tous les coins? Je prétends qu'on peut faire un jeu sans faire de new Thread()...

    Pour améliorer la gestion des événements utilisateurs, les touches mettent un flag à true/false selon qu'elles sont pressées ou pas. Ensuite, ces flags sont lus dans la boucle principale.

    Bref...
    Glob
    What would you do if you were not afraid?

    Cours et tutoriels pour apprendre Java , FAQ Java, et Forum Java

  13. #13
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2003
    Messages : 69
    Points : 59
    Points
    59
    Par défaut
    ben lorsque tu as des ennemis qui ont des mouvements indépendants du personnage pricncipal, t'es obligé d'avoir un thread pour chacun puis un thread principal pour gérer ces sous-threads qui dessinent chacun un élément indépendant dans le backbuffer. Le coup du KeyPressed, ça marche seulement si ton personnage est seul au monde...

    De plus, ta façon de prendre le thread du main et de le faire tourner à l'infini : C'est franchement deg
    Pascal

  14. #14
    Membre actif
    Avatar de narkotik
    Inscrit en
    Mai 2004
    Messages
    117
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 117
    Points : 229
    Points
    229
    Par défaut
    bon bon, 2-3 explications:

    De plus, ta façon de prendre le thread du main et de le faire tourner à l'infini : C'est franchement deg
    faux, pour le thread principal il faut le faire tourner a l'infini avec une condition d'arret, un boolean pause par exemple

    En vrac, mon expérience dans le Java2D... ce fut une tentative de voir si un jeu de plateforme à la Mario serait difficile à réaliser.
    intéressant, j'aimerais savoir comment tu as codé la physique du moteur, par exemple la maniere dont il saute et retombe, les collisions

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    init() 
    while(not quit) { 
      mesureTempsEcouléDepuisDernièreBoucle 
      traiteTouches() 
      bougeObjets/événementsDuMonde // (en fonction du temps écoulé) 
      dessineMonde() 
      dessineObjets() 
      attendre10ms() // pour éviter un CPU à 100%, pas très élégant :mrgreen: 
    }
    loin de moi l'idée de vouloir critiquer, mais ce thread, je suppose que sa vitesse de rafraichissement (10ms ici) c'est pour les mouvements du héros, ok, mais les ennemis, et autres éléments du monde, ils sont calqués sur le meme système de mouvements ??? honnetement je doute

    J'avais désactivé les appels update/repaint (que je gérais donc)
    bien

    attendre10ms() // pour éviter un CPU à 100%, pas très élégant
    ah bah, et mon thread avec yield et setPriority(Thread.MIN_PRIORITY); c'est fait pour quoi a ton avis ?

    Pour améliorer la gestion des événements utilisateurs, les touches mettent un flag à true/false selon qu'elles sont pressées ou pas. Ensuite, ces flags sont lus dans la boucle principale.
    oui !!!!!!!!! ca il faut le faire c'est trop trop utile lol

    Ma question: pourquoi, systématiquement, vouloir faire des thread dans tous les coins? Je prétends qu'on peut faire un jeu sans faire de new Thread()...
    le minimum pour un jeu a mon avis c'est 1 thread, celui du rafraichissement graphique (FPS), les autres qui dirigent le monde peuvent etre seulement des compteurs de temps ou l'utilisation de GageTimer (dll très très utilisées car précise et efficace)

    Je me suis fait un "monde" d'environ 20'000 x 10'000 px, en dessinant à chaque fois toutes les tiles (optimisations niveau 0)... et bien ça scroll super fluide.
    sur un p'tit pc, il doit souffrir, faut utiliser un systeme de viewport afin d'économiser un maximum la mémoire utilisée
    (+mitch): nan mais nanar j'préfère mourir contre un platane apres un accident de voiture plutot que d'une rupture d'anévrisme devant mon ecran d'pc

  15. #15
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2003
    Messages : 69
    Points : 59
    Points
    59
    Par défaut
    ben moi je prétend que c'est faux de vouloir faire tourner le thread du main à l'infini. Le thread du main doit lancer un thread de dessin principal qui lui boucle à l'infini avec une condition d'arrêt. Cela permet au thread du main de garder le contrôle suprême sur l'exécution du programme. En tout cas à mon avis cette méthode est bien plus propre...
    Pascal

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Très intéressant tout ça... Je vais essayer de placer le dessin dans un thread. A la fin du dessin, je dois faire wait(20) ? J'avais essayé mais ça ne marchait pas : je crois que c parce qu'il n'y avait pas de thread...

  17. #17
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Glop : on peut le télécharger ton Mario ? (ou par mail...) Je serais curieux de voir ça !

  18. #18
    Membre du Club
    Inscrit en
    Mars 2004
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 58
    Points : 49
    Points
    49
    Par défaut
    Essayes ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try {
    	Thread.sleep(20);
    } catch (InterruptedException e) {
    	e.printStackTrace();
    }

  19. #19
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Merci miel_pops, je vais essayer.

  20. #20
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 43
    Points : 25
    Points
    25
    Par défaut
    Cool, il n'y a plus d'erreur maintent ! Mais ça ne fait pas ce que je veux... c'est normal, code à revoir, c pas fini !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Dessin]Double Buffering + Components
    Par Higestromm dans le forum 2D
    Réponses: 1
    Dernier message: 04/07/2005, 15h11
  2. [GDI+] Double buffer
    Par sebbb dans le forum MFC
    Réponses: 3
    Dernier message: 24/05/2005, 15h19
  3. [MFC] Scinttillement vs Double buffering
    Par DamessS dans le forum MFC
    Réponses: 9
    Dernier message: 07/04/2005, 09h01
  4. Réponses: 1
    Dernier message: 04/04/2005, 11h19
  5. Réponses: 7
    Dernier message: 03/08/2004, 16h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo