Je vais dans ce tutorial vous expliquer comment marche mon moteur de lumière. Il n'y a pas d'images, que du texte et des choses à retenir, mais ce n'est pas si compliqué que ça, et au final, cela vaut le coup ^^ Il y a tout ce qu'il faut pour comprendre le contionnement et les différentes fonctions, je suis entrain de rédiger un deuxième tutorial sur l'optimisation de vos jeux en relations avec ce moteur. Il viendra d'ici la mi-décembre.
Fonctionnement :
Il y a trois choses à avoir :
- un objet qui s'occupe de l'affichage générale des lumières : le
buffer.
- Un objet qui fait de la lumière.
- Un objet qui fait de l'ombre à la lumière (un occluder)
En fait, chaque lumière calcule (si elle est rafraichie) les ombres des objets à portée du rayon de la lumière, puis le résultat est stocké dans le buffer, avec toutes les autres lumières.
Il faut savoir que le moteur est prévu pour calculer la lumière apparraissant dans la view0, et ce n'est pas modifiable. Il faut donc obligatoirement utiliser la view0.
Pas à pas :
1) Création du buffer. Il s'agit donc de l'objet qui va stocker les lumières/ombres et qui va faire l'affichage final. Il est préférable de faire un objet qui s'occupera uniquement du buffer du système de lumière. Lors de la création du buffer (pas forcément au début de la room, mais c'est mieux et ça consomme pas grand chose), il faut appeler l'instruction :
("code"):
il faut ensuite mettre le script scr_oel_buffer_end_step.. dans end step. Ce script n' pas d'arguments, mais il faut en changer le contenu. Vous trouverez des lignes du type :
with(obj_light...) {if ....}
Il faut rajouter votre propre couple de lignes pour chaque objet lumière! par exemple, si une de vos lumières s'appelle obj_lumiere_rose, il faudra avoir ces lignes :
with(obj_lumiere_rose) {...}
Seul le nom change, le reste est pareil. Il faut bien entendu supprimer les lignes mises par défaut, elles correspondent aux objets lumière de l'exemple, mais si vous n'avez pas d'objets de ce nom faisant de la lumière, il faut les supprimer.
Il reste la dernière fonction du buffer, et la plus importante : l'affichage avec la fonction
("code"): scr_oel_buffer_draw(shadow,alpha) |
On le met bien sur dans l'event draw du buffer, et les arguments sont les suivants : shadow : si vous mettez 0, la pièce est éclairée par défaut, et les lumières éblouiront par dessus. Mis à 1, la pièce est noire et seul les lumières éclaireront. Il n'est donc par défaut pas possible d'éblouir lorsque vous êtes en mode 'nuit'. On pourra, mais on vera ça plus tard.
Le second argument, est la transparence des lumières, et des lumières seulement : pas de l'ombre! Cela permet de régler l'intensité des lumières, c'est toujours pratique.
2) Création d'une lumière
Deuxième élément : la lumière. Il est possible d'utiliser bien sûr la lumière dans un objet déjà prévu pour autre chose, mais pour se simplifier la vie et pour une meilleure clarté, il vaut là encore mieux prendre un objet rien que pour votre lumière.
Dans le create event, il faut mettre :
("code"): scr_oel_light_create(radius,color,sat,OLD,spot,spot_angle) |
radius : rayon (et pas diamètre!) de la lumière : à la distance radius du centre, il
n'y a plus de lumière. color : simplement la couleur de votre lumière. Si elle est noire, elle n'est pas
affichée. sat : nombre de surimpression de la lumière dans le buffer. laisser ce paramètre à 0. OLD : ancien paramètre obsolète, laisser à 0 ou false. spot : valeur booléene : true/false : si la lumière est un spot (true) ou une lumière
classique et ronde (false) spot_angle : à rentre de toute façon, mais si la lumière est un spot, cette valeur
définit la moitié de l'angle : c'est l'angle entre la direction du spot et un rayon extrème.
exemple d'une lumière orange classique de diamètre 100 :
("code"): scr_oel_light_create(50,c_orange,0,0,0,0); |
exemple d'un spot vert de longueur 64 et d'angle total de 25° :
("code"): scr_oel_light_create(64,c_green,0,0,true,12.5); |
Dans le begin step event, il faut mettre :
("code"): scr_oel_light_begin_step() |
Sans se poser de question :p
Autres scripts :
("code"): Script ULTRA IMPORTANT : C'est lui qui met la lumière à
jour, par rapport aux différentes ombres à calculer pour cette lumière. par défaut, il faut simplement le mettre
dans begin step, mais plein d'optimisations sont possibles, je le détail plus loin dans ce tutorial.
("code"):
C'est ce script qui permet d'éblouir si on est en 'mode nuit' : il permet de réafficher la lumière, sans tenir compte du buffer, il s'agit d'un affichage de surface classique.
2) Création d'une polygone
Il reste un élément à voir, et pas des moindres : les polygones, c'est à dire des formes quelquonques qui bloquent la lumière. Tout objet/instance peut posséder son lot de vertices (au moins deux), et c'est le polygone formé par les vertices qui s'occupera de bloquer la lumière. Bref, le sprite n'influe pas sur la lumière : seul le polygone (non visible) qui se trouve sur l'objet définit le passage (ou non) de la lumière. Point important : tout objet ayant un polygone d'ombre DOIT être parenté à un objet nommé obj_wall, qui lui ne doit qu'exister, c'est tout. Tout d'abord, il faut initialiser les poygones, dans le create de l'objet. (Regardez le script, c'est risible). scr_oel_vertex_init();
Puis, toujours dans create, mettre tous les vertices (les sommets du polygones) , l'un après l'autre DANS L'ORDRE OÙ IL SE SUIVENT, avec la commande : scr_oel_vertex_add(X,Y); on se place dans le même repère que le sprite : donc un vertex un (0,0) sera sur les coordonnées de l'objet (en x,y quoi). Les coordonnées sont donc relatives à l'objet. Point important : il faut remettre le premier point à la fin pour fermer le polygone! Par exemple un carré donnera :
("code"): scr_oel_vertex_add(0,0); scr_oel_vertex_add(0,32); scr_oel_vertex_add(32,32); scr_oel_vertex_add(32,0); scr_oel_vertex_add(0,0); |
Il existe des scripts déjà faits pour faire des carrés et rectangles :
("code"): scr_oel_pref_carre(size); scr_oel_pref_rectangle(width,height); |
C'est un raccourci qui peux se révéler pratique.
Les polygones, c'est bien. Mais c'est impossible de faire des polygones corrects pour un cercle. Pour cela, il faut un objet SANS POLYGONES (ou en tout cas ils ne servent à rien), qui est parenté à un obj_circle. Votre objet doit avoir un sprite, dont la largeur correspondra au diamètre du cercle. Et voilà, vous avez une belle ombre sur un cercle, qui n'utilise qu'une paire de vertices, soit pas grand chose.
Il existe des fonctions auxilliaires sur les polygones :
("code"): scr_oel_vertex_projection(); |
Je ne vous conseille pas d'y toucher, il est utilisé par les autres scripts mais ne sert strictement à rien sinon.
("code"): scr_oel_vertex_draw(x,y,col); |
Permet de dessiner le contour du polygone de l'objet en x,y avec la couleur col. Cela permet surtout de faire des tests et de débugger votre jeu, rien de plus.
("code"): scr_oel_vertex_rotate(rotation_type,angle,x,y); |
Cette fonction est un peu spéciale, et est à utiliser avec précaution.
type de rotation : 0 : le centre de rotation sera l'origine du sprite_index 1 : le centre de rotation sera le centre du sprite 2 : le centre de rotation sera (0,0) 3 : le centre de rotation sera ce que vous avez précisez en arguments x et y
Les angles DOIVENT etres positifs, ils sont en direction directe, et en degrés (0-360) Donc pour faire -15, il faut faire +(360-15) soit +345 /! La rotation modifie DEFINITIVEMENT les vertices, ce n'est pas temporaire, il faut donc retenir précieusement où l'on en est dans la rotation si on veut revenir en place.
Soyez prudents, cette fonction est un peu buggée : le polygone se déplace doucement, car la rotation n'est pas parfaite. N'utilisez la rotation que si nécessaire.
("code"): scr_oel_ask_inview(view); |
Ce script retourne si la lumière executant le script est dans la room sélectionnée ou non. La fonction prend en compte le radius de la lumière.
("code"): scr_oel_view_get_speed(); |
Suite à des problèmes de décallages, il est nécessaire de se soucier de la vitesse de la view pour afficher le buffer au bon endroit. C'est cette fonction qui s' occupe de retourner la vitesse de la view. Ce script est utilisé par le système, vous n'en avez normalement pas l'utilité.
Voilà, nous sommes arrivés au bout du tutoriel. |