[Solarus] Afficher une image semi-transparente au-dessus de la map

Démarré par Christopho, 22 Avril 2013 à 16:00

0 Membres et 1 Invité sur ce sujet

22 Avril 2013 à 16:00 Dernière édition: 22 Avril 2013 à 23:02 par Christopho
Comment appliquer un masque sombre sur la map pour faire un effet de nuit ?
Ou plus généralement, afficher sur la map une surface semi-transparente de n'importe quelle couleur, ou même provenant d'une image PNG.

Voir la documentation des surfaces pour plus de détails : http://www.solarus-games.org/doc/1.0.0/lua_api_surface.html

Créer d'abord une surface pour votre masque une seule fois pour toutes les maps (dans game:on_started() par exemple):

game:on_started()
 ...
 night_overlay = sol.surface.create(320, 240)  -- Créer une surface vide de 320x240 pixels appelée night_overlay.
 night_overlay:set_opacity(192)  -- La rendre partiellement transparente.
 night_overlay:fill_color({0, 0, 64})  -- La remplir en bleu foncé pour un effet de nuit.
end


La surface de nuit est créée, il ne reste plus qu'à l'afficher à l'écran lorsque la map est redessinée, c'est-à-dire dans map:on_draw().
Il faut définir ce map:on_draw() à chaque fois qu'une nouvelle map est démarrée. Autrement dit, dans l'évènement game:on_map_changed() :

function game:on_map_changed(map)
 function map:on_draw(destination_surface)
   night_overlay:draw(destination_surface)
 end
end

Et voilà !

Remarque : si vous dessinez la surface dans game:on_draw() au lieu de map:on_draw(), alors l'effet de nuit s'appliquera au-dessus de votre HUD, du menu de pause et de la boîte de dialogue. Ce n'est probablement pas ce que vous voulez :P

Remarque 2 : Pour afficher une image provenant d'un fichier au lieu d'une image unie, remplacez juste sol.surface.create(320, 240) par sol.surface.create("chemin/vers/un_fichier.png").
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus

Le tutoriel est assez clair :P, je pense que tu devrais préciser où trouver le game::on_started() et le map::on_started(), parce que je pense que ceux qui vont s'initier dans le futur vont être perdu xD

22 Avril 2013 à 16:20 #2 Dernière édition: 22 Avril 2013 à 16:23 par Christopho
Très bon tuto que je vais notamment utiliser pour faire un effet forêt :)

Citation de: MetalZelda le 22 Avril 2013 à 16:17
Le tutoriel est assez clair :P, je pense que tu devrais préciser où trouver le game::on_started() et le map::on_started(), parce que je pense que ceux qui vont s'initier dans le futur vont être perdu xD
Effectivement, ce tuto part du principe que le lecteur connaît les bases du scripting Lua avec le moteur Solarus, a déjà scripté quelques maps, etc. Je ferai d'autres tutos d'introduction pour ces bases :)
En attendant il y a la doc de référence très (trop) complète : www.solarus-games.org/doc/1.0.0/lua_api.html
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus

Citation de: Christopho le 22 Avril 2013 à 16:25
Citation de: MetalZelda le 22 Avril 2013 à 16:17
Le tutoriel est assez clair :P, je pense que tu devrais préciser où trouver le game::on_started() et le map::on_started(), parce que je pense que ceux qui vont s'initier dans le futur vont être perdu xD
Effectivement, ce tuto part du principe que le lecteur connaît les bases du scripting Lua avec le moteur Solarus, a déjà scripté quelques maps, etc. Je ferai d'autres tutos d'introduction pour ces bases :)
En attendant il y a la doc de référence très (trop) complète : www.solarus-games.org/doc/1.0.0/lua_api.html
Moi ce que j'aime bien avec ce moteur ... C'est que déjà il est bien conçu et aussi qu'il possède une documentation pour bien se repérer ... Chose que très peu de moteur ont ...

C'est gentil ^^. L'API de référence est en effet complète désormais. En complément, il reste à faire un guide de l'utilisateur, c'est-à-dire une sorte de grand tuto en plusieurs parties avec des exemples.

J'ai aussi envie de faire des tutos d'intro sur youtube où je montre comment créer un petit jeu tout en expliquant.
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus

Je note deux belles erreurs dans ce tuto.

La première pour cette ligne:
night_overlay:fill_color{{0, 0, 64}}
Il faut mettre plutot  night_overlay:fill_color{0, 0, 64}

La seconde c'est qu'il y adeux fonctions embarquées. Ca sert strictement à rien il me semble.
A la place de
Citation
function game:on_map_changed(map)
  function map:on_draw(destination_surface)
    night_overlay:draw(destination_surface)
  end
end
Il faut mettre :

Citation
  function map:on_draw(destination_surface)
    night_overlay:draw(destination_surface)
  end

Merci pour le retour. Je viens de corriger la première erreur qui en était bien une. Le bon code est
night_overlay:fill_color({0, 0, 64}).
Comme les parenthèses sont optionnelles dans certains cas, on peut aussi écrire night_overlay:fill_color{0, 0, 64}. Mais je recommande de toujours mettre les parenthèses quand on appelle une fonction, plutôt que de se demander quand elles sont optionnelles ou pas.

Par contre pour la deuxième, ta version marche pour une map individuelle. Selon ton cas, c'est peut-être ce que tu veux :)
Mon exemple affiche l'overlay sur toutes les maps. Mon code est équivalent à

function game:on_map_changed(map)
  map.on_draw = function(map, destination_surface)
    night_overlay:draw(destination_surface)
  end
end

C'est-à-dire qu'à chaque fois que la map change, tu crées une nouvelle fonction on_draw sur la nouvelle map.
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus

Dans le cas d'une image (contenant ou non de la transparence), y a-t-il une possibilité de la faire bouger ? Je prends l'exemple de nuages, il peut être intéressant de montrer un certain mouvement de ces nuages, car des nuages fixes ça fait pas forcément super beau. Dans le même genre d'idée, peut-on faire une image qui scrolle à une vitesse différente de l'écran ? Genre si je ne m'abuse dans les Bois Perdus de la version ALTTP, l'ombrage ne se déplace pas aussi vite que l'écran, ce qui rend un effet de hauteur assez intéressant.

Deux petites questions purement par curiosité :)


23 Avril 2013 à 11:28 #9 Dernière édition: 23 Avril 2013 à 13:23 par Christopho
Oui.

1) Pour délacer l'image, il suffit de créer un mouvement et de l'attacher à la surface :

local m = sol.movement.create("straight")  -- Créer un mouvement rectiligne.
m:set_speed(16) -- 16 pixels par seconde.
m:set_angle(math.pi / 4)  -- Direction nord-est.
m:set_max_distance(200)  -- Arrêter le mouvement au bout de 200 pixels parcourus.
m:start(night_overlay, function()
 m:set_speed(16)
 m:set_angle(2 * math.pi - m:get_angle())  -- Demi-tour une fois le mouvement terminé.
end)

Je n'ai pas testé mais quelque chose dans ce genre doit fonctionner. Il faut bien sûr que l'image soit plus grande que l'écran si vous voulez la bouger.

2) Pour faire défiler l'image non pas automatiquement, mais en même temps que l'écran, avec une autre vitesse de défilement, on peut spécifier à quelles coordonnés on l'affiche à l'écran (par défaut, c'est 0,0) :

night_overlay:draw(destination_surface, x, y)

La façon de déterminer x et y est laissée en exercice pour le lecteur :ninja:
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus

Je pense que pour le système jour nuit je vais le retranscrire en LUA, sa serais nettement plus beau d'avoir des transitions progressives sur l'écran ^^ je vais déjà utilisé ce qui à ici mais je vais me mettre au travail dessus :p

Sinon, tu devrais faire un tutoriel sur l'éditeur de map de Solarus, j'ai pas vu beaucoup de tuto dessus et je pense que bon nombre de ceux qui prendrons Solarus comme moteur seront un peu perdus (Notament dans la prog. des tilesets et des entities :P)

Je me rends compte que le callback de ce script (pour un mouvement straight) ne fonctionne pas.

m:start(night_overlay, function()
  m:set_speed(16)
  m:set_angle(2 * math.pi - m:get_angle())  -- Demi-tour une fois le mouvement terminé.
end)


Il ne va jamais dans la fonctionne.:)

Si le mouvement a bien une fin (c'est le cas si tu as fait le set_max_distance), le callback du mouvement devrait être appelé. Sinon c'est un bug, peux-tu le poster sur le bug tracker sur github stp ? Merci
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus


Pour info si quelqu'un repasse par là : j'ai corrigé le bug il y a un bon moment, il n'est plus présent dans la 1.0.
https://github.com/christopho/solarus/issues/165
Chaîne Twitch : diffusion en direct de sessions de développement de Solarus, de création de jeux, de parties de jeux vidéo.
Chaîne YouTube : replays des diffusions en direct, tutos Solarus
Compte Twitter : pour être au courant des nouveautés
Chat Discord : pour discuter en direct avec la communauté Solarus