Fonction FlipSprite

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Fonction FlipSprite

Message par Thyphoon »

Salut
J'ai trouvé une solution pour faire une commande de flip sprite (2D)
Direction=0 Mirroire Horizontal
Direction=1 Mirroire Vertical
Mais il y a un petit bug il y a toujours une ligne qui ne bouge pas
Voici le code toute sugestion est la bien venu...

Code : Tout sélectionner

hdc.l = GetDC_(0) 
ReleaseDC_(0, hdc) 

Procedure MirrorSprite(SpriteID.l, Direction.l) 
  hdc = StartDrawing(SpriteOutput(SpriteID)) 
    Height = SpriteHeight(SpriteID) 
    Width = SpriteWidth(SpriteID) 
    If Direction 
      StretchBlt_(hdc, 0, Height, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    Else 
      StretchBlt_(hdc, Width, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf 
  StopDrawing() 
EndProcedure 
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ce qui aurai ete cool, c'est que tu nous mettes un exemple tout fait et simple de ta procedure en utilisant une forme geometrique pour le sprite !!!! :)
(je suis feneant et j'ai la bulle de creer ça ! :lol:
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Lollll tu as raison :lol:
Voilà :P
Espace pour fliper le sprite
Escape pour sortir
;- Init DirectX
If InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
CloseWindow(0) : End
EndIf

res = OpenWindow(0, 0, 0, 640, 480, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "")
OpenWindowedScreen(res, 0, 0, 640, 480, 0, 0, 0)

CreateSprite(1, 50, 50,0)
StartDrawing(SpriteOutput(1))
FrontColor(255, 0, 0)
Line(0, 0, 50,25)
Line (0,0,0,50)
Line(50,25,-50,25)
StopDrawing()

hdc.l = GetDC_(0)
ReleaseDC_(0, hdc)

Procedure MirrorSprite(SpriteID.l, Direction.l)
hdc = StartDrawing(SpriteOutput(SpriteID))
Height = SpriteHeight(SpriteID)
Width = SpriteWidth(SpriteID)
If Direction
StretchBlt_(hdc, 0, Height, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY)
Else
StretchBlt_(hdc, Width, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY)
EndIf
StopDrawing()
EndProcedure

Repeat
FlipBuffers()
ClearScreen(0,0,0)
ExamineKeyboard()
If KeyboardPushed(#PB_Key_space)
Delay(200)
MirrorSprite(1,0)
EndIf
DisplaySprite(1,320,200)
While WindowEvent():Wend ; evite le plantage clic gauche
Until KeyboardPushed(#PB_Key_Escape)
On remarque donc que la première colone de la pixel ne bouge pas
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

j'ai comparé ta procédure avec les essais de fonctions que j'avais fait

La fonction avec buffer , déconne ( gestion incomplète ) , mais reste la plus rapide pour l'instant , à voir quand elle fonctionnera vraiment dans tous les cas si ça ne va pas la ralentir :)

sinon la fonction FlipSprite(no.l) avec des plots met le même temps que ta fonction , l'avantage de la fonction FlipSprite(no.l) c'est qu'elle retourne bien l'ensemble du sprite :)

Code : Tout sélectionner

;- Init DirectX 
If InitSprite() = 0 Or InitKeyboard() = 0 
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0) 
  CloseWindow(0) : End 
EndIf 

res = OpenWindow(0, 0, 0, 640, 480, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "") 
OpenWindowedScreen(res, 0, 0, 640, 480, 0, 0, 0) 

Global  adresse , pitch , Format 

CreateSprite(1, 64, 64,0) 
StartDrawing(SpriteOutput(1)) 
FrontColor(255, 0, 0) 
Line(0, 0, 50,25) 
Line (0,0,0,50) 
Line(50,25,-50,25) 
adresse = DrawingBuffer() 
pitch = DrawingBufferPitch() 
Format = DrawingBufferPixelFormat() 
StopDrawing() 

hdc.l = GetDC_(0) 
ReleaseDC_(0, hdc) 

Procedure MirrorSprite(SpriteID.l, Direction.l) 
  hdc = StartDrawing(SpriteOutput(SpriteID)) 
  Height = SpriteHeight(SpriteID) 
  Width = SpriteWidth(SpriteID) 
  If Direction 
    StretchBlt_(hdc, 0, Height, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
  Else 
    StretchBlt_(hdc, Width, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
  EndIf 
  StopDrawing() 
EndProcedure 

Procedure BufferFlipSprite(no.l) 
  ; bon apparemment ça ne fonctionne qu'avec des multiples de 8 ? 
  ; voir comment le pitch intervient dans le calcul de l'adresse !!
  If Format > 5 
    Nboctet = 4 
  ElseIf Format = 2 Or Format = 3 
    Nboctet = 2 
  Else 
    ProcedureReturn 0 ; je ne vais pas m'emmerder à gérer les autres cas alors que personne ne va utiliser cette procédure :) 
  EndIf  
  For v = 0 To SpriteHeight(no) - 1 
    adr = adresse + ((u + (SpriteWidth(no) * v)) * Nboctet)  
    adr1 = adresse + ((SpriteWidth(no) - 1 - u + (SpriteWidth(no) * v)) * Nboctet) 
    For u = 0 To (SpriteWidth(no) - 1 ) / 2 
      If Nboctet = 4 
        CoulG = PeekL(adr) 
        CoulD = PeekL(adr1) 
        PokeL(adr,CoulD) 
        PokeL(adr1,CoulG) 
        
      Else 
        CoulG = PeekW(adr) 
        CoulD = PeekW(adr1) 
        PokeW(adr,CoulD) 
        PokeW(adr1,CoulG) 
      EndIf  
      adr + Nboctet 
      adr1 - Nboctet 
    Next u 
  Next v 
EndProcedure 

Procedure FlipSprite(no.l) 
  StartDrawing(SpriteOutput(no)) 
  For v = 0 To SpriteHeight(no)-1 
    For u = 0 To (SpriteWidth(no) - 1 ) / 2 
      CoulG = Point(u, v) 
      CoulD = Point(SpriteHeight(no) - 1 - u,v) 
      Plot(u,v,CoulD) 
      Plot(SpriteHeight(no) - 1 - u,v,CoulG) 
    Next u 
  Next v 
  StopDrawing() 
EndProcedure 

Temps = ElapsedMilliseconds() 
For i = 1 To 1000 
  BufferFlipSprite(1) 
Next i  
Total = ElapsedMilliseconds() - Temps 
Debug "Avec Buffer" 
Debug Total 
  
Temps = ElapsedMilliseconds() 
For i = 1 To 1000 
  FlipSprite(1) 
Next i  
Total = ElapsedMilliseconds() - Temps 
Debug "Sans Buffer" 
Debug Total  


Temps = ElapsedMilliseconds() 
For i = 1 To 1000 
  FlipSprite(1) 
Next i  
Total = ElapsedMilliseconds() - Temps 
Debug "Avec StretchBlt_" 
Debug Total  
  
; Repeat 
  ; FlipBuffers() 
  ; ClearScreen(0,0,0) 
  ; ExamineKeyboard() 
  ; If KeyboardReleased(#PB_Key_Space) 
    ; ;Delay(200) 
    ; ;MirrorSprite(1,0) 
    ; BufferFlipSprite(1)
    ; ; FlipSprite(1)
  ; EndIf 
  ; DisplaySprite(1,320,200) 
  ; While WindowEvent():Wend ; evite le plantage clic gauche 
; Until KeyboardPushed(#PB_Key_Escape) 
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci ! :D
je pense que pour l'instant je vais utiliser ton FlipSprite ... :)
:wink:
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Parcontre Une petite correction a ta procedure !

Code : Tout sélectionner

Procedure FlipSprite(no.l) 
  StartDrawing(SpriteOutput(no)) 
  For v = 0 To SpriteHeight(no)-1 
    For u = 0 To (SpriteWidth(no) - 1 ) / 2 
      CoulG = Point(u, v) 
      CoulD = Point(SpriteWidth(no) - 1 - u,v) ; remplacement de SpriteHeight par SpriteWidth
      Plot(u,v,CoulD) 
      Plot(SpriteWidth(no) - 1 - u,v,CoulG) ; remplacement de SpriteHeight par SpriteWidth

    Next u 
  Next v 
  StopDrawing() 
EndProcedure 
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

exact , avec ma manie de faire des copier coller , voila le résultat :)

Merci d'avoir corriger .
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

En cherchant à simplifier la procédure Flipsprite() , pour limiter les calculs dans les boucles , je me suis aperçu que je ne testais pas ta procédure , mais flipsprite() (encore avec ma manie des copier coller) , donc c'est normal que les temps soient identiques :oops:

en refaisant le test , ta fonction bat tous les records , reste à corriger le bug .
Je n'ai pas cherché sur codearchiv , mais je serais étonné qu'on ne puisse pas y trouver une fonction de ce type .
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

j'ai regardé sur codearchiv mais j'ai pas trouvé :(
il manque a Purebasic des fonctions rapide pour les sprites 2Ds ! je comprends pas que ça soit si lent sur des machines d'aujordh'ui alors que sur des machines de plus de 10Ans comme sur les A1200 on fait la même choses sans pb et ralentissment apparent !
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

as-tu fait une suggestion au sujet de la fonction flip dans la section Suggestion et amélioration ?
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

A non je n'y ai pas pensé...j'y vais de ce pas !! :o) :P
Dräc
Messages : 526
Inscription : dim. 29/août/2004 0:45

Message par Dräc »

Petite correction :

Dans ta routine MirrorSprite, il faut remplacer

StretchBlt_(hDC, Width, 0, -Width, Height, hDC, 0, 0, Width, Height, #SRCCOPY)
par
StretchBlt_(hDC, Width-1, 0, -Width, Height, hDC, 0, 0, Width, Height, #SRCCOPY)

et
StretchBlt_(hDC, 0, Height, Width, -Height, hDC, 0, 0, Width, Height, #SRCCOPY)
par
StretchBlt_(hDC, 0, Height-1, Width, -Height, hDC, 0, 0, Width, Height, #SRCCOPY)

afin d’effectuer le traitement jusqu’aux derniers bits ;)
Dernière modification par Dräc le lun. 11/oct./2004 22:07, modifié 1 fois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci beaucoup !!! :P
Tes un as !!
Répondre