[2D] Flip Horizonal

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

[2D] Flip Horizonal

Message par falsam »

J'essaye de coder un flip horizontal d'un sprite. Mais je n'obtiens pas le résultat voulu.

Le sprite se retrouve superposé sur son image d'origine. Le mieux est de vous laisser un code exemple.

Appuyé sur la barre d'espace pour exécuter le flip Horizontal. Vous verrez dans ce code que j'ai commenté le redimentionneme du sprite car ça ne fonctionne pas non plus. Peut être que je ne l'emploie pas comme il faut. Merci de l'aide que vous pouvez m'accorder.

Si quelqu'un a dans sa besace un code sans API qui fonctionne, je suis bien entendu preneur.

Code : Tout sélectionner

Enumeration
  #MainForm
EndEnumeration

Global Event, Sprite

Procedure SpriteFlipHorizontal(Sprite)
  Protected Width = SpriteWidth(Sprite)
  Protected Height = SpriteHeight(Sprite)
  Protected Dim ColorsArray(Width, height), x, y
    
  StartDrawing(SpriteOutput(Sprite))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  
  For y = 0 To Height-1
    For x = 0 To Width-1  
      ColorsArray(x,y) = Point(x,y)                
    Next x    
  Next y    
   
  For y = 0 To Height-1
    For x = Width-1 To 0 Step -1 
      Plot((SpriteWidth(Sprite)-1)-x, y , ColorsArray(x,y))      
    Next  
  Next 
  
  StopDrawing()
EndProcedure  

Procedure GameStart()
  Protected cr.b = #True
  Protected Width = 800
  Protected Height = 600
  
  UsePNGImageDecoder()
    
  InitNetwork()
  ReceiveHTTPFile("http://s242132022.onlinehome.fr/Download/PureBasic/platform_bench_2.png", GetTemporaryDirectory()+"image.png")
    
  InitSprite() : InitKeyboard() : InitMouse() : InitSound()
  
  OpenWindow(#mainform, 0, 0, Width, Height, "New Game", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  OpenWindowedScreen(WindowID(#mainform), 0, 0, Width, Height)        
  Sprite = LoadSprite(#PB_Any, GetTemporaryDirectory()+"image.png", #PB_Sprite_AlphaBlending)
  
  Repeat  
    Repeat
      Event = WindowEvent()
     
      Select event    
        Case #PB_Event_CloseWindow
          End
      EndSelect  
    Until event=0
    
    FlipBuffers()
    ClearScreen(RGBA(245, 222, 179, 255))
                
    ExamineKeyboard()
    If KeyboardReleased(#PB_Key_Space)
      SpriteFlipHorizontal(Sprite)
    EndIf   
    
    DisplayTransparentSprite(Sprite, 0, 0)
    ;ZoomSprite(Sprite, 500, 300)
  Until KeyboardPushed(#PB_Key_Escape)
  
  DeleteFile(GetTemporaryDirectory()+"image.png")
EndProcedure

GameStart()
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

arretez , avec vos double Repeat !!

c'est du n'importe quoi , faut pas coder comme ça 8O
je viens de voir qu'il y a des exemples sur ce model , c'est n'importe quoi ....
je ne sais pas qui code les exemples , mais chapeau !! :roll:



ton probleme viens du fait que lorsque tu met ton image en tableau , et que tu la dessine
tu n'efface pas entre les 2 ...
donc la fois d'apres, ça met dans le tableau ce qui n'a pas été effacé ...
d'ou le reste de ton sprite

alors tu te trouves dans un bloc StartDrawing-StopDrawing , impossible de faire appel
a clearScreen() ...

donc, il faut ruser et employer un Box par exemple :)

Code : Tout sélectionner

Enumeration
	#MainForm
EndEnumeration

Global Event, Sprite
Declare  catch_sprite(sprite)
Declare  SpriteFlipHorizontal(Sprite)
Declare  GameStart()




Procedure catch_sprite(sprite)
	Protected Width = SpriteWidth(Sprite)
	Protected Height = SpriteHeight(Sprite)
	Global Dim ColorsArray(Width, height), x, y
	
	StartDrawing(SpriteOutput(Sprite))
		
		For y = 0 To Height-1
			For x = 0 To Width-1 
				ColorsArray(x,y) = Point(x,y)             
			Next x   
		Next y   
		
	StopDrawing()
	
	TransparentSpriteColor(Sprite,$0)
Endprocedure





Procedure SpriteFlipHorizontal(Sprite)
	Protected Width = SpriteWidth(Sprite)
	Protected Height = SpriteHeight(Sprite)
	StartDrawing(SpriteOutput(Sprite))
		Box(0,0,Width, height,RGB(245, 222, 179))
		For y = 0 To Height-1
			For x = Width-1 To 0 Step -1
				if ColorsArray(x,y)<>0
					Plot((SpriteWidth(Sprite)-1)-x, y , ColorsArray(x,y))   
				Endif
			Next 
		Next
	StopDrawing()
EndProcedure 

Procedure GameStart()
	Protected cr.b = #True
	Protected Width = 1024
	Protected Height = 768
	
	UsePNGImageDecoder()
	
	InitNetwork()
	ReceiveHTTPFile("http://s242132022.onlinehome.fr/Download/PureBasic/platform_bench_2.png", GetTemporaryDirectory()+"image.png")
	
	InitSprite() : InitKeyboard() : InitMouse() : InitSound()
	
	OpenWindow(#mainform, 0, 0, Width, Height, "New Game", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
	OpenWindowedScreen(WindowID(#mainform), 0, 0, Width, Height)       
	Sprite = LoadSprite(#PB_Any, GetTemporaryDirectory()+"image.png", #PB_Sprite_AlphaBlending)
	
	Repeat
		
		Event = WindowEvent()
		
		Select event   
			Case #PB_Event_CloseWindow
			End
		EndSelect 
		
		
		ExamineKeyboard()
		
		If KeyboardReleased(#PB_Key_Space)
			catch_sprite(sprite)
			SpriteFlipHorizontal(Sprite)
		EndIf   
		
		ClearScreen(RGB(245, 222, 179))
		DisplaytransparentSprite(Sprite, 0, 0)
		
		FlipBuffers()
		
		;ZoomSprite(Sprite, 500, 300)
	Until KeyboardPushed(#PB_Key_Escape)
	
	DeleteFile(GetTemporaryDirectory()+"image.png")
EndProcedure

GameStart() 
; Epb



Dernière modification par Backup le lun. 31/mars/2014 0:36, modifié 1 fois.
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

Re: [2D] Flip Horizonal

Message par majikeyric »

Dobro a écrit :arretez , avec vos double Repeat !!

c'est du n'importe quoi , faut pas coder comme ça 8O
Bein si, il faut :mrgreen:

C'est toi qui n'a pas compris la finalité du deuxième "repeat" :)
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

Re: [2D] Flip Horizonal

Message par majikeyric »

Je pense que le vrai problème venait du canal alpha avec l'emploi du 'plot'.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

j'ai corrigé mon code , maintenant ça marche :)







majikeyric a écrit :
Dobro a écrit :arretez , avec vos double Repeat !!

c'est du n'importe quoi , faut pas coder comme ça 8O
Bein si, il faut :mrgreen:

C'est toi qui n'a pas compris la finalité du deuxième "repeat" :)
bien -sur , je ne comprends rien .... :roll:
regarde mon nombre de message, je viens de débuter en Purebasic ;)

d'ailleurs ma version du code de Falsam, n'a pas 2 Repeat qui se suivent, et marche tres bien sans .... ;)


l'exemple de la Doc a OpenWindowedScreen() est naze !!
il contient 2 boucles repeat imbriquée ... l'une des 2 ne sert a rien !!!
tout ce que ça fait, c'est que ça donne de mauvaises habitudes ...



voici le Code qu'on trouve dans la Doc (ce qu'il ne faut pas faire ):

Code : Tout sélectionner

If InitSprite() = 0
    MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
    End
  EndIf
  
  If OpenWindow(0, 0, 0, 220, 160, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0, 170, 135, 45, 20, "Quitter")

    If OpenWindowedScreen(WindowID(0), 0, 0, 160, 160)
      CreateSprite(0, 20, 20)
      If StartDrawing(SpriteOutput(0))
        Box(0, 0, 20, 20, RGB(255, 0, 155))
        Box(5, 5, 10, 10, RGB(155, 0, 255))
        StopDrawing()
      EndIf
    Else
      MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
      End
    EndIf
  EndIf
  
  direction = 2
  Repeat
    ; Il est très important de traiter tous les événements restants dans la file d'attente à chaque tour
    ;
    Repeat
      Event = WindowEvent()
      
      Select Event 
        Case #PB_Event_Gadget
          If EventGadget() = 0
            End
          EndIf
        
        Case #PB_Event_CloseWindow
          End 
      EndSelect
    Until Event = 0
  
    FlipBuffers() 
    ClearScreen(RGB(0, 0, 0))
    DisplaySprite(0, x, x)
    x + direction
    If x > 140 : direction = -2 : EndIf
    If x < 0   : direction =  2 : EndIf
    Delay(1)
  ForEver



et voici ma version Corrigé ou il n'y a pas 2 repeat !! car je le repete, ça ne sert a rien !
ça ne fait que ralentir point

Code : Tout sélectionner

If InitSprite() = 0
	MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
	End
EndIf

If OpenWindow(0, 0, 0, 220, 160, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ButtonGadget(0, 170, 135, 45, 20, "Quitter")
	
	If OpenWindowedScreen(WindowID(0), 0, 0, 160, 160)
		CreateSprite(0, 20, 20)
		If StartDrawing(SpriteOutput(0))
			Box(0, 0, 20, 20, RGB(255, 0, 155))
			Box(5, 5, 10, 10, RGB(155, 0, 255))
			StopDrawing()
		EndIf
		Else
		MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
		End
	EndIf
EndIf

direction = 2
Repeat
	; Il est très important de traiter tous les événements restants dans la file d'attente à chaque tour
	;
	Event = WindowEvent()
	
	Select Event 
		Case #PB_Event_Gadget
		If EventGadget() = 0
			End
		EndIf
	EndSelect
	
	DisplaySprite(0, x, x)
	x + direction
	If x > 140 : direction = -2 : EndIf
	If x < 0   : direction =  2 : EndIf
	Delay(1)
	FlipBuffers() 
	ClearScreen(RGB(0, 0, 0))
Until Event =#PB_Event_CloseWindow
End 
; Epb


c'est un non sens d'imbriquer 2 boucles repeat !!
je ne vois meme pas dans quel cas ça peut etre utile !! :roll:

en tout cas pas dans le traitement des events !!
Dernière modification par Backup le lun. 31/mars/2014 0:53, modifié 1 fois.
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

Re: [2D] Flip Horizonal

Message par majikeyric »

mise à 0 des éléments d'un tableau à 2 dimensions (avec 2 repeats!)

Code : Tout sélectionner

i=0
Repeat
	j=0
	Repeat
		tab(i,j)=0
		j+1
	Until j=15
	i+1
Until i=10
:roll:
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: [2D] Flip Horizonal

Message par GallyHC »

Bonjour tous,

Dobro > Je ne penses que ce soit forcement "naze". Car en essayant de comprendre le code avec les boucles imbriquer, je comprend juste qu'il vide la pile des évènements avant de continuer la boucle main du programme.

Code : Tout sélectionner

If InitSprite() = 0
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
  End
EndIf

If OpenWindow(0, 0, 0, 220, 160, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0), 0, 0, 160, 160)
  Else
    MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
    End
  EndIf
EndIf

Repeat
    ;
    ; BOUCLE MAIN
    ;
    i = 0
    Repeat
      ;
      ; BOUCLE DE TRAITEMENT DES EVENEMENTS
      ; SI = 0 LA PILE EST VIDE.
      ;
      Event = WindowEvent()
      
      i + 1
      
      Select Event 
        Case #PB_Event_Gadget
        Case #PB_Event_CloseWindow
          End 
      EndSelect
    Until Event = 0
    ;
    ; AFFICHAGE ET AUTRE...
    ;
    Debug i
    ;
    ; SI ON REGARDE i ON VOIS QU'IL A ETE INCREMENTER
    ; ENTRE 1 A 6 FOIS, DONC 6 RAFRAICHISSEMENTS POUR
    ; TRAITER SEULEMENT LES EVENEMENTS WINDOWS.
    ;
ForEver
C'est une façon de faire qui évite de retracer par exemple un "sprite" a chaque évènement de la fenêtre.

Enfin c'est ce que je comprend,
Cordialement,
GallyHC
Dernière modification par GallyHC le lun. 31/mars/2014 1:04, modifié 1 fois.
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

majikeyric a écrit :mise à 0 des éléments d'un tableau à 2 dimensions (avec 2 repeats!)

Code : Tout sélectionner

i=0
Repeat
	j=0
	Repeat
		tab(i,j)=0
		j+1
	Until j=15
	i+1
Until i=10
:roll:
tu me demontre quoi ?
qu'on peut imbriquer des repeat ... haaa la bonne nouvelle

ce que je dis , c'est que cela n'a pas d'utilité en tout cas dans le traitement des events comme l'exemple de la Doc

entre nous .... entre faire :

Code : Tout sélectionner


i=0
Repeat
	j=0
	Repeat
		tab(i,j)=0
		j+1
	Until j=15
	i+1
Until i=10
et faire :

Code : Tout sélectionner

for i=0 to 10
	for j=0 to 15
		tab(i,j)=0
	Next j
Next i
c'est quoi le mieux ??


@GallyHC
et voici ce que je fait .... plus simple fait la meme chose !

Code : Tout sélectionner


Repeat
	;
	; BOUCLE MAIN
	;
	;;;; Repeat  <<<<<<<<<<< retiré par Dobro
	;
	; BOUCLE DE TRAITEMENT DES EVENEMENTS
	; SI = 0 LA PILE EST VIDE.
	;
	Event = WaitWindowEvent()
	
	Select Event
		Case #PB_Event_Gadget
		
	EndSelect
	;;;;;; Until Event = 0 <<<<<<<<<<< retiré par Dobro
	;
	; AFFICHAGE ET AUTRE...
	;
Until Event = #PB_Event_CloseWindow

End
; Epb


codez comme vous le voulez ...

ne soyez pas surpris d'voir des codes qui rames ....
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

je viens juste de corriger ce code :
http://www.purebasic.fr/french/viewtopi ... =4&t=14350

qui ramait Testez la différence ... vous verrez par vous meme
regardez les Cycles avec le gestionnaire des taches ....
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: [2D] Flip Horizonal

Message par GallyHC »

"WindowEvent()" est pour moi une pile d'évènement, donc il faut traiter la pile avant de faire autre chose, non?

Cordialement,
GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

tout le probleme est là

il y a un double emploi dans Purebasic

entre WindowEvent() (qui a mon avis devrai etre suprimé .... )

et WaitWindowEvent(timer ) qui est la nouvelle version apparu plus recemment avec le Timer

d'ailleurs a propos de WindowEvent() la doc dit :
Une application devrait, si possible, toujours utiliser cette fonction (WaitWindowEvent() ) en préférence à WindowEvent() car elle ne prend pas de temps CPU en attente d'un événement

en clair WaitWindowEvent() ne prends que les evenements attendus .... ex : un clique sur un gadget
et seulement si .... (attends cet evenement precis .. et laisse passer le reste )

alors que WindowEvent() prends tout les event qui se présentent ... meme ceux qui ne nous servent pas ...

de par le fait les 2 fonctions liberes la liste des events ...
c'est meme pour ça qu'apres un WindowEvent() on ajoute un Delay() pour rendre la main au systeme ....
(sinon le pourcentage Processeur du gestionnaire Grimpe en fleche )


entre utiliser 2 repeat imbriqués et windowEvent()

je prefere utiliser un seul Repeat et WaitWindowEvent(xx)
je respecte ainsi, les dernieres directives de Fred ... :)
et la Doc
Avatar de l’utilisateur
MetalOS
Messages : 1492
Inscription : mar. 20/juin/2006 22:17
Localisation : Lorraine
Contact :

Re: [2D] Flip Horizonal

Message par MetalOS »

Arretez de le mettre sous pression le vieux Dobro il va nous claquer dans les pattes. C'est fragile à cette âge là lol
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: [2D] Flip Horizonal

Message par Micoute »

D'autant plus, qu'il a parfaitement raison !
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [2D] Flip Horizonal

Message par falsam »

Houla que de réactions sur ce code :)

■ Merci Dobro pour ton aide : Le flip fonctionne bien mais on perd le lissage du contour.
majikeyric a écrit :Je pense que le vrai problème venait du canal alpha avec l'emploi du 'plot'.
majikeyric tu as raison et je ne sais pas comment faire pour résoudre ce souci.
Micoute a écrit :D'autant plus, qu'il a parfaitement raison !
Un vrai groupi de Dobro ce mec. Il boit avec délices les paroles de Dobro :)

■ Quand à la polémique du double repeat, C'est vrai que dans ce cas j'aurais pu m'en passer. Mais pour un code un peu conséquent je pense qu'il faut d'abord traiter et vider les événements Windows avant de passer aux événements 2D. D'ou cette façon de faire (C'est valable aussi pour la 3D)

Code : Tout sélectionner

Repeat  ;Boucle application
  
  Repeat ;Boucle Evenement windows
    
    Event = WindowEvent()
    
    Select event    
        Case #PB_Event_CloseWindow
          ;Reste du code
          
      EndSelect  
      
    Until Event=0 ;Jusqu'à qu'il n'y ait plus d'événement Window
    
    
    ;La pile d'évenements windows est vide.
    ;On peut traiter les évenements 2D 
    FlipBuffers()
    ClearScreen(RGBA(245, 222, 179, 255))
                
    ExamineKeyboard()
    
    If KeyboardReleased(#PB_Key_Space)
      SpriteFlipHorizontal(Sprite)
    EndIf   
    
    ExamineMouse()
    
    ;etc .....
    
    DisplayTransparentSprite(Sprite, 0, 0)
   
Until KeyboardPushed(#PB_Key_Escape)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: [2D] Flip Horizonal

Message par Backup »

falsam a écrit :Mais pour un code un peu conséquent je pense qu'il faut d'abord traiter et vider les événements Windows avant de passer aux événements 2D. D'ou cette façon de faire (C'est valable aussi pour la 3D)
pas besoin de double Repeat , et donc pas besoin de vider quoique ce soit si tu utilises WaitWindowEvent(xxx) ;)
puisque tu tu ne prends QUE ce que tu attends ....

mais bon ... faites comme si je n'avais rien dit... c'est pas grave :)
Répondre