[TUTO]Une fenêtre de Zoom sur des tuiles de jeux de plateau

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

[TUTO]Une fenêtre de Zoom sur des tuiles de jeux de plateau

Message par kerkael »

compilable en PureDisk 4.20
Attention ! Avec le temps le compilateur a évolué, et il faudrait modifier le code pour être compilable au-delà de la 4.20.
Suivez ce topic pour voir comment faire cohabiter plusieurs versions du compilateur : http://www.purebasic.fr/french/viewtopi ... 21&t=13137


Tiens, je continue sur ma lancée alors que je développe petit à petit mon jeu de plateau avec interface graphique en PB.

Présentation du problème :
Après avoir scanné mes tuiles et cartes de jeux de plateau, elles sont plutôt illisibles pour en faire une version jouable, même en 1280x1024.

Idée 1 : Infobulle et GadgetToolTip
Très rapidement on remarquera que ces ToolTips sont indispensables mais ils ne peuvent pas remplacer un beau Zoom

Idée : Zoomer sur les différentes Images
Bon, comme j'ai cherché encore à droite et à gauche et posé des questions, on m'a dit de faire une recherche sur Zoom. Ca n'a rien donné. Alors peut-être que j'ai réinventé la roue, mais voilà ce que ça donne.
L'écran principal contient de petites images. Et quand on droit-clique sur l'une d'elles, on fait apparaître une fenêtre de zoom avec une meilleure résolution de cette image (en fait, avec une copie de l'image de plus grosse taille).
Le zoom se ferme quand on Droit-double-clique sur le Zoom.

Synopsis : 3 fichiers + toutes les images

Fichier1 : tutomain.pb fichier principal, sollicite tutoCommon.pb, fait tourner la boucle sur la fenêtre principale.

Fichier2 : tutoCommon.pb sollicité par tutomain.pb, fichier principal de définition des variables, structures, procédures utilisées dans la boucle principale - sollicite tutoData.pb

Fichier2 : tutoData.pb sollicité par tutoCommon.pb, contient l'énumération des divers champs des tuiles et cartes du jeu

Les Images : Comme détaillé dans tutoData.pb les images sont de 2 formats, dans 2 répertoires distincts, mais avec le même nom. Nous prendrons ici appui sur de petites images png de 87x87 et le zoom se fera sur des images de 250x250. Les dossiers à créer pour tester les 3 fichiers décrits ci-après seront minImages et maxImages.

minImages\cg1.png et minImages\ci1.png
Image Image

maxImages\cg1.png et maxImages\ci1.png
Image Image

Au fait, j'attends vos critiques, parce que je rouvre systématiquement la fenêtre de zoom et j'imagine qu'il doit pourtant être simple d'en rafraichir le contenu, mais ça ne changera pas beaucoup la philosophie de ce code.
Mais je préfèrerai quand même, parce que ça veut dire que la fenêtre de zoom revient toujours à son point d'apparition initial. Pas très bô.


.................... Code de 3 fichiers à venir
Dernière modification par kerkael le mer. 31/juil./2013 15:14, modifié 4 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

Message par kerkael »

Fichier 1/3 : tutomain.pb
;tutomain.pb
; fichier principal

;==============================
; Structures, Procédures, et Variables globales
IncludeFile "tutoCommon.pb"

;==============================
; Appel de la fenêtre principale utilisée lors de la boucle principale
; Cette procédure est définie dans projectCommon appelé juste avant
FenetrePrincipale()

;==============================
; Boucle principale avec gestion de quelques clics sur les gadgets (ici des images)
Repeat
  Event = waitwindowevent () ;Attendons un événement
   Select Event ;Selon l'événement survenu !!!
    Case #PB_Event_Gadget ;Cet événement est arrivé sur un Gadget
       Select eventgadget () ;Selon Le Gadget concerné ...
         Case #ImageZoom ;si le gadget touché est #ImageZoom, pas question de rezoomer sur le Zoom !!!
           If eventtype ()= #PB_EventType_RightDoubleClick ;du coup pour fermer le Zoom, Double-Clic Droit
             closewindow ( #FenetreZoom ) ;et Voilà où l'on ferme la fenêtre de Zoom ... mais quand l'a-t-on ouverte ?
           EndIf
          
         Default ;Dans tous les autres cas, on n'est pas sur le Zoom, alors que fait-on ?
          Select eventtype () ;Selon le type d'évenement ...
            Case #PB_EventType_LeftClick : Debug "Left Clic sur " + str ( eventgadget ()) ;Explicite, non ?
            Case #PB_EventType_RightClick : Debug "Right Clic sur " + str ( eventgadget ())
             FenetreZoom( eventgadget ()) ;C'est ici que s'ouvre la fenêtre de zoom, en cas de clic droit sur un gadget
                                         ;on fournit à la fenêtre appelée le numéro du gadget sur lequel on vient de droit-cliquer
            Case #PB_EventType_LeftDoubleClick : Debug "Double Left Clic sur " + str ( eventgadget ()) ; 2 autres types de clic
            Case #PB_EventType_RightDoubleClick : Debug "Double Right Clic sur " + str ( eventgadget ()) ;histoire de ne rien oublier
          EndSelect
       EndSelect
   EndSelect

Until Event = #PB_Event_CloseWindow ;sortie du programme dès que l'on ferme une fenêtre, probablement la principale, puisque celle du Zoom n'a pas de Menu
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

Message par kerkael »

Fichier 2/3 : tutoCommon.pb
;tutoCommon.pb
;included dans tutomain.pb

;==============================
; Toutes Data définissant les pièces, éléments, cartes, modules du plateau de jeu
IncludeFile "tutoData.pb"

Enumeration
   #Image0
   #Image1
   #ImageZoom
   #FenetrePrincipale
   #FenetreZoom
EndEnumeration

;==============================
; structure définissant les Modules, ou tuiles et cartes du plateau de jeu
Structure MODULE
  nom.s ;faire très attention à la nature des variables, qui devra être reprise dans la Datasection
  titre.s ;ici les 4 premières variables sont des textes, on poura les regrouper sur une seule Data.s
  minimagepath.s
  maximagepath.s
  minlargeur.l ;les 4 data Longues utilisées ici seront regroupables sur une seule ligne Data.l
  minhauteur.l
  maxlargeur.l
  maxhauteur.l ;ainsi 2 lignes seront suffisantes pour chaque Module
EndStructure

;===============================
; les tuiles sont de type MODULE, on en définit le nombre par la dimension du tableau
; C'est une variable globale parce qu'elle est définie et appelée depuis diverse structures et fichiers

Global Dim Tuile.MODULE(10)
Restore MesTuiles ;La fonction RESTORE va chercher MESTUILES dans la DATASECTION - ici ma DATASECTION se trouve appelée par INCLUDEFILE en début de fichier
   For i =0 To 1
     With Tuile(i) ;TUILE est un tableau de dimension 10
       Read \nom ;Toutes les champs de TUILE sont lus par READ depuis la DATASECTION
       Read \titre ;...et qu'il soient tous dans le bon ordre, parce que les READ sont dans le même ordre
       Read \minimagepath ;le chemin de l'image à l'exterieur de l'exe parce que les images ne seront pas incluses
        \minimagepath=\minimagepath + \nom + ".png" ;minimagepath est composé du chemin du dossier + nom de la tuile + .png
                                                     ;parce que c'est là que l'on trouve le fichier image de ce nom et format !
       Read \maximagepath
        \maximagepath=\maximagepath + \nom + ".png" ;Notez que la grande image porte le même nom que la petite, mais elle se trouve dans un autre répertoire
       Read \minlargeur ;les dimensions des images permettent de limiter la taille des fenêtre, de Zoom en particulier
       Read \minhauteur
       Read \maxlargeur
       Read \maxhauteur
     EndWith
Next i

;- Image Plugins, pour supporter les images au format PNG
usepngimagedecoder ()
 
loadimage ( #Image0 ,Tuile( #Image0 )\minimagepath) ;Considérons dans un premier temps que seuls les images mini sont utilisées
loadimage ( #Image1 ,Tuile( #Image1 )\minimagepath) ;ces appels à Load sont alors tous faits en amont de la boucle et de la fenêtre principale


Procedure FenetrePrincipale()
   If openwindow ( #FenetrePrincipale , 350, 100, 600, 600, "JEU" ) ;fenêtre assez large, sans option

   If creategadgetlist ( windowid ( #FenetrePrincipale )) ;définition des gagdets de cette fenêtre


;affichage de l'image et de son TOOLTIP, ou infobulle
   imagegadget ( #Image0 ,10,80,Tuile(0)\minlargeur,Tuile(0)\minhauteur, imageid ( #Image0 ), #PB_Image_Border ) ;première image dont les dimensions viennent du tableau des TUILES
   gadgettooltip ( #Image0 ,Tuile(0)\titre) ;ceci est l'info bulle avec titre
  
   imagegadget ( #Image1 ,100,80,Tuile(1)\minlargeur,Tuile(1)\minhauteur, imageid ( #Image1 ), #PB_Image_Border ) ;deuxième image, ou deuxième TUILE
   gadgettooltip ( #Image1 ,Tuile(1)\titre) ;ceci est l'info bulle avec titre et texte
; les TOOLTIP sont indispensables si les images sont trop petites et illisible, et bien sur pour la version traduite
   EndIf
   EndIf
EndProcedure

Procedure FenetreZoom(maTuile)
   If openwindow ( #FenetreZoom , 50, 50, Tuile(maTuile)\maxlargeur, Tuile(maTuile)\maxhauteur, "Zoom" , #PB_Window_TitleBar )
   ;Petite fenetre de Zoom à la taille des modules, avec juste un titre, ne sera fermée que selon la gestion de ses gadgets
   If creategadgetlist ( windowid ( #FenetreZoom )) ;définition des gagdets de cette fenêtre

;affichage de l'image et de son TOOLTIP, ou infobulle
   loadimage ( #ImageZoom ,Tuile(maTuile)\maximagepath) ; ici l'image est chargée en fonction de l'appel qui est fait avec la FenetreZoom
   imagegadget ( #ImageZoom ,0,0,Tuile(maTuile)\maxlargeur,Tuile(maTuile)\maxhauteur, imageid ( #ImageZoom )) ;depuis le coin supérieur gauche on place l'image chargée précédemment
   gadgettooltip ( #ImageZoom ,Tuile(maTuile)\titre) ;La fenetre de Zoom a elle aussi le ToolTip prévu
   EndIf
   EndIf
EndProcedure
Dernière modification par kerkael le sam. 20/sept./2008 22:58, modifié 2 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

Message par kerkael »

Fichier 3/3 : tutoData.pb
;tutoData.pb
;included dans tutoCommon.pb

;-------------------------------------
; Ici le DataSection de toutes les tuiles et cartes utilisables dans le jeu
; La nature et le nombre de champs sont définis par l'appel qui est fait
; de cette DataSection par le combiné de commandes RESTORE et READ
;
; Chaque nouvelle tuile doit absolument être définie par le bon nombre de champs
; Nous prendrons ici maxImages et minImages comme les répertoires relatifs qui
; contiennent les petites et grandes images, mais avec le même nom, tiré du nom de la tuile

DataSection
  MesTuiles:
     Data.s "ci1" , "Centre d'Infos I" , "minImages\" , "maxImages\" ;nom, titre, minImagePath, maximagePath
     Data.l 87,87,250,250 ;minlargeur , minhauteur, maxlargeur, maxhauteur,
     Data.s "cg1" , "Centre de Gestion I" , "minImages\" , "maxImages\"
     Data.l 87,87,250,250
EndDataSection
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

Message par kerkael »

Bon, après mure réflexion, j'ai trouvé comment modifier à chaud ma fenêtre de zoom sans la rouvrir à chaque fois. La commande à utiliser était

Code : Tout sélectionner

SetGadgetState(#GadgetImageZoom,ImageID(EventGadget()+2))
SetGadgetState permet de modifier un Gadget existant. En particulier de remplacer l'image d'un ImageGadget comme l'explique l'aide.

J'ai du modifier le code en plusieurs points pour la prise en compte de ces nouveaux paramètres. Tout d'abord l'énumération des variables doit prévoir :
  • - un gadget par image mini
    - un gadget par image maxi
    - un gadget pour le zoom
L'énumération des images maxi doit suivre celle des mini dans le même ordre. Le nombre d'images de part et d'autre servira de compteur de décalage. Dans la commande ci-dessus, le décalage est +2 parce que je ne gère que 2 images dans un premier temps.

Par ailleurs, toutes les images (mini et maxi) doivent être loadées avant l'appel des fenêtres (principale et zoom) pour que le rafraichissement du Zoom ne soit pas bloqué.

Code : Tout sélectionner

LoadImage(#Image0,Tuile(#Image0)\minimagepath)
LoadImage(#Image1,Tuile(#Image1)\minimagepath)
LoadImage(#Image0Zoom,Tuile(#Image0)\maximagepath)
LoadImage(#Image1Zoom,Tuile(#Image1)\maximagepath)
Notez le décalage de 2 entre une image mini et la maxi corresondante.

Ensuite, la déclaration de la FenetreZoom n'est pas modifiée. Sauf que j'ai corrigé une petite erreur : j'avais donné à ImageGadget du zoom le même identifiant qu'à LoadImage. J'ai maintenant prévu dans les énumérations initiales une variable pour ImageGadget.

En ce qui concerne le traitement des événements, eh bien vous avez déjà la commande à utiliser. Il faut juste prévoir de n'ouvrir la FenetreZoom que la première fois. D'où l'utilisation de

Code : Tout sélectionner

If IsWindow(#FenetreZoom)
Voici le code complet après modif :
Fichier 1/3
;tutomain.pb
; fichier principal

;==============================
; Structures, Procédures, et Variables globales
IncludeFile "tutoCommon.pb"

FenetrePrincipale()

;==============================
; Boucle principale avec gestion de quelques clics sur les gadgets (ici des images)
Repeat
  Event = waitwindowevent () ;Attendons un événement
   Select Event ;Selon l'événement survenu !!!
    Case #PB_Event_Gadget ;Cet événement est arrivé sur un Gadget
       Select eventgadget () ;Selon Le Gadget concerné ...
         Case #GadgetImageZoom ;si le gadget touché est #GadgetImageZoom, pas question de rezoomer sur le Zoom !!!
           If eventtype ()= #PB_EventType_RightDoubleClick ;du coup pour fermer le Zoom, Double-Clic Droit
             closewindow ( #FenetreZoom ) ;et Voilà où l'on ferme la fenêtre de Zoom ... mais quand l'a-t-on ouverte ?
           EndIf
         Default ;Dans tous les autres cas, on n'est pas sur le Zoom, alors que fait-on ?
          Select eventtype () ;Selon le type d'évenement ...
            Case #PB_EventType_RightClick ; En cas de ClicDroit
              If iswindow ( #FenetreZoom ) ; Si la fenêtre de zoom est ouverte
               setgadgetstate ( #GadgetImageZoom , imageid ( eventgadget ()+2)) ;Modifier l'image qu'elle porte par l'image max
               gadgettooltip ( #GadgetImageZoom ,Tuile( eventgadget ())\titre) ;sans oublier de mettre à jour l'infobulle
              Else ;sinon c'est que la fenêtre n'est pas encore ouverte
             FenetreZoom( eventgadget ()) ;C'est ici que s'ouvre la fenêtre de zoom, en cas de clic droit sur un gadget
                                         ;on fournit à la fenêtre appelée le numéro du gadget sur lequel on vient de droit-cliquer
              EndIf
          EndSelect
       EndSelect
   EndSelect
Until Event = #PB_Event_CloseWindow ;sortie du programme dès que l'on ferme une fenêtre, probablement la principale, puisque celle du Zoom n'a pas de Menu
Attention, n'oubliez pas de modifier le paramètre +2 selon le nombre d'images énumérées dans le fichier suivant.

Fichier 2/3
;tutoCommon.pb
;included dans tutomain.pb

;==============================
; Toutes Data définissant les pièces, éléments, cartes, modules du plateau de jeu
IncludeFile "tutoData.pb"

Enumeration
   #Image0 ;On commence obligatoirement l'enumération par #Image0 parce que le tableau Tuile() utilisera cette variable comme index
   #Image1
   #Image0Zoom ;Après toutes les images mini, dans le même ordre on définit les images maxi
   #Image1Zoom
   #GadgetImageZoom
   #FenetrePrincipale
   #FenetreZoom
EndEnumeration

;==============================
; structure définissant les Modules, ou tuiles et cartes du plateau de jeu
Structure MODULE
  nom.s ;faire très attention à la nature des variables, qui devra être reprise dans la Datasection
  titre.s ;ici les 4 premières variables sont des textes, on poura les regrouper sur une seule Data.s
  minimagepath.s
  maximagepath.s
  minlargeur.l ;les 4 data Longues utilisées ici seront regroupables sur une seule ligne Data.l
  minhauteur.l
  maxlargeur.l
  maxhauteur.l ;ainsi 2 lignes seront suffisantes pour chaque Module
EndStructure

;===============================
; les tuiles sont de type MODULE, on en définit le nombre par la dimension du tableau
; C'est une variable globale parce qu'elle est définie et appelée depuis diverse structures et fichiers

Global Dim Tuile.MODULE(10)
Restore MesTuiles ;La fonction RESTORE va chercher MESTUILES dans la DATASECTION - ici ma DATASECTION se trouve appelée par INCLUDEFILE en début de fichier
   For i =0 To 1
     With Tuile(i) ;TUILE est un tableau de dimension 10
       Read \nom ;Toutes les champs de TUILE sont lus par READ depuis la DATASECTION
       Read \titre ;...et qu'il soient tous dans le bon ordre, parce que les READ sont dans le même ordre
       Read \minimagepath ;le chemin de l'image à l'exterieur de l'exe parce que les images ne seront pas incluses
        \minimagepath=\minimagepath + \nom + ".png" ;minimagepath est composé du chemin du dossier + nom de la tuile + .png
                                                     ;parce que c'est là que l'on trouve le fichier image de ce nom et format !
       Read \maximagepath
        \maximagepath=\maximagepath + \nom + ".png" ;Notez que la grande image porte le même nom que la petite, mais elle se trouve dans un autre répertoire
       Read \minlargeur ;les dimensions des images permettent de limiter la taille des fenêtre, de Zoom en particulier
       Read \minhauteur
       Read \maxlargeur
       Read \maxhauteur
     EndWith
Next i

;- Image Plugins, pour supporter les images au format PNG
usepngimagedecoder ()
 
loadimage ( #Image0 ,Tuile( #Image0 )\minimagepath) ;On charge toutes les images mini ...
loadimage ( #Image1 ,Tuile( #Image1 )\minimagepath)
loadimage ( #Image0Zoom ,Tuile( #Image0 )\maximagepath) ; ... et toutes les images maxi
loadimage ( #Image1Zoom ,Tuile( #Image1 )\maximagepath)
  

Procedure FenetrePrincipale()
   If openwindow ( #FenetrePrincipale , 350, 100, 600, 600, "JEU" ) ;fenêtre assez large, sans option

   If creategadgetlist ( windowid ( #FenetrePrincipale )) ;définition des gagdets de cette fenêtre


;affichage de l'image et de son TOOLTIP, ou infobulle
   imagegadget ( #Image0 ,10,80,Tuile(0)\minlargeur,Tuile(0)\minhauteur, imageid ( #Image0 ), #PB_Image_Border ) ;première image dont les dimensions viennent du tableau des TUILES
   gadgettooltip ( #Image0 ,Tuile(0)\titre) ;ceci est l'info bulle avec titre
  
   imagegadget ( #Image1 ,100,80,Tuile(1)\minlargeur,Tuile(1)\minhauteur, imageid ( #Image1 ), #PB_Image_Border ) ;deuxième image, ou deuxième TUILE
   gadgettooltip ( #Image1 ,Tuile(1)\titre) ;ceci est l'info bulle avec titre et texte
; les TOOLTIP sont indispensables si les images sont trop petites et illisible, et bien sur pour la version traduite
   EndIf
   EndIf
EndProcedure

Procedure FenetreZoom(maTuile)
   If openwindow ( #FenetreZoom , 50, 50, Tuile(maTuile)\maxlargeur, Tuile(maTuile)\maxhauteur, "Zoom" , #PB_Window_TitleBar )
   ;Petite fenetre de Zoom à la taille des modules, avec juste un titre, ne sera fermée que selon la gestion de ses gadgets
   If creategadgetlist ( windowid ( #FenetreZoom )) ;définition des gagdets de cette fenêtre

;affichage de l'image et de son TOOLTIP, ou infobulle
   loadimage ( maTuile+2 ,Tuile(maTuile)\maximagepath) ; ici l'image est chargée en fonction de l'appel qui est fait avec la FenetreZoom
   imagegadget ( #GadgetImageZoom ,0,0,Tuile(maTuile)\maxlargeur,Tuile(maTuile)\maxhauteur, imageid ( maTuile+2 )) ;depuis le coin supérieur gauche on place l'image chargée précédemment
   gadgettooltip ( #GadgetImageZoom ,Tuile(maTuile)\titre) ;La fenetre de Zoom a elle aussi le ToolTip prévu
   EndIf
   EndIf
EndProcedure
Bon, voilà ma petite contribution. Mais vu le peu de réponse à ce sujet jusque ici, je dois considérer soit que ça n'intéresse pas grand monde, où bien que tout cela tombe sous l'évidence, ou encore que tout existait déjà ailleurs ...

Pour la suite du développement de mon jeu de plateau, je posterai mes idées dans les Trucs et Astuces.

EDIT : Encore une légère erreur, corrigée sur le Le dernier LoadImage. J'appelais toujours la même variable lors de la première ouverture du Zoom. J'ai remplacé la variable #Image0Zoom par maTuile+2. Même chose pour l'imageId(maTuile+2)
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

Il n'y a pas eu un problème au niveau du scannage?
Car là les images sont quasi illisibles!
Les originaux doivent être plastifiés brillants?
Il faut virer la "trame" ou bricoler quelque chose, car là cela fait images des années 80 sur imprimantes couleur pour Amstrad :)
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

Message par kerkael »

Okay, j'ai réclamé des remarques ... je paye le prix.
Vous prenez vos propres images, bien entendu. Celles que je fournis sont là pour la démo.

Sinon dans les faits, comment je scanne sans trame ?
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

En général dans tous scanners modernes qui se respectent, il y a une fonction "Détramage"
Sinon il faut le faire dans un programme 2D, çà s'appelle en général
"Enlever la moirure" "Détramer"...
Ce qui pose problème c'est la lumière qui se reflète sur la partie "glacée" de la carte et qui génère ces effets génants!
Il faut bien regarder tout les paramètres avancés du scanner! (type de document, nature du document etc...
Répondre