 
 
 
 Animation
L'animation d'un graphisme à l'écran reprend des techniques de dessins
animés. La majeure partie du dessin ne change pas, seule la partie
animée doit modifier la couleur des pixels qui la compose. Un des
problèmes immédiatement rencontré provient de la vitesse
d'animation. Celle-ci peut varier selon la complexité du calcul et la
vitesse d'exécution du processeur. Ainsi une application graphique
animée pour être portable et donner le même effet doit tenir compte de
la rapidité du processeur. Pour avoir un rendu fluide il est
préférable d'afficher la nouvelle position de l'objet animé, puis
d'effacer l'ancienne, en tenant compte de leur intersection.
 Déplacement d'un objet
Nous simplifions le problème du déplacement d'un objet en choisissant 
des objets de forme simple que sont les rectangles. La difficulté restante 
est de savoir réafficher le fond d'écran une fois l'objet déplacé.
On cherche à faire
évoluer un rectangle dans un espace clos. L'objet se
déplace selon une vitesse en X et Y, quand il rencontre un bord de la
fenêtre graphique, il rebondit selon son angle d'incidence. On se
place dans une situation sans recouvrement entre la nouvelle et
l'ancienne position de l'objet. La fonction calc_pv calcule,
à partir d'une position (x,y), de la taille de l'objet
(sx,sy) et d'une vitesse (dx,dy), la
nouvelle position et la nouvelle vitesse. Cette dernière tient
compte des bords de la fenêtre.
# let calc_pv (x,y) (sx,sy) (dx,dy) = 
   let nx1 = x+dx     and  ny1 = y + dy
   and nx2 = x+sx+dx  and  ny2 = y+sy+dy
   and ndx = ref dx   and  ndy = ref dy 
   in  
     ( if (nx1 < 0) || (nx2 >= Graphics.size_x()) then ndx := -dx ) ;
     ( if (ny1 < 0) || (ny2 >= Graphics.size_y()) then ndy := -dy ) ;
     ((x+ !ndx, y+ !ndy), (!ndx, !ndy)) ;;
val calc_pv :
  int * int -> int * int -> int * int -> (int * int) * (int * int) = <fun>
La fonction roule_fond déplace n fois le rectangle
donné par pos et taille selon la trajectoire
indiquée par sa vitesse vit en tenant compte des bords comme
décrit par la fonction ci-dessus. La trace du déplacement que l'on
obtient sur la figure 5.7 est obtenue par inversion du
bitmap correspondant au rectangle déplacé.
# let  roule_fond pos taille vit n =
   let (x, y) = pos and (sx,sy) = taille in
   let mem = ref (Graphics.get_image x y sx sy) in 
   let rec roule_aux  x y vit n =
    if n = 0 then Graphics.moveto x y
    else 
     let ((nx,ny),n_vit) = calc_pv (x,y) (sx,sy) vit 
     and old_mem = !mem in 
      mem := Graphics.get_image nx ny sx sy ;
      Graphics.set_color Graphics.blue;
      Graphics.fill_rect nx ny sx sy;
      Graphics.draw_image (inv_image old_mem) x y;
      roule_aux nx ny n_vit (n-1)
   in roule_aux x y vit n ;;
val roule_fond : int * int -> int * int -> int * int -> int -> unit = <fun>
Le code suivant correspond aux dessins de la figure 5.7. Le
premier est obtenu sur fond uniformément rouge, le second, en
déplaçant le rectangle sur l'image de Jussieu.
# let anim_rect () = 
   Graphics.moveto 105 120 ;
   Graphics.set_color Graphics.white;
   Graphics.draw_string "Début" ;
   roule_fond (140,120) (8,8) (8,4) 150 ;
   let (x,y) = Graphics.current_point() in 
    Graphics.moveto (x+13) y ;
   Graphics.set_color Graphics.white;
   Graphics.draw_string "Fin" ;;
val anim_rect : unit -> unit = <fun>
# anim_rect();;
- : unit = ()
Figure 5.7 : Code du déplacement d'un objet
Le problème a été simplifié dans la mesure où il n'y a pas
d'intersection entre deux positions successives de l'objet
déplacé. Si tel n'est pas le cas, il faut écrire une fonction de
calcul de cette intersection qui est plus ou moins compliquée selon la
forme de l'objet. Dans le cas présent d'un carré, l'intersection de
deux carrés donne un rectangle. C'est celui-ci qu'il faut alors
effacer.
 
 
