/** disquesDessinA.java Animer des boules; affichage double tampon Dans une 'image' affichage standard Dans une autre, dessin dans un tampon image, puis affichage (redéfinition de update(Graphics g) et double buffering) Un thread pour déplacer les boules (class DisquesAnimes) Un thread pour dessiner (class Dessiner) Récupération de paramètre depuis la page html http://java.developpez.com/sources/?page=AWT */ // Les classes dans ce fichier: // public class DisquesDessinA extends Frame // class Dessiner extends Thread // class DisquesAnimes extends Thread // class UnDisque // import javax.swing.*; import java.applet.Applet; import java.awt.Panel; // pour contexte graphique des tracés import java.awt.Graphics; // pour contexte graphique des tracés import java.awt.Dimension; // pour dimension de la zone à effacer import java.awt.Component; // pour la surface de dessin import java.awt.Color; import java.awt.Image; // pour tampon caché import java.awt.event.*; // public class DisquesDessinA extends Applet { static final int ROTATION=1, REFLEXION=2, DROITE=3; static final int NDD=200; // nombre de disques par défaut static final int RAYON=20; static final int PIXPARSEC=70; // pixels par secondes int xMax=300, yMax=300; // taille de la fenêtre static final int REBOND=REFLEXION; DisquesAnimes dd; // les disques qui bougent int ATTENTEDISQUE=100; // déplacer les disques chaque 100 ms. int ATTENTEDESSIN=30; // redessiner chaque 60 millisecondes boolean avecTampon; // double buffering String txt; Image imCachée; Graphics cgTampon; public DisquesDessinA() { } public void init() { // paramètre: avec ou sans tampon String ch_par=getParameter("tampon"); if(ch_par == null) avecTampon=true; else avecTampon = ch_par.equals("avec"); // paramètre: nombre de disques et texte affiché int ndd=NDD; ch_par=getParameter("disques"); if(ch_par!=null) try{ndd=Integer.parseInt(ch_par);} catch(Exception e){}; if(avecTampon) txt=" AVEC TAMPON ("+ndd+" disques)"; else txt=" SANS TAMPON ("+ndd+" disques)"; dd = new DisquesAnimes(ndd,ATTENTEDISQUE); dd.start(); Dessiner d = new Dessiner(this,ATTENTEDESSIN); d.start(); } public void start() { } public void paint(Graphics cg) { Dimension d=this.getSize(); if(avecTampon) { // technique tampon caché (double buffering) if(cgTampon==null) { // Au premier affichage uniquement imCachée = createImage(d.width,d.height); cgTampon = imCachée.getGraphics(); } cgTampon.clearRect(0,0,d.width,d.height); cgTampon.setColor(Color.black); cgTampon.drawString( txt, 10, 45); dd.dessiner(cgTampon); cg.drawImage(imCachée,0,0,null); // affichage effectif } else { // technique standard cg.clearRect(0,0,d.width,d.height); cg.setColor(Color.black); cg.drawString( txt, 10, 45); dd.dessiner(cg); } } public void update(Graphics g) {paint(g);} /** Renvoie un entier entre 0 et max-1 (pratique pour l'aspect aléatoire) */ static int unEntier(int max) { return (int)(max*Math.random()); } // public static void main(String mots[]) { // DisquesDessin fen=new DisquesDessin(NBD,100,100,false); // DisquesDessin fen2=new DisquesDessin(NBD,100,400,true); // } // classe interne (un seul objet de cette classe) /** Pour afficher (classe interne: un seul objet de cette classe) */ class Dessiner extends Thread { int attenteDessin=30; Component sd; Dessiner(Component c, int a) { sd=c;attenteDessin=a;} public void run() { while(true) { sd.repaint(); try { sleep(attenteDessin); } catch (Exception e) { System.out.println(" "+ e); } } } } /** Déplacements d'un groupe de disques; méthode dessiner (classe interne) */ class DisquesAnimes extends Thread { UnDisque td[]; int attenteDisque; DisquesAnimes (int n, int a) { attenteDisque=a; td = new UnDisque[n]; for(int i=0; i<td.length; i++) td[i]=new UnDisque(attenteDisque); } public void run() { while(true) { // déplacer les disque se tles redessiner(); for(int i=0; i<td.length; i++) td[i].déplacer(); try { sleep(attenteDisque); } catch (Exception e) { System.out.println(" "+ e); } } } void dessiner(Graphics cg) { for(int i=0; i<td.length; i++) td[i].dessiner(cg); } } //fin class DisquesAnimes /** Création aléatoire, déplacement, rebond et dessin d'un disque (classe interne) */ class UnDisque { int xC,yC, rayon; // abscisse, ordonnée du centre int dX,dY; // vitesses de déplacement sur les axes int angle; // en degré Color couleur; int vitesse; UnDisque(int attente) { // Position de départ du centre du disque xC=xMax/2; yC=yMax/2; // Couleur couleur = new Color(16*unEntier(16),16*unEntier(16),16*unEntier(16)); // Rayon (moyenne: RAYON) rayon= (RAYON+2*unEntier(2*RAYON))/3; angle = unEntier(360); // Vitesse vitesse = PIXPARSEC+unEntier(PIXPARSEC); // Déplacement par 'attente' milliseconde dX = (int)(vitesse*Math.cos(angle*Math.PI/180.0)/1000*attente); if(dX==0) dX++; dY = (int)(vitesse*Math.sin(angle*Math.PI/180.0)/1000*attente); if(dY==0) dY--; } void déplacer() { xC+=dX; yC+=dY; if (xC-rayon<=0 ) rebondir(1); else if(xC+rayon >= xMax) rebondir(2); else if(yC-rayon <= 0 ) rebondir(3); else if(yC+rayon >= yMax) rebondir(4); } // modifier delta void rebondir(int r) { int dx=dX; switch(REBOND) { case ROTATION: // rotation 90° if(r==1) // par la gauche if(dY>0) { dX=dY; dY=-dx;} else {dX=-dY; dY=dx; } else if(r==2) // par la droite if(dY>0) {dX=-dY; dY=dx; } else { dX=dY; dY=-dx;} else if(r==3) // par le haut if(dX>0) {dX=-dY; dY=dx; } else { dX=dY; dY=-dx; } else if(r==4) // par le bas if(dX>0) { dX=dY; dY=-dx; } else { dX=-dY; dY=dx; } break; case REFLEXION: // réflexxion standard // System.out.println(""+xC+","+yC+" "+dX+","+dY); if(r==1 || r==2) {// par la gauche ou la droite dX=-dX; } else if(r==3 || r==4) { // par le haut ou le bas dY=-dY; yC=yC+(7-2*r); } break; case DROITE: // en restant sur la même droite dX=-dX; dY=-dY; break; } } void dessiner(Graphics cg) { cg.setColor(couleur); cg.fillOval(xC-rayon,yC-rayon,2*rayon,2*rayon); } } //fin class UnDisque } //fin DisquesDessinA.java