Seite 1 von 2

CreateSprite aus ClipSprite erstellen?!?

Verfasst: 17.09.2013 20:18
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.

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 17.09.2013 20:53
von NicTheQuick
Wolltest du jetzt was fragen oder nur was sagen?

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 17.09.2013 21:01
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 22:55
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:01
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:07
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....

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:10
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.

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:17
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:21
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 18.09.2013 23:29
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...