Page 1 sur 2

[jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 10:42
par blendman
salut

Dans mon jeu, j'ai besoin d'afficher des informations (texte) par exemple le nom des joueurs au dessus de leur tête, ou d'autres choses du genre.

Du coup, je fais beaucoup de :

Code : Tout sélectionner

start3D()
displaysprite3d()
stop3d()

StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
drawtext()
stopdrawing()

start3D()
etc..
Mais ça rame...

Il y a une technique pour ce genre de choses ? Je sais qu'il faut tout regrouper.

Mais pas exemple, j'ai des interfaces et le texte des personnages (leur nom) doit passer en dessous et pas au dessus... Le texte ne doit pas non passer au dessus d'une interface si elle est en dessous, etc.. Donc difficile de tout regrouper
Bref, existe-t-il des techniques qui font moins ramer ? par exemple, vaut-il mieux utiliser ScreenOutput() ou spriteoutput() ?

Merci pour les informations :D

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 13:11
par case
tu dois eviter de faire des start/stop a tout bout de champ tu dois penser en couches et surcouches

-> couche sol
affichage de tout les sprites du décor
-> couche objets
affichage de tout les sprites des objets (au sens large, mobs etc compris)
-> couche décor haut
affichage de tout les sprites du décor se trouvant plus haut que les objets au sol (feuillage)
-> couche objets haut
affichage de tout les sprites des objets (au sens large, mobs etc compris)se trouvant plus haut que le décor haut (oiseaux)
-> couche texte objets
affichage des noms des joueurs, etc
-> couche interface
affichage des fenêtres et autre morceaux de ton interface

un exemple je n'affiche pas vraiment le sol j'efface l'écran.
j'ai zappé les surcouches décor haut et objets haut...

Code : Tout sélectionner

InitSprite()
InitMouse() 
InitKeyboard()
; pour l'exemple création d'une pseudo interface
Structure gui
   ;coordones
   x.i   
   y.i   
   l.i   
   h.i      
   ; ordre d'affichage le plus petit = au dessus
   z.i  
   ;couleur
   col.i
   ;sprite
   spr.i
EndStructure


Structure joueur   
   x.i
   y.i
   name.s
EndStructure

; liste chainée de l'interface
Global NewList gui.gui()
Global NewList player.joueur()
; fenetre pour une sortie...
Global main=OpenWindow(#PB_Any,0,0,640,480,"test",#PB_Window_BorderLess)
;procedures
Declare makegui(x,y,l,h,col)
Declare Pick()
OpenWindowedScreen(WindowID(main),0,0,640,480,0,0,0)
; couleur transparente par defaut
TransparentSpriteColor(#PB_Default,$ff00ff)
; crée le pointeur de la souris
StartDrawing(ScreenOutput())
Box(0,0,10,10,$ff00ff)
Circle(4,4,4,$ffffff)
Circle(4,4,2,$000000)
StopDrawing()
Global pointer=GrabSprite(#PB_Any,0,0,10,10)
StartDrawing(ScreenOutput())
Box(0,0,30,30,$ff00ff)
Circle(14,14,14,$0)
Circle(14,14,12,$8888ff)
StopDrawing()
FlipBuffers()
Global play=GrabSprite(#PB_Any,0,0,28,28)


; crée des morceau d'interface au hazard
For a=1 To 5
   makegui(Random(400),Random(300),Random(200)+50,Random(100)+50,Random($ffffff))
Next
; cree des "joueurs" aleatoirement
For a = 1 To 30
   AddElement(player())
   player()\x=Random(600)
   player()\y=Random(450)
   For e= 1 To Random(12)+6
      player()\name+Chr(Random(96)+32)
   Next
Next

;
Repeat
   ExamineMouse()   
   ExamineKeyboard()
   ; affichagfe du fond 
   ClearScreen(0)      
   ; affichage mobs
   ForEach player()
            player()\x+Random(2)-1
      player()\y+Random(2)-1      

      DisplayTransparentSprite(play,player()\x-14,player()\y-14)
   Next      
   ; affichage des textes    
   StartDrawing(ScreenOutput())    
   DrawingMode(#PB_2DDrawing_Transparent)
   ForEach player()
      xs=TextWidth(player()\name)/2
      ys=TextHeight(player()\name)
      DrawText((player()\x-xs),player()\y-14-ys,player()\name)
   Next
   StopDrawing()   
   hover=Pick()
   If MouseButton(#PB_MouseButton_Left)
      If hover<>0
         If lastpick<>hover
            lastpick=hover
            gui()\z=$ffffffff ; passe au dessus
            SortStructuredList(gui(),#PB_Sort_Descending,OffsetOf(gui\z),#PB_Sort_Integer)
         Else
            gui()\x+MouseDeltaX()
            gui()\y+MouseDeltaY()
         EndIf      
      EndIf
   Else
      lastpick=0
   EndIf
   ForEach gui()             
      DisplaySprite(gui()\spr,gui()\x,gui()\y)      
   Next   
   DisplayTransparentSprite(pointer,MouseX(),MouseY())
   ev=WaitWindowEvent(0)
   FlipBuffers()
Until ev=#PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
Procedure makegui(x,y,l,h,col)
   AddElement(gui())
   gui()\x=x
   gui()\y=y
   gui()\l=l
   gui()\h=h
   gui()\spr=CreateSprite(#PB_Any,l,h)
   StartDrawing(SpriteOutput(gui()\spr))
      Box(0,0,l,h,col)
   StopDrawing()
   gui()\z=ListIndex(gui())
EndProcedure
Procedure Pick()
   ;sort the interface list
   ; verifie si la souris est au dessus d'un element du gui
   hover=0
   For E=ListSize(gui())-1 To 0 Step -1
      SelectElement(gui(),e)
      gui()\z=ListSize(gui())-ListIndex(gui()) ; 
      If MouseX()>=gui()\x And MouseY()>=gui()\y And MouseX()=<gui()\x+gui()\l And MouseY()<=gui()\y+gui()\h And hover=0         
         hover=ListIndex(gui())+1
      EndIf
   Next
   If hover=0
      FirstElement(gui())
      ProcedureReturn 0 ; au dessus de rien
   Else
      SelectElement(gui(),hover-1)
      ProcedureReturn 1 ; au dessus d'un élément du gui
   EndIf   
EndProcedure

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 16:20
par djes
+1 avec Case, ajout d'une composante Z (ou profondeur) à tous tes sprites, tri de la liste avant affichage groupé.

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 17:59
par Fig
Si tu as des textes qui changent peu souvent, c'est bien de les intégrer à des sprites pour gagner en ressources.

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 18:09
par djes
case> Super exemple!!! :D

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 18:11
par blendman
Case : merci, c'est intéressant comme exemple. Finalement, j'ai regroupé pas mal de choses et c'est effectivement mieux :).
Fig a écrit :Si tu as des textes qui changent peu souvent, c'est bien de les intégrer à des sprites pour gagner en ressources.
Donc, il vaut mieux un spriteoutput qu'un screenoutput (pour le startdrawing()) ?

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 19:35
par djes
Non, ce qu'il vaut mieux, c'est de ne pas utiliser de textes du tout, c'est une fonction très très lente. Donc, à terme, et si tu peux, tu en fais une toi-même avec des caractères "sprités". Bon, maintenant, les machines sont quand même très puissantes, donc garde ça pour la fin, à l'étape d'optim, si nécessaire...
Ca me fait penser à des jeunes au festival du jeu vidéo qui se plaignaient que leur jeu ramait dès qu'ils affichaient des textes. Sauf que l'affichage du texte était une routine postscript. 8O

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : dim. 08/mai/2011 20:00
par case
postscript 8O les malades !

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 8:30
par blendman
djes a écrit :Non, ce qu'il vaut mieux, c'est de ne pas utiliser de textes du tout, c'est une fonction très très lente. Donc, à terme, et si tu peux, tu en fais une toi-même avec des caractères "sprités". Bon, maintenant, les machines sont quand même très puissantes, donc garde ça pour la fin, à l'étape d'optim, si nécessaire...
ok, je garderai cette optimisation des texte par sprite pour la fin effectivement, si jamais je dois optimiser le jeu ;).

Par contre, je ne sais pas encore comment transformer un texte en affichage sur un sprite, à mon avis, il doit y avoir quelque part un exemple ou des procédures pour ça, non ?

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 9:07
par Fig
je crois que c'est:

Code : Tout sélectionner

startdrawing(spriteoutput(numero de sprite))
 ....drawtext(...)
stopdrawing()
Pour écrire dans un sprite...

Effectivement comme dit Djes tu peux utiliser des mots/lettres en sprite... (c'ets beaucoup plus rapide que d'écrire les mots directement). Mais je faisais plutôt allusion à ce genre de situation:
Par exemple tu as une barre avec tes ressources et la quantité associé:

Bois: 120 Argent: 420 ... Score : 1200 Vie: 2/4 etc

Tu créé un sprite au début du jeu contenant::

Bois:'________' Argent:'_______'Score:'_______'Vie:'________'

Ca évite de devoir l'écrire à chaque boucle. Tu affiche juste ce sprite puis tu n'as plus qu'a écrire les nombres associés. C'est déja ça de pris.

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 9:22
par Cool Dji
Salut Blendman,

Je n'utilise jamais la fonction Drawtext
J'ai des sprites de chacun des caractères à afficher.
La numérotation des sprites est croissante avec l'ordre du String$

Ainsi, j'utilise la procédure AfficheTextcentre3D()
Attention, cette procédure est pourrie dans le sens ou je fais des boucles imbriquées pour comparer la valeur de la lettre à afficher et en déduire le bon numéro de sprite.
Je dois optimiser ça en récupérant le n° Ascii du caractère et avec un tableau, pointer directement sur le bon n° de sprite...

La routine ci dessous-centre automatiquement un texte sur un écran de 800 pixel, il faut ajouter une position x dans la procédure...

La varaible FirstSpriteSmallFont correspond au 1er numéro du sprite des caractère ex :
! = sprinte n° FirstSpriteSmallFont
' = sprinte n° FirstSpriteSmallFont+1
# = sprinte n° FirstSpriteSmallFont+2
...

Code : Tout sélectionner


lobal String$ = " !'#$%&'()*+,-./0123456789:;=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}"

Global Texttest$ = "Mad Fire @ Cool Dji 2008-2009"

Procedure AfficheTextcentre3D(Text$,y.i,fondu.i)
  For i=1 To Len(Text$)  ; regarde les caractères à afficher les uns après les autres
   For j=1 To Len(String$) ; compare le caractère avec les caractères de la police
     If Mid(Text$,i,1)=Mid(String$,j,1) ; si les caractères sont les memes, on affiche le sprite du caractère
       DisplaySprite3D(FirstSpriteSmallFont+j-1,i*16+Random(1)+400-Len(Text$)*8-16, y+Random(1),fondu)
       j=Len(String$)
     EndIf 
   Next
 Next

EndProcedure

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 9:35
par Fig
:arrow: Super ! Tu sais combien tu gagnes en vitesse par rapport à un affichage réel avec drawtext ??

Blendman> Il faut savoir que la tu es obligé d'utiliser une police avec un espacement des lettres constants. Sinon il te faut une routine plus complexe pour prévoir les différentes associations de lettre et un espacement variable. (au moins réduire l'espacement pour 'i' et 'l')

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 9:45
par Cool Dji
Fig, je n'ai jamais fait de comparatif...

Pour la taille de caractères différentes, je dois avoir un autre exemple ou c'est pris en compte mais c'est guère plus compliqué.
Je vais corriger cette procédure avec un système de pointage et pas des tests comparatifs.

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 15:05
par case
le plus simple pour du texte en sprite c'est au debut du programme de créer un tableau a 255 entrée avec tes sprites dedans dans la bonne case

mettons que j'ai une font bitmap avec les caracteres dans cet ordre

ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890=+-*/

au debut je crée mon tableau

Code : Tout sélectionner

global dim ascii.i(255)
il est judicieux de créer un tableau avec une structure pour y sauver plusieurs sprites pour la même lettre par exemple la version sprite et la version sprite3D si on en a besoin pour l'exemple je resterais avec simplement les sprites 2D.

Code : Tout sélectionner

structure fnt3d
  f2d.i
  f3d.I
endstructure
global dim ascii.fnt3d(255)
je charge l'image dans un sprite

Code : Tout sélectionner

  font=loadsprite(#pb_any,"font.bmp")
je crée une string avec les mêmes caractères dans le même ordre c'est ma clé de décodage de la font bitmap

Code : Tout sélectionner

key$=" ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890=+-*/"
ensuite je crée mes sprites a l'aide d'une boucle et je stocke dans le tableau chaque id de sprite

Code : Tout sélectionner

for a=1 to len(key$)
  clipsprite(font,(a-1)*16,0,16,16)
  displaysprite(font,0,0)
  ascii(asc(mid(key$,a,1)))= grabsprite(#pb_any,0,0,16,16) ; utiliser le mode texture pour un sprite 3D
next
freesprite(font)
ensuite pour afficher ma ligne de texte je n'ai plus qu'a faire un

Code : Tout sélectionner

ma phrase = "SALUT LES COPAINS, PUREBASIC C'EST GENIAL"
for a=1 to len(ma phrase)
ch=ascii(asc(mid(key$,a,1)))
if issprite(ch) ; vérifie que le sprite est valide pour eviter une erreur si le caractere n'est pas dans la font bitmap...
   displaysprite(ch,(a-1)*16,0)
endif
next a

Re: [jeu] 2D : displaysprite3d() et drawtext()

Publié : lun. 09/mai/2011 15:10
par Cool Dji
Nickel Case :D