CreateSprite aus ClipSprite erstellen?!?

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
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 »

Ich kann dir an der Stelle nochmal die Methode mit DrawImage ans Herz legen, da bist du nämlich unabhänig von deiner Bildschirmgröße.W
enn nämlich ein Tile größer als der Screen ist bekommst du bei GrabSprite logischerweise Probleme...

Und wie oben an meinem Beispiel ersichtlich ist es mit DrawImage auch fast 10 mal so schnell (bei mir zumindest), außer ich hab einen Fehler gemacht der Zeit verschwendet *g*

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

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von N_Gnom »

ja das mit der bildschirmgröße ist mir bewusst.
aber nun kann ich ja zwischen 3 möglichkeiten wählen.grab, clip und drawimage.

und die geschwindigkeit ist nicht soooo tragisch, da ja das ganze im vorfeld erstellt werden wird und da macht man das während eines ladescreens oder so...wenns so massiv werden würde.
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 hats mich gepackt... weil mit Sprites schon lange nix mehr zu tun gehabt ;)

Funktionierte bei diversen "SpriteAnims" tadellos ...

Code: Alles auswählen

EnableExplicit

Structure struct_tileset
  Array Sprite.i(0)
EndStructure

Procedure LoadTileSet(FileName.s, TileWidth, TileHeight, Tiles = #PB_Any, SpriteMode = #PB_Sprite_AlphaBlending)
  
  Protected tImage, tTileImage, tSprite, Counter = 0
  Protected Rows, Cols, MaxTiles, x, y
  Protected *TileSet.struct_tileset = #Null
  
  ; --- Bild Laden
  tImage = LoadImage(#PB_Any, FileName)
  
  If IsImage(tImage)
    
    ; --- Speicher Reservieren
    *TileSet = AllocateMemory(SizeOf(struct_tileset))
    If Not *TileSet
      FreeImage(tImage)
      ProcedureReturn #Null
    EndIf
    
    ; --- Wegen Array Initialisieren
    InitializeStructure(*TileSet, struct_tileset)
    
    ; --- Automatische Berechnung der Spalten und Zeilen
    Rows      = ImageHeight(tImage) / TileHeight
    Cols      = ImageWidth(tImage)  / TileWidth
    MaxTiles  = Rows * Cols
    
    ; --- Anpassen der Maximal lesbaren Tiles
    If Tiles > MaxTiles Or Tiles = #PB_Any
      Tiles = MaxTiles
    EndIf
    
    ; --- Dimensionierung des Arrays
    Dim *TileSet\Sprite(Tiles)
    
    For y = 0 To Rows-1
      For x = 0 To Cols-1
        Counter + 1
        ; --- Tile Ausschneiden
        tTileImage = GrabImage(tImage, #PB_Any, x * TileWidth, y * TileHeight, TileWidth, TileHeight)
        If IsImage(tTileImage)
          tSprite = CreateSprite(#PB_Any, TileWidth, TileHeight, SpriteMode)
          If IsSprite(tSprite)
            ; --- Tile auf Sprite zeichnen
            If StartDrawing(SpriteOutput(tSprite))
              DrawingMode(#PB_2DDrawing_AllChannels)
              Box(0, 0, TileWidth, TileHeight, $00000000)
              DrawAlphaImage(ImageID(tTileImage), 0, 0, 255)
              StopDrawing()
            EndIf
          EndIf
        EndIf
        If IsSprite(tSprite)
          *TileSet\Sprite(Counter) = tSprite            
        EndIf
        If IsImage(tTileImage) : FreeImage(tTileImage) : tTileImage = #Null : EndIf
        If Counter = Tiles
          x = Cols : y = Rows  
        EndIf
      Next x
    Next y
        
  EndIf
  
  ; --- Adresse des Speichers rausgeben
  ProcedureReturn *TileSet
  
EndProcedure
Procedure FreeTileSet(*TileSet.struct_tileset)
  
  Protected Tiles, i
  
  If *TileSet
    
    Tiles = ArraySize(*TileSet\Sprite())
    For i = 0 To Tiles
      If IsSprite(*TileSet\Sprite(i))
        FreeSprite(*TileSet\Sprite(i))
      EndIf
    Next i
    
    FreeArray(*TileSet\Sprite())
    ClearStructure(*TileSet, struct_tileset)
    FreeMemory(*TileSet)
    
  EndIf
  
EndProcedure
Procedure DisplayTile(*TileSet.struct_tileset, Tile, x, y, Intensity = 255, Color = -1)
  
  If *TileSet
    
    If Intensity < 0 : Intensity = 0 : EndIf
    If Intensity > 255 : Intensity = 255 : EndIf
    
    If Tile >= 0 And Tile <= ArraySize(*TileSet\Sprite())
      If IsSprite(*TileSet\Sprite(Tile))
        If Color > -1
          DisplayTransparentSprite(*TileSet\Sprite(Tile), x, y, Intensity, Color)
        Else
          DisplayTransparentSprite(*TileSet\Sprite(Tile), x, y, Intensity)
        EndIf
      EndIf        
    EndIf
    
  EndIf
  
EndProcedure
Procedure GetTileCount(*TileSet.struct_tileset)
  
  Protected Result
  
  If *TileSet
    Result = ArraySize(*TileSet\Sprite())  
  EndIf
  
  ProcedureReturn Result
    
EndProcedure
Edit:

ich vergaß ... die Benutzung....

Code: Alles auswählen

UsePNGImageDecoder()
InitSprite()

Procedure DisplayScreen(*MapTiles)
  
  Static Anim
  
  Anim + 1
  If Anim > GetTileCount(*MapTiles)
    Anim = 1
  EndIf
  
  ClearScreen(#White)
  DisplayTile(*MapTiles, Anim, 24, 46)
  FlipBuffers()
  
  Delay(100)
  
EndProcedure

PfadZumBild.s = "D:\WoIst\DasBild.png" ; <-- selbst eintragen
TileX = 48 : TileY = 48 : Anzahl = 14

OpenWindow(0, 0,0,48*2, 92*2,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 48*2, 92*2)

*MapTiles.struct_tileset = LoadTileSet(PfadZumBild, TileX, TileY, Anzahl)

SetWindowTitle(0, "Es sind "+Str( ArraySize(*MapTiles\Sprite()) ) + " Sprites geladen")

Anim = 1
Repeat
  Event = WindowEvent()
  
  If Event = #PB_Event_None
    DisplayScreen(*MapTiles)
  EndIf
  
  If event = #PB_Event_CloseWindow
    Quit = 1
  EndIf

  
Until Quit > 0

FreeTileSet(*MapTiles)
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 »

Lustig, ich konnte es auch nicht lassen und musste auch noch die Möglichkeit mit Clip-Sprite probieren.
Dabei habe ich herausgefunden, dass ClipSprite keine relevante Rechenzeit braucht, daher ist es absolut unnötig das Sprite für jedes Tile zu kopieren (wie in einem der ersten Posts).

Hier ein Bild zum Testen: http://leerlijn3d.files.wordpress.com/2 ... estrip.png

Code: Alles auswählen

EnableExplicit

InitSprite()
InitKeyboard()

UsePNGImageDecoder()

Structure TileSet
  id.i
  width.i
  height.i
  rows.i
  cols.i
  
EndStructure

Define walker.TileSet

Define.i anim


Procedure LoadTileSet(*id.TileSet,path.s,width,height,rows,cols)
  
  *id\id = LoadSprite(#PB_Any,path,#PB_Sprite_AlphaBlending)
  
  If *id\id = 0
    ProcedureReturn 0
  EndIf
  
  *id\width = width
  *id\height = height
  *id\rows = rows
  *id\cols = cols
  
  ProcedureReturn 1
  
EndProcedure

Procedure DisplayClipSpriteTile(*id.TileSet,tile,x,y,alpha=255)
  If (*id\rows**id\cols) <= tile Or tile < 0
    ProcedureReturn 0
  Else
    ClipSprite(*id\id,(tile%*id\cols)**id\width,Int(tile/*id\rows)**id\height,*id\width,*id\height)  
    DisplayTransparentSprite(*id\id,x,y,alpha)
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure DisplayClipSpriteTileCoord(*id.TileSet,tileX,tileY,x,y,alpha=255)
  If (*id\rows) <= tileX Or (*id\cols) <= tileY Or tileX < 0 Or tileY < 0
    ProcedureReturn 0
  Else
    ClipSprite(*id\id,tileX**id\width,tileY**id\height,*id\width,*id\height)  
    DisplayTransparentSprite(*id\id,x,y,alpha)
    ProcedureReturn 1
  EndIf
EndProcedure


Define.i screenWidth = 1920, screenHeight = 1080
If Not OpenScreen(screenWidth,screenHeight,32,"Test")
  End
EndIf

; -> http://leerlijn3d.files.wordpress.com/2012/03/lopenrechts_spritestrip.png
LoadTileSet(@walker,"lopenrechts_spritestrip.png",256,256,5,5)

Repeat
  
  ClearScreen(RGB(255,255,anim%256))
  
  DisplayClipSpriteTile(@walker,(anim%48)/2,anim*3-256,screenHeight/2-128)
  
  DisplayClipSpriteTileCoord(@walker,4,4,10,10)
  
  anim+1
  If anim >= (screenWidth+512)/3
    anim = 0
  EndIf
  
  FlipBuffers()
  ExamineKeyboard()
  
Until KeyboardPushed(#PB_Key_Escape)

End
Dabei ist mir auch noch aufgefallen (Wie Bisonte wohl auch), dass man GrabSprite spätestens bei Tilesets mit Alphakanal komplett vergessen kann...


Edit:
Hab mir noch erlaubt Bisontes Beispiel anzupassen:

Code: Alles auswählen

EnableExplicit
UsePNGImageDecoder()
InitSprite()

Procedure DisplayScreen(*MapTiles)
  
  Static Anim
  
  Anim + 1
  If Anim > GetTileCount(*MapTiles)
    Anim = 1
  EndIf
  
  ClearScreen(#White)
  DisplayTile(*MapTiles, Anim, 0, 0)
  FlipBuffers()
  
  Delay(100)
  
EndProcedure


Define PfadZumBild.s
Define TileX,TileY,Anzahl
Define Event, Quit

PfadZumBild.s = "lopenrechts_spritestrip.png" ; <-- selbst eintragen
TileX = 256 : TileY = 256 : Anzahl = 24

OpenWindow(0, 0,0,TileX, TileY,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, TileX, TileY)

Define *MapTiles.struct_tileset
*MapTiles.struct_tileset = LoadTileSet(PfadZumBild, TileX, TileY, Anzahl)

SetWindowTitle(0, "Es sind "+Str( ArraySize(*MapTiles\Sprite()) ) + " Sprites geladen")

Repeat
  Event = WindowEvent()
  
  If Event = #PB_Event_None
    DisplayScreen(*MapTiles)
  EndIf
  
  If event = #PB_Event_CloseWindow
    Quit = 1
  EndIf

  
Until Quit > 0

FreeTileSet(*MapTiles)
LG KeyKon
(\/) (°,,,°) (\/)
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: CreateSprite aus ClipSprite erstellen?!?

Beitrag von Bisonte »

KeyKon hat geschrieben:Lustig, ich konnte es auch nicht lassen
Ja genau... wenn einen der Ehrgeiz packt :mrgreen:
KeyKon hat geschrieben:Dabei ist mir auch noch aufgefallen (Wie Bisonte wohl auch), dass man GrabSprite spätestens bei Tilesets mit Alphakanal komplett vergessen kann...
LG KeyKon
ClipSprite hab ich noch nie benutzt :lol:
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 »

Bisonte hat geschrieben:ClipSprite hab ich noch nie benutzt :lol:
Ich bis heute auch nicht^^
(\/) (°,,,°) (\/)
Antworten