problème sprite et changement d'image

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

problème sprite et changement d'image

Message par blendman »

salut

J'ai remarqué que si on crée un sprite de petite taille, puis qu'on dessine une image de plus grande taille, c'est pixelisé.

C'est logique, mais existe-t-il un moyen de changer les dimensions du sprite (je ne parle de zoomsprite() ou tranformsprite() qui ne change pas les dimensions mais la taille d'affichage) ?

Pour tester, un petit code :

Code : Tout sélectionner

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


flag = #PB_Window_ScreenCentered|#PB_Window_SystemMenu
If OpenWindow(0,0,0,1024,768,"SetSpriteImage", flag)=0 Or OpenWindowedScreen(WindowID(0),0,0,1024,768)=0
  MessageRequester("Error", "Can't open the sprite system", 0)
  End
EndIf
UsePNGImageDecoder()



Procedure SetSpriteImage(sprite, image)
  
  ; change the image on a sprite
  Shared w1, h1
  
  w = ImageWidth(image)
  h = ImageHeight(image)
  
  
  
  If StartDrawing(SpriteOutput(sprite))
    ; erase the sprite
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0, 0, OutputWidth(), OutputHeight(),RGBA(0,0,0,0))
    
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    DrawImage(ImageID(image), 0, 0 , w1, h1)
    StopDrawing()
  EndIf
  
  ZoomSprite(sprite, w, h)
  
EndProcedure

Procedure AddSprite(img = 1)
  
  Shared w1, h1
  
  w1 = ImageWidth(img)
  h1 = ImageHeight(img)

  CreateSprite(1, w1, h1,#PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
  SetSpriteImage(1, img)
  
EndProcedure

Procedure SetSpriteSize(sprite, width, height)
  
  ZoomSprite(sprite, width, height)
  
EndProcedure






KeyboardMode(#PB_Keyboard_International)



LoadImage(0,#PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp") 

LoadImage(1,#PB_Compiler_Home + "Examples\Sources\Data\world.png") 
w2 = ImageWidth(1)
h2 = ImageHeight(1)

AddSprite()

SetSpriteImage(1, 1)
w.d = SpriteWidth(1)
h.d = SpriteHeight(1)
SetSpriteSize(1, w*20, h*20)


#SpriteMouse = 2
CreateSprite(#SpriteMouse, 16, 16, #PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
If StartDrawing(SpriteOutput(#SpriteMouse))
  Box(0, 0, OutputWidth(), OutputHeight(),RGB(50,0,255))
  StopDrawing()
EndIf

SpriteQuality(0)



Repeat
  
  Repeat
    
    event = WaitWindowEvent(1)
    
    Select event
      Case #PB_Event_CloseWindow
        quit = 1
    EndSelect
    
    
  Until event = 0 Or quit = 1
  
  x = WindowMouseX(0)
  y = WindowMouseY(0)
  
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_A)
    image= 1 - image
    SetSpriteImage(1, image)
    w = SpriteWidth(1)
    h = SpriteHeight(1)
  EndIf
  
  If KeyboardPushed(#PB_Key_Up)
    w *(1.01)
    h *(1.01)
    SetSpriteSize(1, w, h)
  EndIf 
  If KeyboardPushed(#PB_Key_Down)
    w *(0.99)
    h *(0.99)
    SetSpriteSize(1, w, h)
  EndIf
  
  FlipBuffers()
  ClearScreen(RGB(50,50,50))
  
  
  
  DisplayTransparentSprite(1, 200, 200)
  DisplayTransparentSprite(#SpriteMouse, x, y)
  
  If SpritePixelCollision(1, 200, 200, #SpriteMouse, x, y) 
    Debug "collision : " + x + " / " + y
  EndIf
  
  If StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(200, 200, SpriteWidth(1),SpriteHeight(1), RGB(255,0,0))
    StopDrawing()
  EndIf
    
Until quit = 1 Or KeyboardReleased(#PB_Key_Escape)

CloseScreen()
End
Pour le moment, la technique que j'ai trouvé c'est de recréer le sprite, mais c'est pourri, car alors, je prends l'id du sprite (vu que j'utilise #pb_any pour créer mes sprites), et je sauvegarde cet id pour le réutiliser.

Donc, c'est un peu la galère pour le moment, je me dépatouille comme je peux, mais si on pouvait modifier les dimensions d'un sprite sans devoir le recréer, ce serait cool :).


une idée ?

ps : Bon, après, de toutes façons, il y a un bug avec spritepixelcollision et zoomsprite() ^^
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: problème sprite et changement d'image

Message par Fig »

Pas sûr d'avoir tout compris...
Mais tu peux toujours tester spritepixelcollision() avec ton sprite à ses dimensions normales, en ajustant les coordonnées en fonction du facteur du zoom que tu souhaites.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: problème sprite et changement d'image

Message par case »

L'astuce est de créer un Sprite de grande taille et de la réduire avec zoomsprite non? Plutôt que l'inverse
ImageImage
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: problème sprite et changement d'image

Message par blendman »

En fait, le problème, c'est que c'est pour mon éditeur de niveau.
On peut changer l'image d'un sprite si on veut.

Donc, oui, je pourrais créer des sprites très grand de base.
Cependant, je ne peux savoir à l'avance si je vais mettre un sprite avec une grande image ou une petite. Et si crée chaque sprite en 1024*1024 par exemple, avec plus de 500 sprites sur la plupart des maps voire plus, j'ai peur que ça commencé à ramer...

donc, pour le moment, si on change l'image du sprite, je recrée le sprite au dimension de nouvelle image. mais ça change son id.
J'utilise une map() pour stocker l'id du sprite lorsqu'on le crée pour la première fois. Donc, ça va à peu près comme ça, mais j'ai quelques bugs que je dois résoudre à cause de ce changement d'id.

ce serait plus simple de pouvoir changer la taille du sprite en interne ou carrément de pouvoir changer l'image d'un sprite, ce qui changerait sa taille en "interne" ^^.
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

Re: problème sprite et changement d'image

Message par Zorro »

blendman a écrit : carrément de pouvoir changer l'image d'un sprite, ce qui changerait sa taille en "interne" ^^.

le code suivant, creer indéfiniment le meme sprite (le sprite 0 )
en changeant sa taille , et la taille et la couleur du cercle a l'interieur

ça marche ...
parcequ'en Purebasic un sprite n'est pas un objet !! (comme dans les autres language )

donc tu peux recreer autant de fois que tu veux le meme numero de Sprite !
et justement a mon sens le bug est là ....

la création d'un sprite en Purebasic , ben c'est pas une creation ....
c'est juste une "image" auquel on attribut un index ...un numero ...

mais cette image, "ce sprite" peut etre présent a different endroit de l'ecran

alors que dans les autres language un sprite etant un objet , il ne peut pas etre present a 2 endroit en meme temps !!
lorsq'uon veux faire ça , on effectue une copie du SPrite ...

en purebasic, pas la peine, tu veux poser le Sprite 1 a la coordonée 10,10 , et aussi le poser a la coordonée 150,150
ben pas de soucis, il sera bien présent au 2 endroits ...

cette représentation des Sprites, je sais pas ou Fred est allé pecher ça ...
j'ai jamais vu ça ailleurs (dans les autres Basic (GFA,STOS,DarkBasic,etc... )

bref, pour moi en Purebasic, les Sprites, ne sont pas des Sprites ! (sens Objet du terme)
je nommerai ça, plutot des "ghosts"


APPUYEZ SUR ESC pour quitter

Code : Tout sélectionner

InitSprite()

ExamineDesktops()
#Bureau=0
OpenScreen(DesktopWidth(#Bureau),DesktopHeight(#Bureau),DesktopDepth(#Bureau),"Sprite")
InitKeyboard()
;Création du sprite

repeat
ExamineKeyboard()
SpriteLarg=random(255,128)
SpriteHaut=random(255,128)
		if CreateSprite( 0,SpriteLarg,SpriteHaut)
				StartDrawing(SpriteOutput(0))							
				couleur=RGB(random(255,125),random(255,125),random(255,125))
							Circle (SpriteLarg/2, SpriteHaut/2,sqr((SpriteLarg * SpriteHaut)/6) ,couleur)
				StopDrawing() 
				
				DisplaytransparentSprite(0, 210, 160)				
				FlipBuffers()
			ClearScreen($0)
		Endif
		Delay(550)
Until KeyboardPushed(#PB_Key_Escape)





Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: problème sprite et changement d'image

Message par djes »

Tu te compliques la vie je pense, et la solution n'est pas dans un truc bancal genre changer les dimensions d'un sprite ou le recréer (même si Zorro a raison, ça n'est pas gênant du tout), mais plutôt dans ta gestion de tes images. Tu dois avoir ta propre liste de sprites, à laquelle tu associes un sprite PB. Ce dernier, tu vas obtenir son id avec pb_any, et si tu charges un autre sprite, tu libères l'ancien (s'il existe) et tu recommences. C'est juste une bête gestion de ressources, tu te fais quelques procédures, et après, tu seras tranquille.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: problème sprite et changement d'image

Message par blendman »

Tu dois avoir ta propre liste de sprites, à laquelle tu associes un sprite PB. Ce dernier, tu vas obtenir son id avec pb_any, et si tu charges un autre sprite, tu libères l'ancien (s'il existe) et tu recommences.
Je ne comprends pas trop ce que tu veux dire par là.

En plus, j'utilise une lib que je me suis faite pour gérer beaucoup de choses que pb ne gère pas en interne (genre : getspriteX(), GetspriteY(), SetSpriteOffset(), SetSpritePositionByOffset(), etc...).
Donc, j'utilise une map() pour gérer les sprites, que je créer avec #pb_any.
Donc, pour changer l'image si je supprime, j'ai toujours le même problème puisque je l'ai conçu avec #pb_any et que cet id est supprimé lorsque je change d'image pour mon sprite.
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: problème sprite et changement d'image

Message par case »

n'utilise pas #pb_any
fais un compteur que tu incremente a la premiere initialisation
que tu stock dans ta map et quand tu recrée ton sprite réutilise le mème numéro de compteur.


a la creation

compteur +1
CreateSprite(compteur, Largeur, Hauteur [, Mode])
addmapelement(sprites())
sprites()=compteur


si tu veux changer le sprite



freesprite(sprites())
createsprite(sprites(), Largeur, Hauteur [, Mode])

du coup tu as toujours le meme ID et tu change ton sprite
#pb_any sort juste un nombre aléatoire unique en quelque sorte.
il est facilement remplaçable par un autre nombre. c'est juste un truc plus pratique pour les feignasses que nous sommes ^^


ou bien quand tu recrée un sprite si tu tiens a #pb_any tu peux aussi faire

Code : Tout sélectionner

if sprites()=0
sprites()= createsprite(#pb_any, Largeur, Hauteur [, Mode])
else
createsprite(sprites(), Largeur, Hauteur [, Mode])
endif
ImageImage
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: problème sprite et changement d'image

Message par djes »

case dans son exemple a bien résumé ce que je voulais dire :)
Il est aussi possible de faire un freesprite() si le sprite existe déjà et d'utiliser le même createsprite(pb_any...), ce qui revient au même.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: problème sprite et changement d'image

Message par blendman »

ça ne marche pas la technique de case (avec le debugger), vous pensez bien que j'avais testé ;).


J'avais pensé à l'id dynamique, c'est peut-être ce que je vais utiliser (un id de base = 100000 pour le premier sprite par exemple)

exemple à lancer avec le debugger :

Code : Tout sélectionner

 
InitSprite()
    
  If OpenWindow(0, 0, 0, 800, 600, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    ButtonGadget(0, 10, 10, 45, 20, "change")

    If OpenWindowedScreen(WindowID(0), 60, 0, 750, 600) =0
         MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
      End
    EndIf
  EndIf
  

  Repeat
   
    Repeat
      Event = WindowEvent()
      
      Select Event 
        Case #PB_Event_Gadget
          If EventGadget() = 0
            If sprite = 0              
              sprite= CreateSprite(#PB_Any, 64, 64)
              If StartDrawing(SpriteOutput(sprite))
                Box(0,0,64,64,RGB(255,0,0))
                StopDrawing()
              EndIf              
            Else
              CreateSprite(sprite, 128, 64 )
               If StartDrawing(SpriteOutput(sprite))
                Box(0,0,64,64,RGB(Random(255),Random(255), Random(255)))
                StopDrawing()
              EndIf
            EndIf
            
          EndIf
        
        Case #PB_Event_CloseWindow
          End 
      EndSelect
    Until Event = 0
  
    FlipBuffers() 
    ClearScreen(RGB(50, 50, 50))
    If IsSprite(sprite)
      DisplaySprite(sprite, 50, 50) 
    EndIf
    
    Delay(1)
    
  ForEver

mais sans le debugger, si vous recréez le sprite plusieurs fois et ensuite essayez de fermer la fenêtre avec la croix, ça plante.

sans le debugger, ça marche, mais est-ce qu'on peut utiliser ça si le debugger nous dit que c'est un id trop grand ?
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: problème sprite et changement d'image

Message par djes »

Il est où, mon FreeSprite() ? :twisted:
(normalement, à la ligne 31)

Sinon, je préfère quand même la liste chaînée "perso", où tu bloques des numéros que tu incrémentes, et que tu libères au besoin, et ça évite le msg d'avertissement de PB.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: problème sprite et changement d'image

Message par Fig »

Idem, je n'utilise jamais #pb_any ou rarement. Je gère moi même les index des sprites/images.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: problème sprite et changement d'image

Message par case »

comme le dit djes il manque un freesprite car si tu en crée un tu dois effacer l'existant sinon la memoire n'est pas libérée et cela crée un memory leak et cela fini par planter
une version sans le #pb_any et avec un freesprite ^^ et la ca neplante pas du tout avec ou sans debugger et pour prouver la chose j'ai viré le bouton et ca recrée le sprite tres vite, tres tres vite ^^

Code : Tout sélectionner


InitSprite()
   
  If OpenWindow(0, 0, 0, 800, 600, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
    ButtonGadget(0, 10, 10, 45, 20, "change")

    If OpenWindowedScreen(WindowID(0), 60, 0, 750, 600) =0
         MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
      End
    EndIf
  EndIf
 
  Repeat
   
    
      Event = WaitWindowEvent(0)
     


          If IsSprite(sprite)
              FreeSprite(sprite)
            EndIf
            If sprite = 0             
               sprite +1                                                      
               CreateSprite(sprite, 64, 64)
              If StartDrawing(SpriteOutput(sprite))
                Box(0,0,64,64,RGB(255,0,0))
                StopDrawing()
              EndIf             
            Else
              CreateSprite(sprite, 128, 64 )
               If StartDrawing(SpriteOutput(sprite))
                Box(0,0,64,64,RGB(Random(255),Random(255), Random(255)))
                StopDrawing()
              EndIf
            EndIf
 
    FlipBuffers()
    ClearScreen(RGB(50, 50, 50))
    If IsSprite(sprite)
      DisplaySprite(sprite, 50, 50)
    EndIf
   
    Delay(1)
    Until Event = #PB_Event_CloseWindow
   
  
   
  
ImageImage
Répondre