[Jeu] interface et Screen

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

[Jeu] interface et Screen

Message par blendman »

Salut

J'ouvre ce sujet pour celles et ceux qui seraient intéressés par la création de jeu et notamment la conception d'interface pour ces jeux (menus, boutons, case à cocher, onglet, ascenseur..).

Vu quand dans un jeu, on utilise un screen (ou un windowedScreen), on ne peut pas utiliser les gadget dessus.
Il faut donc que l'on conçoive son interface complètement.

Je propose donc l'ouverture de ce sujet pour regrouper l'ensemble des informations concernant ce genre de choses : les interfaces dans les jeux.

Voici un premier code.
Il permet de concevoir des boutons et autre gadget du même genre (case à cocher) . La mise en place est assez simple.

Code : Tout sélectionner

;{ infos
; Blendman 11/2011
; début de système d'interface pour jeu.
; PB 4.60 - windows
;}

;{ enumeration, variables, structures
#btn = 0

Global NewMap option.s()
Global keypressed.a,mouseclicked.a

Structure buton
  x.q
  y.q
  over.a
  sens.b
  nom$
  txt$
  valeur.q
EndStructure
Global NewList buton.buton()
;}

;{ macro & procédures
; utilitaire
Procedure AddElmt(key$,val$="")
  AddMapElement(option(),key$)
  option(key$) = val$
EndProcedure

; ajouter un bouton
Procedure AddBtn(x.w,y.w,txt$,valeur,nom$,sens.a=1)
  AddElement(buton())
  buton()\x = x
  buton()\y = y
  buton()\txt$ = txt$
  buton()\nom$ = nom$
  buton()\valeur = valeur
  buton()\sens = sens
EndProcedure
; event sur les boutons

Macro chgOpt(param,val)
  option(param)=val
EndMacro

Procedure EventBtn(List buton.buton())
  ForEach buton()
    With buton()
      If MouseX()>\x And MouseX() < \x+50 And MouseY()>\y And MouseY()<\y+20
        \over = 1
        If MouseButton(#PB_MouseButton_Left) And mouseclicked=0
          mouseclicked =1
          chgOpt(\txt$,Str(Val(option(\txt$)) +\valeur*\sens))
        EndIf 
      Else
        \over = 0
      EndIf
    EndWith
  Next
  If MouseButton(#PB_MouseButton_Left)=0
    mouseclicked=0
  EndIf
EndProcedure
;}

;{ init
If InitSprite() =0 Or  InitKeyboard() =0 Or InitMouse()=0  Or InitSprite3D() =0
  End
EndIf
;}

;{ window
ShowCursor_(1) 
OpenWindow(0,0,0,1024,768,"test d'interface",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,1024,768,0,0,0)

CreateSprite(#btn,50,20,#PB_Sprite_Texture) ; le sprite des boutons
CreateSprite3D(#btn,#btn)
StartDrawing(SpriteOutput(#btn))
Box(0,0,50,20,RGB(100,100,100))
StopDrawing()

; ajout de paramètres pour tester le principe des boutons. Chaque bouton permet de changer un paramètre du jeu.
AddElmt("Vie")
AddElmt("Mana")
AddElmt("Force")
AddElmt("Shado","1") ; option d'affichage (afficher les ombres ou non

;{ ajout des gadgets pour le screen :)
AddBtn(50,50,"Vie",1,"Vie+",1)
AddBtn(110,50,"Vie",1,"Vie-",-1)
AddBtn(50,80,"Mana",1,"Mana+",1)
AddBtn(110,80,"Mana",1,"Mana-",-1)
AddBtn(50,110,"Force",1,"Force+",1)
AddBtn(110,110,"Force",1,"Force-",-1)
;}

KeyboardMode(#PB_Keyboard_International)
;}

;{ boucle
Repeat 
  ;{ les events
  event = WaitWindowEvent(10)
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_B) And keypressed = 0
    keypressed =1
    option("Shado") = Str(1-Val(option("Shado")))
  EndIf
  If KeyboardReleased(#PB_Any)
    keypressed = 0
  EndIf 
  ExamineMouse()
  EventBtn(buton.buton())
  ;}
  
  ;{ l'affichage
  ClearScreen(RGB(50,50,50))
  Start3D()
  ForEach buton()
    DisplaySprite3D(#btn,buton()\x,buton()\y)
    If buton()\over = 1
      Sprite3DBlendingMode(5,7)
      DisplaySprite3D(#btn,buton()\x,buton()\y,100)
      Sprite3DBlendingMode(5,6)
    EndIf
  Next
  Stop3D()
  
  StartDrawing(ScreenOutput())
  DrawingMode(#PB_2DDrawing_Transparent)
  ForEach buton()
    DrawText(buton()\x+5,buton()\y+3,buton()\nom$,#White)
  Next
  DrawText(200,50, "valeur : "+option("Vie"))
  DrawText(200,80, "valeur : "+option("Mana"))
  DrawText(200,110, "valeur : "+option("Force"))
  If option("Shado") = "1"
    DrawText(350,10, "On affiche les ombres")
  EndIf  
   DrawText(10,10, "Touche B pour afficher ou non les ombres")
  StopDrawing()
  FlipBuffers()
  ;}
  
Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow
CloseWindow(0)
End
;}
Je le mettrai prochainement avec d'autre ajouts (onglets, case à cocher, ascenseur..)
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Jeu] interface et Screen

Message par Ar-S »

c'est une très bonne initiative. J'adhère :)
N'ayant que quelques heures de route pour tout ce qui touche à la 2D en PB (quelques tests de sprites et casse brique), je n'ai pas encore pris le tems de me pencher sur les l'interface. C'est donc un sujet en or 8)
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
jem
Messages : 18
Inscription : lun. 26/sept./2011 9:02

Re: [Jeu] interface et Screen

Message par jem »

Je me suis pencher sur le probleme récement.

Ma solution à été la suivante : j'ai utilisé la bibliotheque SGX de WanabePhoenix :
http://www.wannabephoenix.de/pbstuff/pb ... e&light=on
http://forums.purebasic.com/english/vie ... hp?t=31357

à laquelle j'ai apporté des modifications ( transparence des fenetres de type "sgx_Win" , gestion "clavier FR - azerty" - buggué à cause d'un scan code non envoyé correctement, gestion ammélioré des objets type "sgx_TextEdit" pour prendre en charge la touche [ENTER] et [ESCAPE] comme je le voulais - correction d'un probleme de lenteur lors de la creation des "sgx_Combo" ).

Cela m'a fait gagner énormément de temps, mais force est d'avouer que je ne suis pas entièrement satisfait du résultat, de plus aucun suivit du projet SGX ne semble d'actualité.
La réalisation d'une bibliotheque de gadget 2D est un projet dans le projet à lui tout seul et cela pourrait m'intérésser de me lancer la dedans.

On peut en parler via MP et plus si affinité

Edit : voici un début d'interface pour se donner une idée de comment moi je verrai le fonctionnement du truc. L'idée est de se caller sur le fonctionnement des gadgets de PB

Code : Tout sélectionner

; ***********************
; Essai sur système de Gadget 2D
; Jem  : Novembre 2011
; ***********************

EnableExplicit

;- *** ENUMERATION ***
;2DGadget ID
Enumeration
  #GUI_CURSOR
  #GUI_BUTTON1
  #GUI_BUTTON2
EndEnumeration

;2DGadget Type
Enumeration
  #GADGET2D_MOUSE
  #GADGET2D_BUTTON
  #GADGET2D_WINDOWS
EndEnumeration


;- Structures

Structure s_Gadget2D_Item
  Type.a        ;Gadget Type ( Button, TextEdit, Windows )
  SpriteID.l
  Width.l
  Height.l
  posX.l
  posY.l
  Display.b     ;Display Item
  Text.s
  State.b
  IsToggle.b    ;For Button only : True or False
  Opacity.a     ;0-255 : 0=Transparent - 255=Opaque
EndStructure



;- *** VARIABLES AND CONSTANTS ***
#MAIN_GAMEWINDOW_WIDTH=1024
#MAIN_GAMEWINDOW_HEIGHT=768


;- Gadget2D Variable
Global NewMap Gadget2DMap.s_Gadget2D_Item()
Global Gadget2D_SpriteIdStartIndex.l=30000



;- *** PROCEDURES ***
Declare.l Gadget2D_InitMouse()
Declare.l Gadget2D_Button(ButtonID.l,width.l,height.l,positionX.l,positionY.l,Text.s,Opacity.a=255,IsToggle.b=#False) 
Declare.l Gadget2D_CreateButton(ButtonID.l)
Declare Gadget2D_Display()
Declare.l Gadget2D_Event()

Procedure GetKeyboard()
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_Escape)
    End
  EndIf
  
EndProcedure


Procedure.l Gadget2D_Mouse(MouseId.l,Opacity.a=255)
  
  AddMapElement(Gadget2DMap(),Str(MouseId))
  With Gadget2DMap()
    
    \Type=#GADGET2D_MOUSE
    \posX=#MAIN_GAMEWINDOW_WIDTH / 2
    \posY=#MAIN_GAMEWINDOW_HEIGHT / 2
    \Opacity=Opacity
    \Display=#True
    
    \SpriteID=Gadget2D_SpriteIdStartIndex + MouseId
    If CreateSprite(\SpriteID,4,4,0)
      StartDrawing(SpriteOutput(\SpriteID))
      Box(0,0,4,4,$0000FF)
      StopDrawing()
      MouseLocate(\posX,\posY)
      ProcedureReturn MouseId
    Else
      ProcedureReturn 0
    EndIf
   
  EndWith
  
EndProcedure


Procedure.l Gadget2D_Button(ButtonID.l,width.l,height.l,positionX.l,positionY.l,Text.s,Opacity.a=255,IsToggle.b=#False)
  
  AddMapElement(Gadget2DMap(),Str(ButtonID))
  With Gadget2DMap()
    
    \Type=#GADGET2D_BUTTON
    \Width=width
    \Height=height
    \posX=positionX
    \posY=positionY
    \Text=Text
    \Opacity=Opacity
    \IsToggle=IsToggle
    \SpriteID=Gadget2D_CreateButton(ButtonID)
    \Display=#True
    
    If \SpriteID
      ProcedureReturn ButtonID
    Else
      ProcedureReturn 0
    EndIf
    
  EndWith

EndProcedure

Procedure.l Gadget2D_CreateButton(ButtonID.l)
  Protected SpriteID.l
  SpriteID=Gadget2D_SpriteIdStartIndex + ButtonID
  
  With Gadget2DMap(Str(ButtonID))
    
    If CreateSprite(SpriteID,\Width,\Height,0)
      TransparentSpriteColor(SpriteID,$000000)
      
      StartDrawing(SpriteOutput(SpriteID))
      Box(0,0,\Width,\Height,$000001)
      DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
      Box(0,0,\Width,\Height,$FFFFFF)
      DrawText(0,0,\Text,$FFFFFF)
      StopDrawing()
      
      ProcedureReturn SpriteID
    Else
      ProcedureReturn 0
    EndIf
    
  EndWith

EndProcedure



Procedure Gadget2D_Display()
  
  ResetMap(Gadget2DMap())
  While NextMapElement(Gadget2DMap())
    With Gadget2DMap()
      
      If \Display
        DisplayTranslucentSprite(\SpriteID,\posX,\posY,\Opacity)
      EndIf
      
    EndWith
  Wend
  
EndProcedure


Procedure.l Gadget2D_Event()
  ExamineMouse()
  
  ResetMap(Gadget2DMap())
  While NextMapElement(Gadget2DMap())
    With Gadget2DMap()
      
      If \Display
        
        Select \Type
            
          Case #GADGET2D_MOUSE
            \posX=MouseX()
            \posY=MouseY()
            ;Debug "x=" + Str(\posX) + " y=" + Str(\posY)
            
          Case #GADGET2D_BUTTON
            
            If MouseX() >= \posX And MouseX() < (\posX+\Width) And MouseY() >= \posY And MouseY() < (\posY + \Height)
              Debug "hover"
              If MouseButton(#PB_MouseButton_Left)
                ProcedureReturn Val(MapKey(Gadget2DMap()))
              EndIf
            EndIf
            
        EndSelect
        
      EndIf
      
    EndWith
  Wend
  
EndProcedure



;- *** INIT PROCEDURE ***

InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0,0,0,#MAIN_GAMEWINDOW_WIDTH,#MAIN_GAMEWINDOW_HEIGHT,"test GUI",#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
OpenWindowedScreen(WindowID(0),0,0,#MAIN_GAMEWINDOW_WIDTH,#MAIN_GAMEWINDOW_HEIGHT,1,0,0)

KeyboardMode(#PB_Keyboard_International)


Gadget2D_Mouse(#GUI_CURSOR)
Gadget2D_Button(#GUI_BUTTON1,100,50,300,300,"Button1")
Gadget2D_Button(#GUI_BUTTON2,100,50,500,300,"Button2",128)


;-  *** MAIN LOOP ***
Repeat
  
  Select WindowEvent()
    Case #PB_Event_CloseWindow
      End
  EndSelect
  
  ClearScreen($CCCCCC)
  GetKeyboard()
  
  Select Gadget2D_Event()
    Case #GUI_BUTTON1
      Debug "Button 1 click"
    Case #GUI_BUTTON2
      Debug "Button 2 click"
  EndSelect
  
  Gadget2D_Display()
  
  FlipBuffers()

ForEver
End
C'est un noyau pour montrer le sens dans lequel moi je verrai le code fonctionner.
On pourrais rajouter :
- Un modele de "Design" visuel facilement editable au travers un ( ou plusieurs ) fichier image type BMP ou PNG. Cela servira de base pour dessiner les sprites représentant les gadgets ( Bordure, Fond, gestion du "Hover" optionel en affichant un sprite légèrement différent avec passage de souris ) ou tout autre système.
-Rajout de tout les gagets necessaires ( Scroll, TextEdit, Container etc... )
-gestion de fenetre Parent et enfants .. les gadgets doivent pouvoir etre dans un "Container" , et ce "Container" devrait pourvoir se comporter comme un fenetre visble ou invisible , avec fond ou sans fond etc ..., et que tout son contenu soit masquer en meme temps que l'element lorsque 'lon choisit de cacher celui ci.

Bref tout est à faire, cela me semble être quand mème un travail énorme.
PureBasic V4.60 RC2 x86 | Windows 7
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Jeu] interface et Screen

Message par blendman »

J'aime bien l'idée de gérer les gadget2D comme les gadgets de purebasic pour les window (avec ta procedure Gadget2D_Event()).

Par contre, le fait de devoir créer un sprite par gadget devrait être revu, car ça va vite être lourd à gérer.
Je pense que ce serait intéressant d'afficher un texte en font bitmap, ça nous éviterait de devoir créer un sprite par gadget ;).

Mais je trouve ton code plutôt intéressant.

C'est vrai que c'est un gros boulot, mais on n'est pas obligé de tout faire d'un coup, on peut juste commencer par quelques gadgets, et on compléterait au fur et à mesure qu'on avance sur le système, en ajoutant un ou 2 gadgets à la fois par exemple.
D'abord, on peut commencer par les gadgets les plus simples (boutons, cases à cocher, trackbars), puis, les gadgets moins simples (combobox, onglet..) puis les gadgets compliqués (scrollarea, container..).
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Re: [Jeu] interface et Screen

Message par Torp »

Salut,

je vais peut être dire une grosse bêtise mais la bibliothèque Gadget3D fourni avec PB, ne fais pas la même chose ?

Bye
jem
Messages : 18
Inscription : lun. 26/sept./2011 9:02

Re: [Jeu] interface et Screen

Message par jem »

@Blendman :
Par lourd, tu entend occupation mémoire non ?
En mode screen, comment faire pour afficher un Design graphique à ta fenètre sans utiliser de "sprite" ou "d'image" , je pense comme à des fenètres ou des boutons arrondis par exemple, ou gerer un niveau de transparence pour les elements à afficher.

D'apres les quelques essais en programation que j'ai fait récement, le principal soucis me semble etre d'optimiser le temps d'execution d'un code ( temps processeur) plutot que la mémoire.
Je me trompe peut être, mais en terme de temps d'execution , il me semble que charger 3 sprites en mémoire pour chaque élement une bonne fois pour toute ainsi que leur position respectives pour les afficher à la demande est bien plus éfficace que de les dessiner à la voler quand on en as besoin.
Bref mon adage actuel serait plutot qu'il faut mieux economiser du temps processeur que de la mémoire.
Un avis des utilisateurs avancés serait la bienvenu. :)

@Torp
Oui , mais non.
2 raisons :
- 1 : la bibliotheque Gadget 3D s'utiliser avec le moteur 3D .. il faut donc un RenderWorld() pour les afficher , et faire fonctionner du 2D avec du 3D dans PB, je le sens pas tres bien ( je dis pas que c'est infaisable)

-2 : la bibliotheque gadget3D en l'état actuel est absolument inutilisable. Trop de bug et composant qui ne marche pas correctement ( Voir : http://www.purebasic.fr/english/viewtop ... =4&t=40837 )



@Tout le monde
La partie qui me fait le plus peur dans une bibliotheque de gadget2D, est la gestion du clavier et des composants genre "String Gadget".
J'ai énormement de mal à cerner comment utiliser la biblio Keyboard(), et un "StringGadget" par exemple : placement du curseur , utilisation du la touche "Suppr", gerer les copier coller )

Tout en gardant en tète que le principal interet de developper un module similaire est qu'il fontionne comme PB, sur tout les OS ( donc pas d'utilisation de commande propres aux OS )
Je rappel au passage qu'un Bug existant empeche l'utilisation d'une des touche d'un clavier AZERTY ( la "," ) en mode #PB_Keyboard_International.


Edit : Nouvelle version montrant l'utilisation de 3 sprites par Gadget : Sprite normal, sprite Hover , sprite Click
La gestion du click à aussi été améliorée pour n'en prendre qu'un seul en compte.

Code : Tout sélectionner


; ***********************
; Essai sur système de Gadget 2D
; Jem  : Novembre 2011
; ***********************

EnableExplicit

;- *** ENUMERATION ***
;2DGadget ID
Enumeration
  #GUI_CURSOR
  #GUI_BUTTON1
  #GUI_BUTTON2
  #GUI_BUTTON_QUIT
EndEnumeration

;2DGadget Type
Enumeration
  #GADGET2D_TYPE_MOUSE
  #GADGET2D_TYPE_BUTTON
  #GADGET2D_TYPE_WINDOWS
EndEnumeration

;Gadget2D Display
Enumeration -1 Step 1
  #GADGET2D_DISPLAY_NONE      ;=-1
  #GADGET2D_DISPLAY_NORMAL
  #GADGET2D_DISPLAY_HOVER
  #GADGET2D_DISPLAY_CLIKED
EndEnumeration


;- Structures
Structure s_Gadget2D_Item
  Type.a          ;Gadget Type ( Button, TextEdit, Windows )
  Display.b       ;Display Item
  SpriteID.l[3]   ;SpriteID for the Different Display
  Width.l
  Height.l
  posX.l
  posY.l
  Text.s
  IsToggle.b      ;For Button only : True or False
  Opacity.a       ;0-255 : 0=Transparent - 255=Opaque
EndStructure

;- *** VARIABLES AND CONSTANTS ***
#MAIN_GAMEWINDOW_WIDTH=1024
#MAIN_GAMEWINDOW_HEIGHT=768


;- Gadget2D Variable
Global NewMap Gadget2DMap.s_Gadget2D_Item()
#Gadget2D_Sprite_StartIndex_Normal=30000
#Gadget2D_Sprite_StartIndex_Hover=40000
#Gadget2D_Sprite_StartIndex_Clicked=50000



;- *** PROCEDURES ***
Declare.l Gadget2D_InitMouse()
Declare.l Gadget2D_Button(ButtonID.l,width.l,height.l,positionX.l,positionY.l,Text.s,Opacity.a=255,IsToggle.b=#False) 
Declare.l Gadget2D_CreateButton(ButtonID.l)
Declare Gadget2D_Display()
Declare.l Gadget2D_Event()

Procedure GetKeyboard()
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_Escape)
    End
  EndIf
  
EndProcedure


Procedure.l Gadget2D_Mouse(MouseId.l,Opacity.a=255)
  
  AddMapElement(Gadget2DMap(),Str(MouseId))
  With Gadget2DMap()
    
    \Type=#GADGET2D_TYPE_MOUSE
    \posX=#MAIN_GAMEWINDOW_WIDTH / 2
    \posY=#MAIN_GAMEWINDOW_HEIGHT / 2
    \Opacity=Opacity
    \Display=#GADGET2D_DISPLAY_NORMAL
    
    \SpriteID[0]=#Gadget2D_Sprite_StartIndex_Normal + MouseId
    If CreateSprite(\SpriteID[0],4,4,0)
      StartDrawing(SpriteOutput(\SpriteID[0]))
      Box(0,0,4,4,$0000FF)
      StopDrawing()
      MouseLocate(\posX,\posY)
      ProcedureReturn MouseId
    Else
      ProcedureReturn 0
    EndIf
   
  EndWith
  
EndProcedure


Procedure.l Gadget2D_Button(ButtonID.l,width.l,height.l,positionX.l,positionY.l,Text.s,Opacity.a=255,IsToggle.b=#False)
  
  AddMapElement(Gadget2DMap(),Str(ButtonID))
  With Gadget2DMap()
    
    \Type=#GADGET2D_TYPE_BUTTON
    \Width=width
    \Height=height
    \posX=positionX
    \posY=positionY
    \Text=Text
    \Opacity=Opacity
    \IsToggle=IsToggle
    ;\SpriteID[0]=Gadget2D_CreateButton(ButtonID)
    \Display=#GADGET2D_DISPLAY_NORMAL
       
    
    \SpriteID[0]=#Gadget2D_Sprite_StartIndex_Normal + ButtonID
    CreateSprite(\SpriteID[0],\Width,\Height,0)
    TransparentSpriteColor(\SpriteID[0],$000000)  
    StartDrawing(SpriteOutput(\SpriteID[0]))
    Box(0,0,\Width,\Height,$000001)
    DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
    LineXY(0,0,\Width,0,$FFFFFF)
    LineXY(0,0,0,\Height,$FFFFFF)
    LineXY(\Width,0,\Width,\Height,$CCCCCC)
    LineXY(0,\Height,\Width,\Height,$CCCCCC)
    DrawText(\Width/2 - TextWidth(\Text)/2,\Height/2 - TextHeight(\Text)/2,\Text,$FFFFFF)
    StopDrawing()
    
    \SpriteID[1]=#Gadget2D_Sprite_StartIndex_Hover + ButtonID
    CreateSprite(\SpriteID[1],\Width,\Height,0)
    TransparentSpriteColor(\SpriteID[1],$000000)  
    StartDrawing(SpriteOutput(\SpriteID[1]))
    Box(0,0,\Width,\Height,$EEEEEE)
    DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
    LineXY(0,0,\Width,0,$FFFFFF)
    LineXY(0,0,0,\Height,$FFFFFF)
    LineXY(\Width,0,\Width,\Height,$CCCCCC)
    LineXY(0,\Height,\Width,\Height,$CCCCCC)
    DrawText(\Width/2 - TextWidth(\Text)/2,\Height/2 - TextHeight(\Text)/2,\Text,$0000FF)
    StopDrawing()
    
    \SpriteID[2]=#Gadget2D_Sprite_StartIndex_Clicked + ButtonID
    CreateSprite(\SpriteID[2],\Width,\Height,0)
    TransparentSpriteColor(\SpriteID[2],$000000)  
    StartDrawing(SpriteOutput(\SpriteID[2]))
    Box(0,0,\Width,\Height,$EEEEEE)
    DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
    LineXY(0,0,\Width,0,$999999)
    LineXY(0,0,0,\Height,$999999)
    LineXY(\Width,0,\Width,\Height,$CCCCCC)
    LineXY(0,\Height,\Width,\Height,$CCCCCC)
    DrawText(\Width/2 - TextWidth(\Text)/2,\Height/2 - TextHeight(\Text)/2,\Text,$0000FF)
    StopDrawing()
    
    If \SpriteID[0] > 0 And \SpriteID[1] > 0 And \SpriteID[2] > 0
      ProcedureReturn ButtonID
    Else
      ProcedureReturn 0
    EndIf
    
  EndWith

EndProcedure

Procedure Gadget2D_Display()
  
  ResetMap(Gadget2DMap())
  While NextMapElement(Gadget2DMap())
    With Gadget2DMap()
      
      If \Display <> #GADGET2D_DISPLAY_NONE
        DisplayTranslucentSprite(\SpriteID[\Display],\posX,\posY,\Opacity)
      EndIf
      
    EndWith
  Wend
  
EndProcedure


Procedure.l Gadget2D_Event()
  Static Mouse_LeftClick.b,Mouse_LeftReleased.b,Mouse_RightClick.b,Mouse_Right_Released.b
  
  ExamineMouse()
  
  If MouseButton(#PB_MouseButton_Left) And Not Mouse_LeftClick
    Mouse_LeftClick=#True
    Mouse_LeftReleased=#False
  ElseIf Not MouseButton(#PB_MouseButton_Left) And Mouse_LeftClick 
    Mouse_LeftClick=#False
    Mouse_LeftReleased=#True
  ElseIf Not MouseButton(#PB_MouseButton_Left) And Not Mouse_LeftClick
    Mouse_LeftClick=#False
    Mouse_LeftReleased=#False
  EndIf
  
  
  ResetMap(Gadget2DMap())
  While NextMapElement(Gadget2DMap())
    With Gadget2DMap()
      
      If \Display <> #GADGET2D_DISPLAY_NONE
        
        Select \Type
            
          Case #GADGET2D_TYPE_MOUSE
            \posX=MouseX()
            \posY=MouseY()
            ;Debug "x=" + Str(\posX) + " y=" + Str(\posY)
            
          Case #GADGET2D_TYPE_BUTTON
            
            If MouseX() >= \posX And MouseX() < (\posX+\Width) And MouseY() >= \posY And MouseY() < (\posY + \Height)
              
              If Mouse_LeftClick
                \Display=#GADGET2D_DISPLAY_CLIKED
              ElseIf Mouse_LeftReleased
                ProcedureReturn Val(MapKey(Gadget2DMap()))
              Else
                \Display=#GADGET2D_DISPLAY_HOVER
              EndIf
            Else
              \Display=#GADGET2D_DISPLAY_NORMAL
            EndIf
            
        EndSelect
        
      EndIf
      
    EndWith
  Wend
  
EndProcedure



;- *** INIT PROCEDURE ***

InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0,0,0,#MAIN_GAMEWINDOW_WIDTH,#MAIN_GAMEWINDOW_HEIGHT,"test GUI",#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
OpenWindowedScreen(WindowID(0),0,0,#MAIN_GAMEWINDOW_WIDTH,#MAIN_GAMEWINDOW_HEIGHT,1,0,0)

KeyboardMode(#PB_Keyboard_International)


Gadget2D_Mouse(#GUI_CURSOR)
Gadget2D_Button(#GUI_BUTTON1,100,50,300,300,"Button1")
Gadget2D_Button(#GUI_BUTTON2,100,50,500,300,"Button2",128)
Gadget2D_Button(#GUI_BUTTON_QUIT,100,50,#MAIN_GAMEWINDOW_WIDTH/2 - 50,700,"Quit",255)



;-  *** MAIN LOOP ***
Repeat
  
  Select WindowEvent()
    Case #PB_Event_CloseWindow
      End
  EndSelect
  
  ClearScreen($CCCCCC)
  GetKeyboard()
  
  Select Gadget2D_Event()
    Case #GUI_BUTTON1
      Debug "Button 1 click"
    Case #GUI_BUTTON2
      Debug "Button 2 click"
    Case #GUI_BUTTON_QUIT
      End
  EndSelect
  
  Gadget2D_Display()
  
  FlipBuffers()

ForEver
End

Effectivement 3 sprites ( voir plus ? ) par Gagdet peut sembler "lourd", mais en y réfléchissant je ne vois pas trop le soucis :
-on a pas à les gérer .. le code s'en charge,il faut juste implementer le code pour leur création de façon a eviter les répétition de code pour rendre plus simple les modifications. ( dans l'exemple ci dessus je ne me suis pas du tout soucier de ça - j'ai fait ça en mode "sauvage" )

-les sprites font la taille des gadgets. Ils ne prennent vraiement pas beaucoup de mémoire, par rapport à ce qui est maintenant disponible dans une carte vidéo ou dans une machine. ( on parle d'ordre de grandeur en Giga Octets de mémoire )

-je ne vois vraiment pas comment on peut afficher une interface à base de fenetre en mode Screen sans passer par l'utilisation des sprites et leur code d'affichage optimiser pour la rapidité d'affichage dans PB.

bref plus j'en parle et que j'y réfléchi, plus je trouve le projet intérréssant :D
Je pense qu'avec un peu d'encouragement et d'aide ça pourrait le faire.
Dernière modification par jem le ven. 04/nov./2011 13:49, modifié 1 fois.
PureBasic V4.60 RC2 x86 | Windows 7
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Re: [Jeu] interface et Screen

Message par flaith »

J'avais commencé une GUI, que je n'ai pas eu le temps de finir par manque de temps, il permet de créer des boutons avec du texte créé avec une fonte fraphique et affiche aussi des fenêtres avec possibilité de fading

* Les images/fontes utilisées :
http://flaith.free.fr/img/IMG_FONT.png
http://flaith.free.fr/img/IMG_FONT_OUT.png
http://flaith.free.fr/img/SPR_FONT_OUT.png
http://flaith.free.fr/img/SPR_MOUSE.png

* Le code :

Code : Tout sélectionner

; Defined constant for saving png or not
#savepng = 0

;- Structures
Structure CS_Gadget
  ID.i
  Type.i
  X.i
  Y.i
  Width.i
  Height.i
  Text.s
  Flags.i
  Color.i
  ParentID.i
EndStructure

Structure CS_Window
  X.i
  Y.i
  Width.i
  Height.i
  Title.s
  Flags.i
  Color.i
  Alpha.i
  ParentID.i
EndStructure

;- Constantes
Enumeration 
  #MAIN_WIN
  #SPR_MOUSE
  #IMG_FONT
  #IMG_FONT_OUT
  ; GS_TextGadget need to use SPR_FONT_OUT
  #SPR_FONT_OUT
EndEnumeration

Enumeration 500
  #GADGET_Window
  #GADGET_Button
  #GADGET_Button_Toggle
  #GADGET_Text
  #GADGET_String
EndEnumeration

Enumeration 1000
  #GS_FONT_WIDTH
  #GS_FONT_HEIGHT
  #GS_FONT_CHAR_BY_LINE
  #GS_FONT_OUT_WIDTH
  #GS_FONT_OUT_HEIGHT
  #GS_FONT_OUT_CHAR_BY_LINE
EndEnumeration

Enumeration
  #GS_Windows_TitleBar        = 1 << 0
  #GS_Windows_Minimize        = 1 << 1
  #GS_Windows_Maximize        = 1 << 2
  #GS_Windows_Close           = 1 << 3
  #GS_Windows_BorderLess      = 1 << 4
  #GS_Windows_Border_simple   = 1 << 5
  #GS_Windows_Border_Double   = 1 << 6
  #GS_Windows_Border_Triple   = 1 << 7
EndEnumeration

Enumeration
  #GS_Text_Left               = 1 << 0
  #GS_Text_Right              = 1 << 1
  #GS_Text_Center             = 1 << 2
EndEnumeration

Enumeration
  #GS_Button_Enabled          = 1 << 0
  #GS_Button_Pushed           = 1 << 1
  #GS_Button_Disabled         = 1 << 2
EndEnumeration

Enumeration ;For iLastEvent
  #GS_EventType_MouseOver     = 1 << 0
  #GS_EventType_MouseUp       = 1 << 1
  #GS_EventType_MouseDown     = 1 << 2
  #GS_EventType_LeftClick     = 1 << 3                      ; Left mouse button click
  #GS_EventType_MiddleClick   = 1 << 4                      ; Middle mouse button click
  #GS_EventType_RightClick    = 1 << 5                      ; Right mouse button click
  #GS_EventType_Focus         = 1 << 6                      ; Get the focus
  #GS_EventType_LostFocus     = 1 << 7                      ; Lost the focus
EndEnumeration

#FONT_OUT_HEIGHT              = 10
#FONT_OUT_WIDTH               = 7
#NB_CHAR_OUT_BY_LINE          = 28                          ; 28 Char by Line inside Font Image

#FONT_HEIGHT                  = 8
#FONT_WIDTH                   = 6
#NB_CHAR_BY_LINE              = 28                          ; 28 Char by Line inside Font Image

#BORDER_SIMPLE                = 1
#BORDER_DOUBLE                = 2
#BORDER_TRIPLE                = 4

#SCREEN_Width                 = 280*2
#SCREEN_Height                = 192*2

#GS_VERSION                   = "0.14"

#Val_INCR                     = 5

;- Globals
Global NewList GadgetButton.CS_Gadget()
Global NewMap  GadgetWindow.CS_Window()

;- Global Event vars
Global.i iPosX, iPosY
Global.i iBut_left, iBut_middle, iBut_right
Global.i iLastEvent, iLastGadgetEvent, iMouseStatus

Global.i iNewID = 2222                                      ; Les ID commencent à ...
Global.i iTestWin1, iTestWin2, iTestWin3                    ; 5 Windows Test
Global.i iTestWin4, iTestWin5
Global.i iButtonQuit

;- Déclarations
Declare   GS_Init()
Declare.i GS_WindowID(__Window.i)
Declare.i GS_WindowHeight(__Window.i)
Declare.i GS_WindowWidth(__Window.i)
Declare.i GS_WindowX(__Window.i)
Declare.i GS_WindowY(__Window.i)
Declare   GS_TextGadget(__X.i,__Y.i,__sText.s, __ParentID.i = -1)
Declare   GS_DrawGadget()
Declare.i GS_ButtonGadget(__ID.i, __X.i, __Y.i, __Width.i, __Height.i, __sText.s, __Color.i = $EFEFEF, __Flags.i = #GS_Button_Enabled)
Declare.i GS_OpenWindow(__ID.i, __X.i, __Y.i, __Width.i, __Height.i, __sTitle.s = "", __Color.i = $FFFFFF, __Alpha.i = 255, __Flags.i = #GS_Windows_BorderLess)
Declare.i GS_DrawWindow(__ID.i, __X.i, __Y.i, __Alpha.i = -1)
;
Declare.i GS_EventGadget()
Declare.i GS_EventType()

;- Datasection
DataSection
  _DS_IMG_Font:       IncludeBinary "Img_Spr\IMG_FONT.png"
  _DS_IMG_Font_Out:   IncludeBinary "Img_Spr\IMG_FONT_OUT.png"
  _DS_SPR_Font_Out:   IncludeBinary "Img_Spr\SPR_FONT_OUT.png"
  _DS_SPR_CURSOR_DATA:IncludeBinary "Img_Spr\SPR_MOUSE.png"
EndDataSection

;- Procedures Internes
Procedure.i GetIDGadget()
  iNewID + 1
  ProcedureReturn iNewID
EndProcedure

Procedure.i GetFontAttribute(__FontID.i, __Attribute.i)
  Protected.i _iResult = 1

  Select __FontID
    Case #IMG_FONT
      Select __Attribute
        Case #GS_FONT_WIDTH
          _iResult = #FONT_WIDTH
        Case #GS_FONT_HEIGHT
          _iResult = #FONT_HEIGHT
        Case #GS_FONT_CHAR_BY_LINE
          _iResult = #NB_CHAR_BY_LINE
      EndSelect
    Case #IMG_FONT_OUT
      Select __Attribute
        Case #GS_FONT_OUT_WIDTH
          _iResult = #FONT_OUT_WIDTH
        Case #GS_FONT_OUT_HEIGHT
          _iResult = #FONT_OUT_HEIGHT
        Case #GS_FONT_OUT_CHAR_BY_LINE
          _iResult = #NB_CHAR_OUT_BY_LINE
      EndSelect
  EndSelect
  
  ProcedureReturn _iResult
EndProcedure

Procedure MakeImgText(__FontID.i, __PosX.i, __Width.i, __PosY.i, __Height.i, __sText.s, __Flags.i = #GS_Text_Left)
  Protected.i _iLen, _iPosX, _iPosY
  Protected.s _sChar
  Protected.i _sAscii, _iFontLine, _iClipX, _iClipY
  Protected.i _iIndex, _iImgTmp
  Protected.i _iFontWidth  = GetFontAttribute(__FontID, #GS_FONT_WIDTH)
  Protected.i _iFontHeight = GetFontAttribute(__FontID, #GS_FONT_HEIGHT)
  Protected.i _iFontCBLine = GetFontAttribute(__FontID, #GS_FONT_CHAR_BY_LINE)

  _iLen   = Len(__sText)
  If __Flags & #GS_Text_Center
    _iPosX  = (__Width  - (_iLen * _iFontWidth)) / 2
    _iPosY  = (__Height - _iFontHeight) / 2
  Else
    _iPosX  = __Width - __PosX
    _iPosY  = __Height
  EndIf

  For _iIndex = 1 To _iLen
    _sChar     = Mid(__sText,_iIndex,1)
    _sAscii    = Asc(_sChar) - 32
    _iClipX    = (_sAscii % _iFontCBLine) * _iFontWidth
    _iClipY    = (_sAscii / _iFontCBLine) * _iFontHeight
    _iImgTmp   = GrabImage(__FontID, #PB_Any, _iClipX, _iClipY, _iFontWidth, _iFontHeight)
    DrawAlphaImage(ImageID(_iImgTmp), __PosX + _iPosX, __PosY + _iPosY)
    _iPosX + _iFontWidth
  Next
EndProcedure

Procedure.i DoRGB(__Color.i, __Value.i)
  Protected.i _Red   = Red(__Color)   + __Value
  Protected.i _Green = Green(__Color) + __Value
  Protected.i _Blue  = Blue(__Color)  + __Value

  If _Red   < 0 : _Red   = 0 : EndIf
  If _Green < 0 : _Green = 0 : EndIf
  If _Blue  < 0 : _Blue  = 0 : EndIf
  If _Red   > 255 : _Red   = 255 : EndIf
  If _Green > 255 : _Green = 255 : EndIf
  If _Blue  > 255 : _Blue  = 255 : EndIf

  ProcedureReturn RGB(_Red, _Green, _Blue)
EndProcedure

Procedure.i Make_GadgetButton(__ID.i, __X.i, __Y.i, __Width.i, __Height.i, __sText.s, __Color.i = $EFEFEF, __Flags.i = #GS_Button_Enabled)
  Protected.i _iIndex, _iResult = -1
  Protected.i _HV_HG_1, _HV_HG_2, _HV_BD_1, _HV_BD_2

  _HV_HG_1 = DoRGB(__Color, $10)
  _HV_HG_2 = DoRGB(__Color, -$0C)
  _HV_BD_1 = DoRGB(__Color, -$86)
  _HV_BD_2 = DoRGB(__Color, -$4F)

  If Not IsSprite(__ID)
    If CreateSprite(__ID, __Width * 3, __Height)
      StartDrawing(SpriteOutput(__ID))
        Box(0, 0, __Width * 3, __Height, __Color)
        For _iIndex = 0 To 2
          x1 = __Width * _iIndex
          x2 = __Width * (_iIndex + 1)
          Select _iIndex
            Case 0
              ;Ligne haut horizontale et gauche verticale 1
              ;Blanche
              LineXY(x1,0,x2-1,0,_HV_HG_1);$FFFFFF)
              LineXY(x1,0,x1,__Height,_HV_HG_1);$FFFFFF)
              ;line haut horizontale et gauche verticale 2
              ;Gris clair
              LineXY(x1+1,1,x2-2,1,_HV_HG_2);$E3E3E3)
              LineXY(x1+1,1,x1+1,__Height-1,_HV_HG_2);$E3E3E3)
              ;ligne bas droite verticale et bas horizontale 1
              ;Gris 1
              LineXY(x2-2,1,x2-2,__Height-2,_HV_BD_2);$A0A0A0)
              LineXY(x1+1,__Height-2,x2-2,__Height-2,_HV_BD_2);$A0A0A0)
              ;ligne bas droite verticale et bas horizontale 1
              ;Gris 2
              LineXY(x2-1,0,x2-1,__Height-1,_HV_BD_1);$696969)
              LineXY(x1,__Height-1,x2-1,__Height-1,_HV_BD_1);$696969)
              MakeImgText(#IMG_FONT,x1,__Width,0,__Height,__sText, #GS_Text_Center)
            Case 1
              ;Ligne haut horizontale et gauche verticale 1
              ;Gris 2
              LineXY(x1,0,x2-1,0,_HV_BD_1);$696969)
              LineXY(x1,0,x1,__Height,_HV_BD_1);$696969)
              ;line haut horizontale et gauche verticale 2
              ;Gris 1
              LineXY(x1+1,1,x2-2,1,_HV_BD_2);$A0A0A0)
              LineXY(x1+1,1,x1+1,__Height-1,_HV_BD_2);$A0A0A0)
              ;ligne bas droite verticale et bas horizontale 1
              ;Gris clair
              LineXY(x2-2,1,x2-2,__Height-2,_HV_HG_2);$E3E3E3)
              LineXY(x1+1,__Height-2,x2-2,__Height-2,_HV_HG_2);$E3E3E3)
              ;ligne bas droite verticale et bas horizontale 1
              ;Blanche
              LineXY(x2-1,0,x2-1,__Height-1,_HV_HG_1);$FFFFFF)
              LineXY(x1,__Height-1,x2-1,__Height-1,_HV_HG_1);$FFFFFF)
              MakeImgText(#IMG_FONT,x1+1,__Width,1,__Height,__sText, #GS_Text_Center)
            Case 2
              ;Ligne haut horizontale et gauche verticale 1
              ;Blanche
              LineXY(x1,0,x2-1,0,_HV_HG_1);$FFFFFF)
              LineXY(x1,0,x1,__Height,_HV_HG_1);$FFFFFF)
              ;line haut horizontale et gauche verticale 2
              ;Gris clair
              LineXY(x1+1,1,x2-2,1,_HV_HG_2);$E3E3E3)
              LineXY(x1+1,1,x1+1,__Height-1,_HV_HG_2);$E3E3E3)
              ;ligne bas droite verticale et bas horizontale 1
              ;Gris 1
              LineXY(x2-2,1,x2-2,__Height-2,_HV_BD_2);$A0A0A0)
              LineXY(x1+1,__Height-2,x2-2,__Height-2,_HV_BD_2);$A0A0A0)
              ;ligne bas droite verticale et bas horizontale 1
              ;Gris 2
              LineXY(x2-1,0,x2-1,__Height-1,_HV_BD_1);$696969)
              LineXY(x1,__Height-1,x2-1,__Height-1,_HV_BD_1);$696969)
              MakeImgText(#IMG_FONT,x1,__Width,0,__Height,__sText, #GS_Text_Center)
              MakeImgText(#IMG_FONT,x1+1,__Width,1,__Height,__sText, #GS_Text_Center)
          EndSelect
        Next
      StopDrawing()
      
      CompilerIf Defined(savepng, #PB_Constant) = #True
        SaveSprite(__ID,"SPR_GUI_"+Str(__ID)+".PNG",#PB_ImagePlugin_PNG)
      CompilerEndIf

      AddElement(GadgetButton())
        GadgetButton()\ID       = __ID
        GadgetButton()\Type     = #GADGET_Button
        GadgetButton()\X        = __X
        GadgetButton()\Y        = __Y
        GadgetButton()\Width    = __Width
        GadgetButton()\Height   = __Height
        GadgetButton()\Text     = __sText
        GadgetButton()\Flags    = __Flags
        GadgetButton()\Color    = __Color
        GadgetButton()\ParentID = -1
      _iResult = __ID
    Else
      _iResult = -1
    EndIf
  Else
    _iResult = -1
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure SetMouseStatus(__Value.i)
  iMouseStatus = __Value
EndProcedure

Procedure.i GetMouseStatus()
  ProcedureReturn iMouseStatus
EndProcedure

;- Procédures GUI
Procedure GS_Init()
  UsePNGImageDecoder()

  If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
    MessageRequester("Error", "Can't open the sprite system", 0)
    End
  EndIf
EndProcedure

Procedure.i GS_WindowID(__Window.i)
  Protected.i _iResult = -1

  If FindMapElement(GadgetWindow(), Str(__Window))
    _iResult = Val(MapKey(GadgetWindow()))
    ;GS_DrawText(1, #SCREEN_Height - (#FONT_OUT_HEIGHT*3), "Window ID = "+Str(_iResult))
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__Window))
    End
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure.i GS_WindowHeight(__Window.i)
  Protected.i _iResult = -1

  If FindMapElement(GadgetWindow(), Str(__Window))
    _iResult = GadgetWindow()\Height
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__Window))
    End
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure.i GS_WindowWidth(__Window.i)
  Protected.i _iResult = -1

  If FindMapElement(GadgetWindow(), Str(__Window))
    _iResult = GadgetWindow()\Width
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__Window))
    End
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure.i GS_WindowX(__Window.i)
  Protected.i _iResult = -1

  If FindMapElement(GadgetWindow(), Str(__Window))
    _iResult = GadgetWindow()\X
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__Window))
    End
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure.i GS_WindowY(__Window.i)
  Protected.i _iResult = -1

  If FindMapElement(GadgetWindow(), Str(__Window))
    _iResult = GadgetWindow()\Y
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__Window))
    End
  EndIf

  ProcedureReturn _iResult
EndProcedure

Procedure GS_TextGadget(__X.i,__Y.i,__sText.s, __ParentID.i = -1)
  Protected.i _iLen = Len(__sText)
  Protected.s _sChar
  Protected.i _sAscii, _iFontLine, _iClipX, _iClipY
  Protected.i _iIndex
  Protected.i _x = __X, _y = __Y

  If __ParentID <> -1
    If FindMapElement(GadgetWindow(), Str(__ParentID))
      _x = GadgetWindow()\X + __X
      _y = GadgetWindow()\Y + __Y
      If GadgetWindow()\Flags & #GS_Windows_Border_simple = #GS_Windows_Border_simple
        _x + #BORDER_SIMPLE
        _y + #BORDER_SIMPLE
      EndIf
      If GadgetWindow()\Flags & #GS_Windows_Border_Double = #GS_Windows_Border_Double
        _x + #BORDER_DOUBLE
        _y + #BORDER_DOUBLE
      EndIf
      If GadgetWindow()\Flags & #GS_Windows_Border_Triple = #GS_Windows_Border_Triple
        _x + #BORDER_TRIPLE
        _y + #BORDER_TRIPLE
      EndIf
    Else
      MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__ID))
      End
    EndIf
  EndIf
  
  For _iIndex = 1 To _iLen
    _sChar     = Mid(__sText,_iIndex,1)
    _sAscii    = Asc(_sChar) - 32
    _iClipX    = (_sAscii % #NB_CHAR_OUT_BY_LINE) * #FONT_OUT_WIDTH
    _iClipY    = (_sAscii / #NB_CHAR_OUT_BY_LINE) * #FONT_OUT_HEIGHT
    ClipSprite(#SPR_FONT_OUT, _iClipX, _iClipY, #FONT_OUT_WIDTH, #FONT_OUT_HEIGHT)
    DisplayTransparentSprite(#SPR_FONT_OUT, _x, _y)
    _x + #FONT_OUT_WIDTH
  Next
EndProcedure

Procedure.i GS_OpenWindow(__ID.i, __X.i, __Y.i, __Width.i, __Height.i, __sTitle.s = "", __Color.i = $FFFFFF, __Alpha.i = 255, __Flags.i = #GS_Windows_BorderLess)
  If __ID = #PB_Any
    __ID = GetIDGadget()
  EndIf

  ; Si le sprite Window existe déjà pas la peine de le créer une nouvelle fois
  If Not IsSprite(__ID)
    CreateSprite(__ID, __Width, __Height)
    AddMapElement(GadgetWindow(), Str(__ID))
      GadgetWindow()\X        = __X
      GadgetWindow()\Y        = __Y
      GadgetWindow()\Width    = __Width
      GadgetWindow()\Height   = __Height
      GadgetWindow()\Title    = __sTitle
      GadgetWindow()\Flags    = __Flags
      GadgetWindow()\Color    = __Color
      GadgetWindow()\Alpha    = __Alpha
      GadgetWindow()\ParentID = -1
  EndIf

  StartDrawing(SpriteOutput(__ID))
    If __Color = 0 : __Color = 1 : EndIf
    ;_ColorRGBA = RGBA(Red(__Color), Green(__Color), Blue(__Color), __Alpha)
    Box(0,0,__Width,__Height,__Color)
    ;Box(0,0,__Width,__Height,_ColorRGBA)

    If __Flags & #GS_Windows_TitleBar = #GS_Windows_TitleBar
      Box(0,0,__Width, #FONT_OUT_HEIGHT+4, RGBA(1,1,1,0))
      MakeImgText(#IMG_FONT_OUT, 5, 10, 0, 2, "Title")
    EndIf

    If __Flags & #GS_Windows_Border_simple = #GS_Windows_Border_simple
      Box(0,0,__Width,__Height,$FFFFFF)
      Box(#BORDER_SIMPLE,#BORDER_SIMPLE,__Width-(#BORDER_SIMPLE*2),__Height-(#BORDER_SIMPLE*2),__Color)
    EndIf

    If __Flags & #GS_Windows_Border_Double = #GS_Windows_Border_Double
      Box(0,0,__Width,__Height,$FFFFFF)
      Box(#BORDER_DOUBLE,#BORDER_DOUBLE,__Width-(#BORDER_DOUBLE*2),__Height-(#BORDER_DOUBLE*2),__Color)
    EndIf

    If __Flags & #GS_Windows_Border_Triple = #GS_Windows_Border_Triple
      Box(0,0,__Width,__Height,$FFFFFF)
      Box(#BORDER_TRIPLE,#BORDER_TRIPLE,__Width-(#BORDER_TRIPLE*2),__Height-(#BORDER_TRIPLE*2),__Color)
    EndIf
  StopDrawing()

  ProcedureReturn __ID
EndProcedure

Procedure.i GS_DrawWindow(__ID.i, __X.i, __Y.i, __Alpha.i = -1)
  If FindMapElement(GadgetWindow(), Str(__ID))
    GadgetWindow()\X = __X
    GadgetWindow()\Y = __Y
    If __Alpha = -1 : __Alpha = GadgetWindow()\Alpha : EndIf
    StartSpecialFX()
      DisplayTranslucentSprite(__ID.i, __X.i, __Y.i, __Alpha)
    StopSpecialFX()
    ;DisplayTransparentSprite(__ID.i, __X.i, __Y.i)
  Else
    MessageRequester("Bad WindowID", "Cannot open Window ID :"+Str(__ID))
    End
  EndIf
EndProcedure

Procedure.i GS_ButtonGadget(__ID.i, __X.i, __Y.i, __Width.i, __Height.i, __sText.s, __Color.i = $EFEFEF, __Flags.i = #GS_Button_Enabled)
  Protected.i _iResult = -1

  If __ID = #PB_Any
    __ID = GetIDGadget()
  EndIf
  
  _iResult = Make_GadgetButton(__ID, __X, __Y, __Width, __Height, __sText, __Color, __Flags)

  ProcedureReturn _iResult
EndProcedure

Procedure GS_DrawGadget()
  Protected.i _iClipPos = 0
  ForEach GadgetButton()
    With GadgetButton()
      If \Flags = #GS_Button_Enabled  : _iClipPos = \Width * 0 : EndIf
      If \Flags = #GS_Button_Disabled : _iClipPos = \Width * 1 : EndIf
      If \Flags = #GS_Button_Pushed   : _iClipPos = \Width * 2 : EndIf
      ClipSprite(\ID,_iClipPos,0,\Width,\Height)
      DisplaySprite(\ID,\X,\Y)
    EndWith
  Next
EndProcedure

;- Event Gadgets
Procedure.i GS_EventGadget()
  Protected.i _x1, _x2, _y1, _y2
  Protected.i _iClipPos, _iResult = -1

  ForEach GadgetButton()
    _x1 = GadgetButton()\X
    _x2 = _x1 + GadgetButton()\Width - 1                        ; -1 obligatoire
    _y1 = GadgetButton()\Y
    _y2 = _y1 + GadgetButton()\Height - 1                       ; -1 obligatoire
    SetMouseStatus(GetMouseStatus() | #GS_EventType_LostFocus | #GS_EventType_MouseUp)
    If iPosX >= _x1 And iPosX <= _x2 And iPosY >= _y1 And iPosY <= _y2
;       If iMouseStatus & #GS_EventType_MouseOver   : Debug "#GS_EventType_MouseOver"   : EndIf
;       If iMouseStatus & #GS_EventType_MouseUp     : Debug "#GS_EventType_MouseUp"     : EndIf
;       If iMouseStatus & #GS_EventType_MouseDown   : Debug "#GS_EventType_MouseDown"   : EndIf
;       If iMouseStatus & #GS_EventType_LeftClick   : Debug "#GS_EventType_LeftClick"   : EndIf
; ;       If iMouseStatus & #GS_EventType_MiddleClick : Debug "#GS_EventType_MiddleClick" : EndIf
;       If iMouseStatus & #GS_EventType_RightClick  : Debug "#GS_EventType_RightClick"  : EndIf
; ;       If iMouseStatus & #GS_EventType_Focus       : Debug "#GS_EventType_Focus"       : EndIf
; ;       If iMouseStatus & #GS_EventType_LostFocus   : Debug "#GS_EventType_LostFocus"   : EndIf
      SetMouseStatus(GetMouseStatus() | #GS_EventType_MouseOver)
      If iBut_left = #False And GetMouseStatus() & #GS_EventType_LeftClick = #GS_EventType_LeftClick
        SetMouseStatus(#GS_EventType_Focus | #GS_EventType_MouseUp)
        _iResult = GadgetButton()\ID
        iLastEvent = #GS_EventType_LeftClick
      EndIf
      If iBut_left
        ;Debug "Displaying sprite #"+Str(GadgetButton()\ID)
        SetMouseStatus(#GS_EventType_LeftClick | #GS_EventType_MouseDown | #GS_EventType_MouseOver)
        ClipSprite(GadgetButton()\ID,GadgetButton()\Width*1,0,GadgetButton()\Width,GadgetButton()\Height)
        DisplaySprite(GadgetButton()\ID,_x1,_y1)
      EndIf
    Else
      _iResult   = -1
      iLastEvent = GetMouseStatus()
    EndIf
  Next

  ProcedureReturn _iResult
EndProcedure

Procedure.i GS_EventType()
  ProcedureReturn iLastEvent
EndProcedure

;- Création Gadgets
Procedure CreateGadget()
  GS_ButtonGadget(#PB_Any,  10,  20, 100, 25, "Hello There !")
  GS_ButtonGadget(#PB_Any,  20,  60, 100, 50, "OK")
  GS_ButtonGadget(#PB_Any, 120,  60, 100, 50, "Cancel")
  iButtonQuit = GS_ButtonGadget(#PB_Any, 450, 320, 100, 50, "Quit", $FAEAAA)
;   iTestWin = GS_OpenWindow(#PB_Any, 15, 20, 300, 200, "", RGB(128,128,255), 64, #GS_Windows_TitleBar)
;   iTestWin = GS_OpenWindow(#PB_Any, 15, 20, 300, 200, "", RGB(128,128,255), 64, #GS_Windows_BorderLess)
  iTestWin1 = GS_OpenWindow(#PB_Any, 0, 0, 300, 200, "", RGB(128,128,255), 64, #GS_Windows_Border_Triple)
  iTestWin2 = GS_OpenWindow(#PB_Any, 0, 0, 120, 100, "", RGB(128,255,128), 64, #GS_Windows_Border_simple)
  iTestWin3 = GS_OpenWindow(#PB_Any, 0, 0,  80,  60, "", RGB(255,128,100), 255)
  ; pour les fades
  ; Black
  iTestWin4 = GS_OpenWindow(#PB_Any, 0, 0, #SCREEN_Width/2, #SCREEN_Height/2, "", RGB(0,0,0), 0)
  ; White
  iTestWin5 = GS_OpenWindow(#PB_Any, 0, 0, #SCREEN_Width/2, #SCREEN_Height/2, "", RGB(255,100,100), 0)
EndProcedure

Procedure Draw_MainWindow()
  If OpenWindow(#MAIN_WIN, 0, 0, #SCREEN_Width, #SCREEN_Height, "GOSE GUI V#"+#GS_VERSION, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
    If OpenWindowedScreen(WindowID(#MAIN_WIN), 0, 0, #SCREEN_Width, #SCREEN_Height, 0, 0, 0)
      ; Sprite Font Out
      CatchSprite(#SPR_FONT_OUT,  ?_DS_SPR_Font_Out)
      TransparentSpriteColor(#SPR_FONT_OUT, $FF00FF)
      ; Image Font & Font Out
      CatchImage(#IMG_FONT,       ?_DS_IMG_Font)
      CatchImage(#IMG_FONT_OUT,   ?_DS_IMG_Font_Out)
      ; Création du sprite de la souris
      CatchSprite(#SPR_MOUSE,     ?_DS_SPR_CURSOR_DATA)
      TransparentSpriteColor(#SPR_MOUSE,$FF00FF)
      ;     SaveSprite(#SPR_MOUSE,"Img_Spr\SPR_MOUSE.png",#PB_ImagePlugin_PNG)
      ; Création des gadgets
      CreateGadget()
    Else
      MessageRequester("Error", "Can't open windowed screen!", 0)
      End
    EndIf
  EndIf
EndProcedure

Procedure ProcessEvent()
  Protected.i _iInside        = #False
  Protected.i _iQuit          = 0
  Protected.i _iEventWindow, _iEventGadget
  Protected.i _iMousePosX, _iMousePosY    ;, _iPosX, _iPosY
  Protected.i _iElement                   ;_iBut_left, _iBut_middle, _iBut_right
  Protected.i _iFade = 0, _iSens = 1

  Repeat
    Repeat
      _iEventWindow = WaitWindowEvent(5)
      Select _iEventWindow
        Case #PB_Event_CloseWindow
          _iQuit = 1
      EndSelect
    Until _iEventWindow = 0
  
    FlipBuffers()

    If _iInside = #True : ExamineMouse() : EndIf
    iBut_left    = MouseButton(#PB_MouseButton_Left)
    iBut_middle  = MouseButton(#PB_MouseButton_Middle)
    iBut_right   = MouseButton(#PB_MouseButton_Right)

    If _iInside
      ; Verification si en dehors de la fenêtre de "screen"
      If MouseX() >= #SCREEN_Width - 1 Or MouseY() >= #SCREEN_Height - 1 Or MouseX() < 1 Or MouseY() < 1
        ReleaseMouse(1)
        _iInside = #False
      EndIf
    Else
      _iMousePosX = WindowMouseX(#MAIN_WIN) : _iMousePosY = WindowMouseY(#MAIN_WIN)
      ; Verification si on se retrouve à l'intérieur de la fenêtre de "screen"
      If _iMousePosX < #SCREEN_Width And _iMousePosX > 0 And _iMousePosY > 0 And _iMousePosY < #SCREEN_Height
        ReleaseMouse(0)
        MouseLocate(_iMousePosX, _iMousePosY) ;Obligatoire car ReleaseMouse(0) remet les coordonées de la souris à 0,0
        _iInside = #True
      EndIf
    EndIf

    ExamineKeyboard()
    iPosX = MouseX() : iPosY = MouseY()

    ; Efface le screen
    ClearScreen(RGB(200,200,200))
    GS_DrawGadget()
    _iEventGadget = GS_EventGadget()
    Select _iEventGadget
      Case iButtonQuit
;   Select GS_EventType()
;     Case #GS_EventType_LeftClick       ; Left mouse button click
;     Case #GS_EventType_RightClick      ; right mouse button click
;     Case #GS_EventType_LeftDoubleClick ; Left mouse button double click
;     Case #GS_EventType_RightDoubleClick; Right mouse button double click
;     Case #GS_EventType_Focus           ; Get the focus.
;     Case #GS_EventType_LostFocus       ; Lose the focus.
        Select GS_EventType()
          Case #GS_EventType_LeftClick
            _iQuit = #True
        EndSelect
    EndSelect

    GS_DrawWindow(iTestWin1, 170, 70, 200):GS_TextGadget(0,0,"TestWin 1",GS_WindowID(iTestWin1))
    GS_TextGadget(1,GS_WindowHeight(iTestWin1) - #FONT_OUT_HEIGHT - 8,"Coucou les gens ! Comment ca-va bien ?",GS_WindowID(iTestWin1))
    GS_DrawWindow(iTestWin2, 210, 90, 128):GS_TextGadget(0,0,"TestWin 2",GS_WindowID(iTestWin2))
    GS_DrawWindow(iTestWin3, 260, 60, 200):GS_TextGadget(0,0,"TestWin 3",GS_WindowID(iTestWin3))
    GS_DrawWindow(iTestWin4, 0, 0, _iFade)
    GS_DrawWindow(iTestWin5, #SCREEN_Width/2, #SCREEN_Height/2, _iFade)

    GS_TextGadget(1, #SCREEN_Height - #FONT_OUT_HEIGHT, "Mouse X: "+Str(iPosX)+" - Mouse Y: "+Str(iPosY))
    ; Affiche la souris ssi à l'intérieur du screen
    If _iInside = #True : DisplayTransparentSprite(#SPR_MOUSE, iPosX, iPosY) : EndIf
    ; Vérification si appuie sur touche 'Esc'
    If KeyboardPushed(#PB_Key_Escape)
      _iQuit = #True
    EndIf
    If _iFade >= 255
      _iSens =  -#Val_INCR
    EndIf
    If _iFade <= 0
      _iSens =  #Val_INCR
    EndIf

    _iFade + _iSens
  Until _iQuit
EndProcedure

;---- Main ---
CompilerIf Defined(savepng, #PB_Constant) = #True
  UsePNGImageEncoder()
CompilerEndIf
GS_Init()
Draw_MainWindow()
ProcessEvent()
End
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Jeu] interface et Screen

Message par blendman »

salut

Merci pour vos exemples, c'est vraiment intéressant.

Je pense que c'est un très bon sujet, d'autant plus important qu'il est indispensable à la création d'un jeu.

Donc, si on arrive à avoir une sorte de lib facilement exploitable pour du jeu, ce sera vraiment génial.
Répondre