CreateSprite aus ClipSprite erstellen?!?

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

In der Hilfe steht lediglich dass man mit CreateSprite ein Sprite erstellen kann.
Mir fiele nur noch die Möglichkeit über CopySprite ein um ein geCliptes Sprite in ein mit CreateSprite erstelltes zu kopieren.

Okay in dem Zuge könnte man CreateSprite auch ganz weglassen.
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von NicTheQuick »

Wolltest du jetzt was fragen oder nur was sagen?
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

Eigentlich fragen...aber da mir die Antwort während des Schreibens einfiel, dachte ich ich poste trotzdem mal.
Kann ja sein, es fällt jemand noch ein anderer Weg ein, oder jmd. findet die Info nützlich...

Ansonsten kanns auch getrashed werden.

edit:

Ich habes jetzt mal so probiert, funktioniert jedoch nicht...
Ich bin wieder neu bei PB gelandet und hab bestimmt etwas mit der structure oder so verkehrt gemacht.
syntax check ist aber okay gewesen.
Vielleicht mag es sich ja jemand anschauen.

Code: Alles auswählen

Structure SpriteType
  Array Arrays.i(255)
EndStructure 
Global *Sprite_Type.SpriteType
*Sprite_Type = AllocateMemory(SizeOf(SpriteType))
InitializeStructure(*Sprite_Type, SpriteType)

Procedure CreateAnimSpritesStrip(sprite, frames, breite, hoehe, zeilen, spalten)
  For a = 0 To SpriteWidth(sprite)/breite
    For b = 0 To SpriteHeight(sprite)/hoehe
      ClipSprite(sprite,a*breite, b*hoehe, breite, hoehe)
      CopySprite(sprite, *Sprite_Type\Arrays(framecounter))
      ClipSprite(sprite, #PB_Default, #PB_Default, #PB_Default, #PB_Default)
      framecounter=framecounter+1
    Next
  Next
  ProcedureReturn *Sprite_Type\Arrays(framecounter)
EndProcedure 

Procedure DrawAnimSprite(sprite, x, y, frame)
  DisplayTransparentSprite(*Sprite_Type\Arrays(frame), x, y)
EndProcedure
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von KeyKon »

Also wenn ich das richtig verstanden habe willst du aus einem Sprite-Strip einzelne Sprite erstellen.
Ich hab das früher immer schön mit UseBuffer gemacht, das ging ja aber leider schon seit DX9 nicht mehr und ist inzwischen (5.20) auch ganz entfernt worden.
Daher hab ich mal mit zwei Möglichkeiten die mir auf die schnelle eingefallen sind rumgespielt:

- Als Image laden und mit DrawImage auf die einzeln erstellen Sprites malen
- Als Sprite laden und mit DisplaySprite und GrabSprite auf dem Hintergrundbuffer arbeiten

Code: Alles auswählen

EnableExplicit

InitSprite()
InitKeyboard()

Define.i x
Define.i anim
Define.i i, time, text.s

Dim AnimImage(4)
Dim AnimGrab(4)

If Not OpenScreen(1920,1080,32,"Test")
  End
EndIf

ClearScreen(#Black)
FlipBuffers()
ClearScreen(#Black)
FlipBuffers()

;Methode DrawImage:
CreateImage(0,200,50)
StartDrawing(ImageOutput(0))
  Box(0,0,50,50,#Red)
  Box(50,0,50,50,#Green)
  Box(100,0,50,50,#Yellow)
  Box(150,0,50,50,#Blue)
StopDrawing()

time = ElapsedMilliseconds()
For i = 0 To 500
For x = 0 To 3
  AnimImage(x) = CreateSprite(#PB_Any,50,50)
  StartDrawing(SpriteOutput(AnimImage(x)))
    DrawImage(ImageID(0),x*-50,0)
  StopDrawing()
Next
Next
text = "Image: "+Str(ElapsedMilliseconds()-time)+" ms"

FreeImage(0)



;Methode GrabSprite:
CreateSprite(0,200,50)
StartDrawing(SpriteOutput(0))
  Box(0,0,50,50,#Red)
  Box(50,0,50,50,#Green)
  Box(100,0,50,50,#Yellow)
  Box(150,0,50,50,#Blue)
StopDrawing()

time = ElapsedMilliseconds()
For i = 0 To 500
DisplaySprite(0,0,0)
For x = 0 To 3
  AnimGrab(x) = GrabSprite(#PB_Any,x*50,0,50,50)
Next
Next
text = text + "  |  Grab: "+Str(ElapsedMilliseconds()-time)+" ms"

FreeSprite(0)
  
  


Repeat
  
  ClearScreen(#Black)
  
  DisplaySprite(AnimImage(Int(anim/15)),10,40)
  DisplaySprite(AnimGrab(Int(anim/15)),70,40)
  
  anim+1
  If anim = 60
    anim = 0
  EndIf
  
  If StartDrawing(ScreenOutput())
    DrawText(10,10,text,#White,#Black)
    StopDrawing()
  EndIf
  
  FlipBuffers()
  ExamineKeyboard()
  
Until KeyboardPushed(#PB_Key_Escape)
Nicht wundern ich mache das ganze 500 mal um die Zeiten zu vergleichen, ich kann dir daher die Methode mit DrawImage ans Herz legen, das ist wie ich finde sauberer und vor allem viel schneller.
Davon abgesehen kannst du (wenn ich die Hilfe richtig verstanden hab) mit der DrawImage-Methode sogar mit Multithreading beim laden arbeiten wenn dein Projekt recht groß ist^^ (wie gesagt ohne Garantie da noch nie getestet)

LG KeyKon
(\/) (°,,,°) (\/)
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

die grab methode würde ich nutzen wollen.
Habe das mal mit structure in einer procedure versucht, aber dafür kenn ich mich wohl noch zuwenig mit pb aus....
Das hier habe ich zusammengewurstelt...

So wie du das gemacht hast, hätte ich auch geschafft, nur brauche ich das als proceduren damit ich das auf verschiedene spritesheets/tilemaps anwenden kann.

sowas in der art hab ich gemacht....funktioniert nicht...aber vielleicht kannst mir ja helfen das richtig zu machen.
p.s. habs im englischen forum vorhin auch gepostet, da hier bisher niemand rat wusste.

Code: Alles auswählen

Structure SpriteType
  Array Arrays.i(255)
EndStructure 
Global *newsprite.SpriteType
*newsprite = AllocateMemory(SizeOf(SpriteType))
InitializeStructure(*newsprite, SpriteType)

Procedure LoadAnimSpritesStrip(sprite.s, frames, breite, hoehe, zeilen, spalten)
  newsprite.SpriteType
  tmp_sprite=LoadSprite(#PB_Any, sprite)
  DisplaySprite(tmp_sprite,0,0)
  For a = 0 To frames
    newsprite\Arrays(a)=GrabSprite(tmp_sprite, a*breite,a*hoehe, breite, hoehe)
  Next
  ClearScreen(RGB(138,43,226))
  ProcedureReturn newsprite\Arrays()
EndProcedure 

Procedure DrawAnimSprite(*newsprite, x, y, frame)
  newsprite.SpriteType
  DisplayTransparentSprite(newsprite\Arrays(frame), x, y)
EndProcedure
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von Bisonte »

Da hab ich zwar schon geschrieben, aber in deutsch gehts besser ;)

Du hast vergessen den Speicher zu reservieren (*newsprite)
desweiteren hast du eventuell noch ein * vergessen beim ProcedureReturn newsprite\Arrays(), wobei ich mich frage
warum du da das nochmal rausgibst, wenn *newsprite eh global ist.
Ausserdem definierst du *newsprite in jeder proc neu...

*newsprite und newsprite sind nicht das gleiche....
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

alles klar danke..ja in deutsch is deutlich besser.
ich steige gerade seit jahren wieder in pb ein daher asche auf mein haupt.
ich seh nun ehrlich gesagt garnicht mehr durch.

ich möchte nur ein spritesheet/tilemap laden, dort alle tiles/frames durchlaufen und diese in irgendeiner form speichern, sodass man diese mit einem anderen befehl einzeln anzeigen kann.

von hand ist das ungünstig wenn ich verschiedene tilesets habe.
Ich bräuchte das schon als procedure.
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von Bisonte »

Also hier mal das was ich mir da nun vorstelle.... ohne zu wissen welchen Sinn diese Prozeduren haben :lol:

Code: Alles auswählen

EnableExplicit

Structure SpriteType
  Array Arrays.i(255)
EndStructure

Procedure LoadAnimSpritesStrip(sprite.s, frames, breite, hoehe, zeilen, spalten)
  
  Protected Tmp_Sprite = #False
  Protected *newsprite.SpriteType = AllocateMemory(SizeOf(SpriteType))
  
  If Not *newsprite : ProcedureReturn #False : EndIf ; raus wenn speicher nicht da
  InitializeStructure(*newsprite, SpriteType)
  
  Tmp_Sprite = LoadSprite(#PB_Any, sprite)
  
  If IsSprite(Tmp_Sprite)
    DisplaySprite(tmp_sprite,0,0)
    For a = 0 To frames
      *newsprite\Arrays(a)=GrabSprite(tmp_sprite, a*breite,a*hoehe, breite, hoehe)
    Next a
  Else
    ClearStructure(*newsprite, SpriteType)
    FreeMemory(*newsprite)
    *newsprite = #Null
  EndIf
  
  ClearScreen(RGB(138,43,226))
  
  ProcedureReturn *newsprite
  
EndProcedure

Procedure DrawAnimSprite(*newsprite.SpriteType, x, y, frame)  
  If *newsprite
    DisplayTransparentSprite(*newsprite\Arrays(frame), x, y)
  EndIf
EndProcedure

; --- Demo

Define *SpriteSet1.SpriteType

*SpriteSet1 = LoadAnimSpritesStrip("Pfad:\Zum\Spriteset.png", 12, 20, 20, 2, 2)
If *SpriteSet1
  DrawAnimSprite(*SpriteSet1, 100, 100, 4)
EndIf
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von KeyKon »

So beim Überfliegen fällt mir auf:

a*breite,a*hoehe führt dazu, dass du nur eine Diagonale Reihe an Sprites ausschneidest
Wenn du wirklich mehrere Reihen und Spalten hast würde ich das so machen (Ungetestet!):

Code: Alles auswählen

For y = 0 To zeilen-1
  For x = 0 To spalten-1
    newsprite\Arrays(spalten*y+x) = GrabSprite(#PB_Any, x*breite, y*hoehe, breite, hoehe)
  Next
Next
Wenn du dir eine Prozedur dafür erstellst halte ich es für unsinnig mit Globalen Variablen zu arbeiten, du solltest vll eher ein Array anlegen, in dem alle Sprites deines Programms mit dem Typ SpriteType angelegt sind und dann jeweils beim laden die Adresse des Array-Eintrags weitergeben, dann brauchst du auch kein ProcedureReturn, da du direkt auf dem Array-Eintrag arbeitest:

Code: Alles auswählen

Structure SpriteType
  Array Arrays.i(255)
EndStructure 

Dim Sprites.SpriteType(10)


Procedure LoadAnimSpritesStrip(*spriteId.SpriteType, sprite.s, frames, breite, hoehe, zeilen, spalten)
  
  *spriteId\Arrays(0) = 10
  *spriteId\Arrays(1) = 20
  
EndProcedure


LoadAnimSpritesStrip(@Sprites(0),"",0,0,0,0,0)

Debug Sprites(0)\Arrays(0)
Debug Sprites(0)\Arrays(1)
Dein Hauptfehler ist aber wohl vor allem, dass du tmp_sprite bei GrabSprite benutzt, dadurch überschreibst du quasi dein temporäres SpriteStrip, du solltest hier #PB_Any verwenden.

Zu guter letzt würde ich noch das tmp_sprite mit FreeSprite entfernen, da es ja nicht mehr gebraucht wird...


LG KeyKon
(\/) (°,,,°) (\/)
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

ach gott naeben...tmp_sprite....übersehen.
ich danke euch beiden....
werd das morgen mal testen, heut ruft erstmal die matratze.


und anfügen wollte ich noch die zeilen und spalten waren ursprünglich gedacht um das durchlaufen der map zu umgehen, welches ich später als routine einbauen will.

ich möchte mittels dieser proceduren eine tilemap egal welcher größe und unabhängig der tileanzahl nutzen können.

hatte das vorher mit clipsprite versucht, was im grunde genauso geht, wenn man nach dem clip das sprite wieder auf default setzt.

vielen dank nochmal...
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Antworten