Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox



Imaging lingo - Economiser les overlay pour une jauge de vie

Compatible Director MX2004. Cliquer pour en savoir plus sur les compatibilités.Par glurp (Elliot Coene), le 02 décembre 2009

jauge_imaging.jpg

On a souvent tendance à multiplier les couches à tout va, surtout sous Director où les sprites sont tellement simple à utiliser. Mais dans un soucis d'optimisation, ou parce que les couches se font trop nombreuses, il est parfois intéressant de fusionner les éléments 2D.

C'est d'autant plus vrai pour les background et overlay 3D, dont la gestion n'est pas la plus aisée et peut provoquer des ralentissements désagréables. C'est pourquoi dans ce tutorial, nous allons prendre l'exemple concret d'un monde 3D qui nécessiterait une “jauge de vie” avec un fond, une barre modulable et un avant plan.

Ces 3 éléments vont devoir être mixés en un seul via Imaging Lingo tout en gérant leurs différents canaux de couleur (y compris l'alpha (transparence)), puis appliqué à un seul overlay.

Qu'est-ce que l'imaging lingo

En deux mots ce sont un lot de fonctions permettant de manipuler les images bitmap et leurs pixels. La fonction que nous allons le plus utiliser est copyPixels() qui permet de copier une zone d'une image sur une autre.

Pour info, copyPixels() fonctionne comme ceci :
imageDestination.copyPixels(imageSource, rectangleDestination, rectangleSource)

Il existe un 4ème paramètre qui est en fait une liste de paramètres, mais nous n'allons pas l'utiliser dans ce tutorial.

Pour en savoir plus sur copyPixels() :
Dictionnaire Lingo - copyPixels()

Petit rappel de shockwave 3D

Sans rentrer dans les détails, un fichier w3d est un “monde” (j'utiliserai la variable global gWorld pour le stocker) qui contient tout un tas de choses ; les models, les shaders, les textures, les animations, les lumières et les cameras.

Un overlay est une “couche 2D” face caméra positionnée en avant plan de la scène 3D (comme si nous mettions un “sprite” par dessus).

Mais sous shockwave 3D, tout élément 2D est contenu dans une texture. Nous devrons donc en créer une contenant l'image avant de la placer sur l'overlay.

Ainsi, nous avons un monde, qui contient une camera, qui contient un overlay, qui contient une texture (vous suivez toujours la logique ? :) )

Pour commencer

Préparez votre cast avec les 3 images nécessaires :
- Le fond de la jauge que j'appelle “fond”
- La jauge de vie proprement dite que j'appelle “vie”
- L'avant plan de la jauge que j'appelle “avant” (avec canal alpha)

Attention : dans cette exemple, j'ai respecté le format en puissance de 2 avec des images de 256*128. Lorsque l'on travaille en 3D, il faut toujours faire l'effort d'utiliser des images ou des découpes aux dimensions en puissance de 2 (si vous ne le faites pas, le résultat sera flou et le framerate pourra en pâtir, surtout en openGL)

Ensuite nous aurons besoin d'une scène 3D vide et un script de behavior “stop” contenant le code suivant :

on exitframe me
   go to the frame
end

Placez l'acteur 3d sur la timeline, disons de la frame 1 à la frame 20 et le script “stop” sur la frame 20 du sprite de script.

Dans le vif du sujet

Maintenant que votre fichier .dir est prêt, nous allons pouvoir coder le système de jauge de vie. Pour plus de facilité, nous allons en faire un objet (je vous invite à aller consulter le tutorial sur la programmation orientée objet). Créons donc un script parent que nous allons appeler “jauge_script” dans lequel nous allons la fonction init() qui crée l'image, la texture et l'overlay, ainsi que la fonction destroy() qui détruit tous ces éléments.

global gWorld
 
property pPercent, pTexture, pImage
 
on new me
 
  me.init()
 
  return me
 
end
 
on init me
 
  pPercent = 0
 
  tFondImg = member("fond").image
 
  -- Création de l image, de même dimension que le fond, sur 32 bits --
  pImage = image(tFondImg.width,tFondImg.height,32)
 
  -- Création de la texture : récipient pour notre image --
  pTexture = gWorld.newtexture("jauge", #fromImageObject, pImage)
  pTexture.quality = #high
  pTexture.renderFormat = #rgba8888
 
  tLoc = point(10,10)
 
  -- Création de l overlay --
  gWorld.camera[1].addoverlay(pTexture, tLoc, 0)
 
end
 
on destroy me
 
  pImage = void
 
  gWorld.deletetexture(pTexture.name)
  gWorld.camera[1].removeOverlay(1)
 
end

Il ne manque plus que la fonction de mise à jour de la texture en fonction du pourcentage. Nous l'appelerons updateLevel() et prendra un argument tPercent qui sera la différence à appliquer au pourcentage actuel.

on updateLevel me, tPercent
 
  -- Calcul du pourcentage --
  pPercent = pPercent + tPercent
  if pPercent < 0 then 
    pPercent = 0 
  else if pPercent > 100 then 
    pPercent = 100
  end if
 
  -- Colle l'image de fond sur l'image --
  tFondImg = member("fond").image
  pImage.copypixels(tFondImg, pImage.rect, pImage.rect)
 
  -- Colle une partie de l'image de la vie sur l'image --
  tVieImg = member("vie").image
  tRectDest = pImage.rect
  tRectDest[3] = tRectDest[3] * (float(pPercent)/100)
  pImage.copypixels(tVieImg, tRectDest, tRectDest)
 
  -- Colle l'avant plan sur l'image --
  tAvantImg = member("avant").image
  pImage.copypixels(tAvantImg, pImage.rect, pImage.rect)
 
  -- Applique la nouvelle image à la texture --
  pTexture.image = pImage
 
end

Nous pouvons désormais faire appel à cet fonction à la fin de notre init() pour initialiser l'affichage et le pourcentage à 100. L'appel s'écrit comme suit :

me.updateLevel(100)

Si vous lancez l'application à ce moment vous ne verrez pas grand chose. En effet, nous avons créé l'objet, mais nous ne l'avons pas encore instancié. Il est donc nécessaire de créer un script de Movie que nous appellerons “global” et qui comprendra le code suivant :

global gWorld, maJauge
 
on prepareMovie
 
  gWorld = member("scene")  
  maJauge = script("jauge_script").new()
 
end
 
on stopmovie
  maJauge.destroy()
  maJauge = void
 
  gWorld.resetWorld()  
  gWorld = void
end

Désormais, vous pouvez voir que l'application fonctionne et que la jauge est bien affichée.
Mais pour se familiariser avec notre jauge, nous allons ajouter à notre script de Movie quelques éléments de contrôle avec les flèches du clavier comme suit :

on keyUp
 
  if the keycode = 123 then
    -- flèche gauche --
    maJauge.updateLevel(-1)
  else if the keycode = 124 then
    -- flèche droite --
    maJauge.updateLevel(1)
  else if the keycode = 126 then
    -- flèche haut --
    maJauge.updateLevel(-5)
  else if the keycode = 125 then
    -- flèche bas --
    maJauge.updateLevel(5)
  end if
 
end

Voilà, votre jauge est terminée et contrôlable.
L'imaging lingo est un outils puissant et rapide, il peut donc être appelé fréquemment (enterframe, exitframe,…) libre à vous de lui faire faire les choses les plus tordues.

A noter que vous pouvez modifier le canal alpha presque aussi facilement que les autres canaux avec setalpha().

En 3D, l'imaging lingo est très utile car il permet aussi de se délier du format d'image en puissance de 2 (il faut alors subdiviser une image en autant de parties que nécessaires).

Sources Director MX 2004 :