Question FLIPBUFFER

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
drfloyd
Messages : 220
Inscription : mar. 21/août/2007 13:30
Contact :

Question FLIPBUFFER

Message par drfloyd »

Bonjour le fofo,

Après une pause pour développer un jeu en GFA sur Atari ST (si ca interesse quelqu'un je peux donner le lien) je vais revenir au PURE BASIC.

Par contre quelque chose m'interpelle au niveau du rafraichissement de l'écran... Vs le GFA BASIC

Je ne sais trop comment expliquer, je reste un débutant. Je tente :

En PURE le rafraichissement se fait via un swap d'écran avec FLIPBUFFERS, ok, c'est classique. En GFA ce n'est pas tout à fait pareil :

En GFA quand je fais un rafraichissement d'écran, ca affiche "en rab" tout ce que j'ai dessiné depuis le dernier rafraichissement... Ce n'est pas un FLIP traditionnel. Je ne sais pas comment on peut appeler ça. Ce qui était super pratique pour mon jeu de type RPG, je pouvais dans une meme boucle de jeu mettre plein de rafraichissements... genre pour faire une pause dialogues dans la boucle de jeu, ou une pause illustrations en surimpression, sans faire tourner la boucle.

En PURE si je fais ca ca crée plein de bugs visuels/clignotements, du au flip de buffers (ce qui est normal)

Je ne sais pas si c'est clair ??? Je vous avais prévenu, je suis un novice ;)

Ma question : est-il possible de fonctionner sur le principe du GFA en PURE ? (afin d'adapter facilement mon jeu sans revoir toute la structure)

Merci
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Question FLIPBUFFER

Message par Ollivier »

Oui, non et peut-être.

Oui, parce qu'au lieu de d'afficher tous les sprites, tu peux dessiner les images de ces sprites dans un seul sprite, à condition de ne pas transformer ces sprites. Puis tu affiche ton sprite avant une synchro.

Non, parce qu'en plus des transformations en temps réel, pureBasic peut afficher x sprites un peu n'importe comment, avec des clippages et de la transparence, et que faire la même dans un seul sprite est beaucoup plus lent.

Peut-être, en fonctionnant un peu comme autocad, en travaillant avec les sprites comme des calques. Dans ce cas une synchro ne nécessite pas toute la boucle mais un minimum d'affichage complexe et cohérent quand même (une boucle d'affichage dans un ordre précis).
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Question FLIPBUFFER

Message par Mesa »

il faudrait donner un exemple stp.

M.
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Question FLIPBUFFER

Message par case »

salut, donne le lien ! :) :mrgreen:
ImageImage
drfloyd
Messages : 220
Inscription : mar. 21/août/2007 13:30
Contact :

Re: Question FLIPBUFFER

Message par drfloyd »

Bon j'ai réussi en créant comme suggéré un sprite de tout l'écran

ici un exemple "yaourt" d'affichage de texte avec pauses au sein d'une boucle :

Code : Tout sélectionner

  
  
 Procedure fond()
   DisplaySprite(99,0,0)
 EndProcedure
 
 Procedure aff()
    FlipBuffers()
 EndProcedure
 
 Procedure aff2()
   GrabSprite(99,0,0,800,600)
   FlipBuffers()
EndProcedure
 
 
 Repeat 
  ..... debut de la boucle......
  
  ; une condition pour afficher la case avec du texte
  If enter()

    text (200,200,"HELLLOOOOOOOOOOOOOOOO",couleurblanc)
    aff2()
    Delay (2000)
    
    fond() 
    text (200,250,"TESTTTTTTTT 2",couleurbleu)
    aff2()
    Delay(2000)
    
    fond()
    text (200,300,"TEST 3",couleurbleu)
    aff2()
    Delay(2000)
    
 EndIf
 
  aff()   ;le vrai flipbuffer de la boucle
 
 
 until ....... fin de la boucle
 
 

Ca marche, en gros à chaque fois j'affiche le fond capturé, le rajout, je recapture, et je rafraichi....
C'est du grand n'importe quoi ce code ou non ??? (je crains de connaitre la réponse LOL)
Peut on faire plus simple ???
Dernière modification par drfloyd le jeu. 17/nov./2022 7:23, modifié 4 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Question FLIPBUFFER

Message par Ar-S »

Les delay ça sent le freeze non ?
Je pense que créer 1 sprite géant qui prend toute la fenêtre puis dessiner d'autres sprites dedans n'est peut-être pas une bonne idée coté perf.. Je ne suis pas assez assidu en 2D pour en être sûr.

En openwindowedscreen j'utiliserai un timer sans hésiter.
Sans fenêtre un truc comme ça pourrait peut-être te convenir ?

En gros tu captes le temps avant ta boucle puis il suffit de le re-capter dans ta boucle..
un

Code : Tout sélectionner

if ElapsedMilliseconds() + temps >= 4000 And ElapsedMilliseconds() + temps < 6000
signifie : "si en cet instant le temps qui s'est écoulé est entre 4 sec et 6 sec"

Code : Tout sélectionner


If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
    MessageRequester("Erreur", "Impossible d'initialiser l'écran.")
    End
EndIf

;Ouverture de l'écran
If OpenScreen(800,600,32,"Exemple OpenScreen") = 0
    MessageRequester("Erreur", "Impossible d'ouvrir l'écran.")
    End
EndIf

;Boucle principale
temps = ElapsedMilliseconds()

Repeat
    
    ;Effacer complètement l'écran et afficher un fond gris
    ClearScreen(RGB(128,128,128))
    ExamineKeyboard() 

    StartDrawing(ScreenOutput())

    If ElapsedMilliseconds() + temps < 4000  
        t$ = "Salut ça va ?"
        couleur = #Green
        posX = 0
    ElseIf ElapsedMilliseconds() + temps >= 4000 And ElapsedMilliseconds() + temps < 6000
        t$ = "Oui et toi ?"
        couleur = #Red
        posX = 50
    ElseIf ElapsedMilliseconds() + temps >= 6000 And ElapsedMilliseconds() + temps < 9000
        t$ = "Top ! J'aime elapsemilliseconds"
        couleur = #Green
        posX = 0
    ElseIf ElapsedMilliseconds() + temps >= 9000 And ElapsedMilliseconds() + temps < 11000
        t$ = "Fin dialogue"
        couleur = $111111
    ElseIf ElapsedMilliseconds() + temps >= 11000 And ElapsedMilliseconds() + temps < 12000
        t$ = "bye"
        exit = 1
    EndIf
    ; On dessine toujours le même texte
    DrawText(posX, 0, t$, couleur, RGB(128,128,128))
    
    StopDrawing()
    
    FlipBuffers()
    
Until KeyboardPushed(#PB_Key_Escape) Or exit = 1

~~~~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
drfloyd
Messages : 220
Inscription : mar. 21/août/2007 13:30
Contact :

Re: Question FLIPBUFFER

Message par drfloyd »

oui bien sur ca c'est la methode classique,

Mais ce n'est pas un soucis de délai, le but est avant tout d'ouvrir une fenetre dans l'ecran global, avec des affichages en plusieurs etapes dans cette fenetre.

En fait je veux vraiment faire une pause de la boucle generale, et afficher des choses en plusieurs étapes durant cette pause de boucle.

Donc en gros :

affichage de la capture ecran
j'affiche mes graphismes de l'interface fenetré
recapture ecran avec les modif
flipbuffer
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Question FLIPBUFFER

Message par Mesa »

PureBasic recalcule le screen entier à chaque frame, on ne peut pas ajouter des choses en cours de traitement, à moins d'utiliser le buffer avec DrawingBuffer(), qui donne accès directement à la mémoire vidéo, mais son utilisation réclame de solides compétences.

Tu peux t'inspirer de ce code que je viens d'écrire à l'arrache mais qui marche.
On peut, capturer/relacher la souris et le clavier dans le screen, mettre en pause, et ouvrir/fermer une fenêtre "Enregistrer le jeu".

A toi de le modifier et de l'améliorer.

Code : Tout sélectionner

EnableExplicit


Global direction = 1
Global playerX = 1
Global playerY = 1

; Start with released input

Global InputReleased = 1
Global x,Event,Quit,Gadget, pausejeu,Touche$,Touche2$,Fenetre

Declare go()

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



OpenWindow(1,0,0,200,100,"Enregistrer jeu",#PB_Window_ScreenCentered|#PB_Window_Invisible)
ButtonGadget( 10, 50,50,50,25, "Fermer")


If OpenWindow(0, 0, 0, 360, 285, "Jeu: ESC, F1, F5", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ButtonGadget(1, 10,  10, 120, 25, "Capture Souris clavier")
	ButtonGadget(2, 140,  10, 100, 25, "Pause")
	ButtonGadget(3, 250,  10, 100, 25, "ok")
	TextGadget  (4, 10, 40, 300, 30, "Capturer Souris et clavier")
	
	If OpenWindowedScreen(WindowID(0), 10, 70, 340, 200, 0, 0, 0)
		LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasicLogo.bmp")
		CreateSprite(1,16,16)
		StartDrawing(SpriteOutput(1))
		DrawingMode(#PB_2DDrawing_Default )      
		Circle(8, 8, 8)
		StopDrawing()
		
		ReleaseMouse(#True)
		
		pausejeu=0
		
		Repeat
			Repeat
				; Always process all the events to flush the queue at every frame
				Event = WindowEvent()
				Fenetre = EventWindow()
				
				Select Event
					Case #PB_Event_CloseWindow
; 						If Fenetre=1
; 							HideWindow(1,#True)
; 						Else
							Quit = 1
; 						EndIf
						
					Case #PB_Event_Gadget
						
						; Do the normal application management here
						Gadget = EventGadget()
						
						Select Gadget
							Case 1
								InputReleased = 0
								ReleaseMouse(#False)
								SetGadgetText(4, "'F1' pour relacher clavier souris")
								
							Case 2
								SetGadgetText(4, "Bouton "+Str(Gadget)+" pressé.")
								If pausejeu=0
									pausejeu=1
									SetGadgetText(2,"go")
									
								Else
									pausejeu=0
									SetGadgetText(2,"pause")
									
								EndIf
								
							Case 10
								ReleaseMouse(#False)
								InputReleased = 0
								SetGadgetText(4, "clavier souris  relachés");
								HideWindow(1,#True)
								pausejeu=0
								
						EndSelect
						
				EndSelect
				
			Until Event = 0 ; Quit the event loop only when no more events are available
			
			If pausejeu=0
				go()
			EndIf
			
		Until  Quit Or KeyboardPushed(#PB_Key_Escape)
	Else
		MessageRequester("Error", "Can't open windowed screen!", 0)
	EndIf
EndIf

Procedure go()
	ExamineKeyboard()
	
	If InputReleased = 0
		
		ExamineMouse()
		
		;     Debug MouseX()
		
		; sprite et screen recalculés à chaque frame
		If KeyboardPushed(#PB_Key_Up)    And playerY > 0   : playerY -3 : EndIf  
		If KeyboardPushed(#PB_Key_Down)  And playerY < 280 : playerY +3 : EndIf  
		If KeyboardPushed(#PB_Key_Left)  And playerX > 0   : playerX -3 : EndIf  
		If KeyboardPushed(#PB_Key_Right) And playerX < 300 : playerX +3 : EndIf  
		
		If KeyboardPushed(#PB_Key_F1)
			ReleaseMouse(#True)
			InputReleased = 1
			SetGadgetText(4, "clavier souris relachés ")
			pausejeu=1
		EndIf
		
		If KeyboardPushed(#PB_Key_F5)
			ReleaseMouse(#True)
			InputReleased = 1
			SetGadgetText(4, "clavier souris  relachés");
			HideWindow(1,#False)
			pausejeu=1
		EndIf
		
		
	EndIf
	
	
	
	; Clear the screen and draw our sprites
	ClearScreen(RGB(0,0,0))
	ClipSprite(0, 0, 0, x, x/8)
	DisplaySprite(0, x, 100)
	DisplaySprite(0, x, x)
	DisplaySprite(0, 300-x, x)
	DisplaySprite(0, playerX, playerY)
	
	x + direction
	If x > 300 : direction = -1 : EndIf   
	If x < 0   : direction =  1 : EndIf   
	
	DisplaySprite(1, MouseX(),MouseY())
	
	Touche$=KeyboardInkey()
	If Touche$
		Touche2$=Touche$
	EndIf
	StartDrawing(ScreenOutput())
	DrawText( 10,10,Touche2$)
	StopDrawing()
	
	
	
	FlipBuffers()
EndProcedure
M.
drfloyd
Messages : 220
Inscription : mar. 21/août/2007 13:30
Contact :

Re: Question FLIPBUFFER

Message par drfloyd »

Merci pour vos aides

mais en fait la solution était hyper simple, il suffit de créer des boucles Flipbuffer dans la boucle principale...

exemple en mode "yaourt" :

Code : Tout sélectionner

 
  
  repeat
  
     affichages de l'ecran de jeu
  
  
    si appui sur ENTER
      u=0
      Repeat
       u+1
       BOX (180,180,200,200)
       text (200,200,"OUVERTURE FENETRE",couleurblanc)
       flipbuffer()   
     Until  u=1000
     Repeat
       u+1
       text (200,250,"CA MARCHE",couleurblanc)
       flipbuffer()   
     Until  u=2000
  endif

   flipbuffer

until ...


donc on peut très bien insérer des flipbuffer à l'interieur d'une boucle flipbuffer, du moment qu'on crée une sous-bloucle
Répondre