[TUTO]Tuiles et Cartes pour un jeu de plateau - multilangue

Informations pour bien débuter en PureBasic
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

[TUTO]Tuiles et Cartes pour un jeu de plateau - multilangue

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


Voici ce que j'ai fait en glanant à droite et à gauche les informations des divers tuto, en particulier j'ai carrément tout pompé pour la version multilangue de ce qui est déjà présent ici.

Je vous propose un premier jet pour débuter dans la programmation d'un jeu de plateau. L'objectif est d'avoir des tuiles et cartes pour le jeu, facilement utilisables. Chaque tuile est associée à diverses variables, nom, description, cout, bonus, malus ...
En plus, les images étant dans un fichier externe à l'exécutable, il est toujours possible de les modifier, pour en changer la lisibilité, par exemple.
Au-delà de celà, j'ai donc réutilisé le code multilangue basé sur les fichiers de préférence pour permettre une traduction facile du jeu.

Autre sujet pour faire suite à celui-ci : [TUTO]Une fenêtre de Zoom sur des tuiles de jeux de plateau


Synopsis :
5 fichiers + toutes les images
Fichier 1 : projectmain.pb - fichier principal, appèle les autres, ouvre les fenêtres, fait tourner la boucle principale - sollicite projectPrefs.pb, projectCommon.pb
Fichier 2 : projectPrefs.pb - utilisé uniquement pour la langue des fenêtres et modules utilisés dans tout le programme - sollicite langues.pref
Fichier 3 : langues.pref - sollicité par projectPrefs.pb - fichier texte contenant les diverses traductions des textes utilisés dans le jeu
Fichier 4 : projectCommon.pb - sollicité par projectmain.pb, fichier principal de définition des variables, structures, procédures utilisées dans la boucle principale - sollicite projectData.pb
Fichier 5 : projectData.pb - sollicité par projectCommon.pb, contient l'énumération des divers champs des tuiles et cartes du jeu

Question : Pourquoi faire reposer le programme sur 5 fichiers au lieu d'un seul ?
Parce qu'une telle architecture est d'une part plus lisible, et d'autre part plus facilement déboguable. En plus regrouper la définition des datas dans un fichier à part permet de passer du temps à le remplir sans toucher au reste du code.

Question : Pourquoi ne pas inclure les images dans le code principal ?
L'inclusion des images sous format binaire agrandit considérablement la taille de l'exécutable. Pour un gros programme, cela augmente aussi le temps de compilation, et dans des périodes de test, on n'a pas envie de patienter, même 30 secondes, pour la compilation du code. En plus, les images peuvent être retouchées par la suite, voire modifiées si on veut y inclure un texte traduit, par exemple. Cela serait impossible si les images étaient incluses dans le binaire compilé.

Au dela des 5 fichiers dont je vais vous donner le code, vous aurez besoin, pour faire des tests, de 2 images de taille 250*250 :
Images\modules1\cg1.png
Image
Images\modules2\cg2.png
Image

Si vous n'avez pas d'image png sous la main, vous n'aurez qu'à adapter le fichier projectData.pb, et spécifier un autre plugin que UsePNGImageDecoder() dans projectCommon.pb

Voici le détail des divers fichiers :

fichier 1/5 : projectmain.pb
; projectmain.pb
; fichier principal

;=============================
; Appel de la gestion des préférences de language
IncludeFile "projectPrefs.pb"

;=============================
; Première fenêtre très temporaire qui propose la langue par séléction radio
; Cette procédure est définie dans le projectPrefs appelé juste avant
; on ira remarque que la FenetreLanguage ne porte pas de menu, ni option - seuls ses gadgest permettront la sortie de la boucle
FenetreLanguage()


;=============================
; Première boucle pour la première fenêtre
Repeat
   EventID = waitwindowevent ()
     If EventID = #PB_Event_Gadget
       Select eventgadget ()
         Case #radioEN
           preferencegroup ( "EN" )
         Case #radioCU
           preferencegroup ( "CU" )
         Case #radioDE
           preferencegroup ( "DE" )
         Default
            preferencegroup ( "FR" )
       EndSelect
     EndIf
Until EventID = #PB_Event_Gadget ;Dès la sélection d'une langue, la fenêtre se ferme

;==============================
; Structures, Procédures, et Variables globales
; On devrait en théorie préciser les includefile en tête de programme,
; mais je trouve plus lisible de n'appeler les fichiers qu'à partir du moment ou on les utilise
IncludeFile "projectCommon.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, au plus simple
Repeat
   EventID = waitwindowevent ()
     If EventID = #PB_Event_Gadget
       Select eventgadget ()
       EndSelect
     EndIf
Until EventID = #PB_Event_CloseWindow ;sortie du programme avec fermeture de la fenêtre[/code]
Dernière modification par kerkael le mer. 31/juil./2013 15:13, modifié 4 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

fichier 2/5

Message par kerkael »

fichier 2/5 : projectPrefs.pb

;projectPrefs.pb
;included dans projectmain.pb

;----------------------------------------------------------
;fichier inclus pour la gestion des préférences de language

;=======================
;inlusion du fichier de préférences initial lors de la compilation
;ce fichier a été créé comme un fichier texte de l'exterieur de PB, et inclus dans l'exe lors de la compilation
DataSection
  StartFile0:
  IncludeBinary "langues.pref"
  EndFile0:
EndDataSection

;=======================
;vérification, lecture et au besoin création d'un nouveéau fichier de préférences adaptable
Pref= openpreferences ( getcurrentdirectory ()+ "langues.pref" )
If Pref=0 ; comme ça il ne le fait pas à chaque fois !
  Size=?EndFile0-?StartFile0
   createfile (0, getcurrentdirectory ()+ "langues.pref" )
   writedata (0, ?StartFile0,Size)
   closefile (0)
EndIf

;=======================
; Définition de la première fenêtre demandant la langue utilisée pour le programme
Enumeration
   #fenetre0
EndEnumeration

;=======================
; 3 langues prédéfinies dans le fichier de pref ... Custom si la langue n'est pas une des 3 les plus courantes
Enumeration
   #radioEN
   #radioFR
   #radioDE
   #radioCU
EndEnumeration

;=======================
; fenêtre minime se fermant dès le choix d'une langue par bouton radio
Procedure FenetreLanguage()
   If openwindow ( #fenetre0 , 368, 138, 192, 41, "Language in Game" , #PB_Window_ScreenCentered |#PB_Window_TitleBar )
     If creategadgetlist ( windowid ( #fenetre0 ))
       optiongadget ( #radioEN , 50, 10, 40, 20, "EN" ) ;Les 4 options apparaissent sous forme de bouton Radio
       optiongadget ( #radioFR , 10, 10, 40, 20, "FR" ) ;un seul choix possible, donc
       optiongadget ( #radioDE , 90, 10, 40, 20, "DE" )
       optiongadget ( #radioCU , 130, 10, 60, 20, "Custom" )
     EndIf
   EndIf
EndProcedure
Dernière modification par kerkael le lun. 15/sept./2008 9:43, modifié 1 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

fichier 3/5

Message par kerkael »

fichier 3/5 : projectCommon.pb

;projectCommon.pb
;included dans projectmain.pb

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

Enumeration
   #Window_0
   #Image0
   #Image1
EndEnumeration

;==============================
; sous-structure du cout utilisée dans la structure MODULE
Structure COST
  ble.b
  minerai.b
  crystal.b
  fuel.b
  marchandise.b
  connaissance.b
  astro.b
EndStructure

;==============================
; structure définissant les Modules, ou tuiles et cartes du plateau de jeu
Structure MODULE
  nom.s
  type.s
  titre.s
  defautTitre.s ;si la traduction n'a pas été faite, toujours prévoir un titre affichable par défaut
  texte.s
  defautTexte.s ;si la traduction n'a pas été faite, toujours prévoir un texte affichable par défaut
  imagepath.s
  niveau.b
  largeur.b
  hauteur.b
  pointV.b ;Points de Victoire
  pointA.b ;Points d'Amitié
  cout.COST ;sous-structure définie plus haut
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 \type ;...il est important que chaque nouvelle TUILE ait exactement le bon nombre de champs
       Read \titre ;...et qu'il soient tous dans le bon ordre, parce que les READ sont dans le même ordre
       Read \defautTitre ;si le fichier de préférences ne contient pas d'entrée TITRE dans la langue demandée, on aura prévu un TITRE par défaut
        \titre= readpreferencestring (\titre,\defautTitre) ;cas particulier, après avoir lu TITRE, on le traduit dans la langue préférentielle
       Read \texte
       Read \defautTexte
        \texte= readpreferencestring (\texte,\defautTexte) ;même chose pour TEXTE, ces 2 champs seront en fait tirés du fichier de PREF
       Read \imagepath ;le chemin de l'image à l'exterieur de l'exe parce que les images ne seront pas incluses
       Read \niveau
       Read \largeur
       Read \hauteur
       Read \pointV
       Read \pointA
         Read \cout\ble ;les couts viennent de la sous-structure COST
         Read \cout\minerai
         Read \cout\crystal
         Read \cout\fuel
         Read \cout\marchandise
         Read \cout\connaissance
         Read \cout\astro
;Ligne à décommenter pour s'assurer de l'attribution des variables
;Debug \nom+Chr(13)+\titre+\texte+Str(\cout\ble)+Str(\cout\fuel)+Str(\cout\astro)
     EndWith
Next i

Procedure FenetrePrincipale()
  ;- Image Plugins, pour supporter les images au format PNG
usepngimagedecoder ()
 
   If openwindow ( #Window_0 , 50, 0, 600, 600, "JEU" ) ;fenêtre assez large, sans option
   If creategadgetlist ( windowid ( #Window_0 )) ;définition des gagdets de cette fenêtre

;pour l'exemple, chargement et affichage de 2 TUILES seulement
loadimage ( #Image0 ,Tuile(0)\imagepath)
loadimage ( #Image1 ,Tuile(1)\imagepath)

;affichage de l'image et de son TOOLTIP, ou infobulle
   imagegadget ( #Image0 ,10,80,Tuile(0)\largeur,Tuile(0)\hauteur, imageid ( #Image0 )) ;première image dont les dimensions viennent du tableau des TUILES
   gadgettooltip ( #Image0 ,Tuile(0)\titre + " : " + Tuile(0)\texte) ;ceci est l'info bulle avec titre et texte
  
   imagegadget ( #Image1 ,265,80,Tuile(1)\largeur,Tuile(1)\hauteur, imageid ( #Image1 )) ;deuxième image, ou deuxième TUILE
   gadgettooltip ( #Image1 ,Tuile(1)\titre + " : " + Tuile(1)\texte) ;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
Dernière modification par kerkael le lun. 15/sept./2008 9:44, modifié 1 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

fichier 4/5

Message par kerkael »

fichier 4/5 : projectData.pb
;projectData.pb
;included dans projectCommon.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

DataSection
  MesTuiles:
     Data.s "cg1" , "Module" , "CG1_Titre" , "Centre de Gestion I" , "CG1_Texte" , "3 Actions" , "Images\modules1\cg1.png" ;nom,type,titre,defautTitre,texte,defautTexte,imagepath
     Data.b 1,250,250,0,0 ;niveau,largeur,hauteur,pointV,pointA
     Data.b 1,1,1,0,0,0,0 ;coutble,coutminerai,coutcrystal,coutfuel,coutmarchandise,coutconnaissance,coutastros
     Data.s "cg2" , "Module" , "CG2_Titre" , "Centre de Gestion II" , "CG2_Texte" , "4 Actions, +1PV" , "Images\modules2\cg2.png" ;nom,type,titre,texte,imagepath
     Data.b 2,250,250,1,0 ;niveau,largeur,hauteur,pointV,pointA
     Data.b 2,1,1,0,0,0,0 ;coutble,coutminerai,coutcrystal,coutfuel,coutmarchandise,coutconnaissance,coutastros

EndDataSection
Dernière modification par kerkael le lun. 15/sept./2008 9:44, modifié 1 fois.
kerkael
Messages : 97
Inscription : mer. 03/sept./2008 21:08

fichier 5/5

Message par kerkael »

fichier 5/5 : langues.pref
Ce fichier est un simple fichier texte à renseigner depuis un notepad, par exemple.

[FR]
CG1_Titre = Centre de Gestion I
CG1_Texte = Pendant votre phase de vol, vous pouvez réaliser 3 actions.
CG2_Titre = Centre de Gestion II
CG2_Texte = Pendant votre phase de vol, vous pouvez réaliser 4 actions. +1VP

[EN]
CG1_Titre = Management Center I
CG1_Texte = During your flight phase, you can realize 3 actions.
CG2_Titre = Management Center II
CG2_Texte = During your flight phase, you can realize 4 actions. +1VP

[DE]
CG1_Titre = Das Management Center I
CG1_Texte = Der During your flight phase, du können realize 3 actions.
;l'absence d'un champ entraine l'utilisation de la valeur par défaut prévue dans le Datasection du code inclus.

[CU]
CG2_Titre = Itchouest Kwetii II
CG2_Texte = Yvanslak Hartsu Blou
Répondre