Seite 2 von 2

Re: CreateSprite aus ClipSprite erstellen?!?

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

Re: CreateSprite aus ClipSprite erstellen?!?

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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 19.09.2013 02:05
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)

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 19.09.2013 12:29
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

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 19.09.2013 12:48
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:

Re: CreateSprite aus ClipSprite erstellen?!?

Verfasst: 19.09.2013 15:52
von KeyKon
Bisonte hat geschrieben:ClipSprite hab ich noch nie benutzt :lol:
Ich bis heute auch nicht^^