Seite 1 von 1

TransparentSpriteColor - mal gehts, mal nicht

Verfasst: 11.10.2011 16:40
von Makke
Hallo,

ich habe mal zur Übung mit Sprite3D rumgespielt und folgendes Problem, ich benutze 2 Sprites und erstelle daraus 3D-Sprites, bei beiden Sprites setze ich den Befehl TransparentSpriteColor, bei dem ersten Sprite ist der Hintergrund dann auch transparent, bei dem zweiten nicht. Hier ist das Beispiel, ich wollte es evtl. als Screensaver nutzen:

Code: Alles auswählen

; Sprite 3D Test by Makke
; 2011-11-10

EnableExplicit

; hardware initialization
If InitSprite()
  If InitSprite3D()
    If InitKeyboard()
      If InitMouse()
        Debug "init done"
      Else
        Debug "init mouse failed"
        End
      EndIf
    Else
      Debug "init keyboard failed"
      End
    EndIf
  Else
    Debug "init sprite 3d failed"
    End
  EndIf
Else
  Debug "init sprite failed"
  End
EndIf

; constants
#DESKTOP_MAIN = 0
Enumeration
  #TEXTFONT
  #DESKTOP_IMAGE
  #DESKTOP_SPRITE
  #SPRITE2D_HANDLE
  #SPRITE3D_HANDLE
  #GRAB_IMAGE
  #GRAB_SPRITE2D
  #GRAB_SPRITE3D
EndEnumeration
#SPRITE2D_TRANSCOL = $000000  
#BUBBLE_SPEED      = 3
#ZOOMINPX          = 25

; lists
NewList MaskList.POINT()

; vars
ExamineDesktops()
Define Desk_Width.i  = DesktopWidth(#DESKTOP_MAIN)
Define Desk_Height.i = DesktopHeight(#DESKTOP_MAIN)
Define Desk_Depth.i  = DesktopDepth(#DESKTOP_MAIN)
Define Desk_Freq.i   = DesktopFrequency(#DESKTOP_MAIN)
Define ShowFPS.i     = #False

Define Bubble.RECT
Define BubbleLen.i

Define SpeedH.i = #BUBBLE_SPEED
Define SpeedV.i = #BUBBLE_SPEED

; procs
Procedure.i GetTransparencyMask()
  Shared MaskList()
  Shared BubbleLen
  Define tempimg.i
  Define x.i
  Define y.i
  Define w.i = BubbleLen - (#ZOOMINPX * 2)
  Define h.i = w
  tempimg = CreateImage(#PB_Any, w, h)
  If Not IsImage(tempimg)
    Debug "can not create mask image"
    ProcedureReturn #False
  EndIf
  StartDrawing(ImageOutput(tempimg))
  Box(0, 0, w, h, $FFFFFF)
  DrawingMode(#PB_2DDrawing_Outlined)
  Circle(w / 2, h / 2, (w - (#ZOOMINPX * 2)) / 2, #SPRITE2D_TRANSCOL)
  DrawingMode(#PB_2DDrawing_Transparent)
  FillArea(0, 0, #SPRITE2D_TRANSCOL, #SPRITE2D_TRANSCOL)
  For x = 0 To w - 1
    For y = 0 To h - 1
      If Point(x, y) = #SPRITE2D_TRANSCOL
        AddElement(MaskList())
        MaskList()\x = x
        MaskList()\y = y
      EndIf
    Next
  Next
  StopDrawing()
  FreeImage(tempimg)
  ProcedureReturn ListSize(MaskList())
EndProcedure

Procedure.i GetDesktopBackgroundAsSprite()
  Shared Desk_Width
  Shared Desk_Height
  Define hDC.i
  Define DeskDC.i
  CreateImage(#DESKTOP_IMAGE, Desk_Width, Desk_Height)
  hDC    = StartDrawing(ImageOutput(#DESKTOP_IMAGE))
  DeskDC = GetDC_(GetDesktopWindow_())
  BitBlt_(hDC, 0, 0, Desk_Width, Desk_Height, DeskDC, 0, 0, #SRCCOPY)
  StopDrawing()
  ReleaseDC_(GetDesktopWindow_(), DeskDC)
  If IsImage(#DESKTOP_IMAGE)
    ;SaveImage(#DESKTOP_IMAGE, "desktop.bmp")
    CreateSprite(#DESKTOP_SPRITE, Desk_Width, Desk_Height)
    If IsSprite(#DESKTOP_SPRITE)
      StartDrawing(SpriteOutput(#DESKTOP_SPRITE))
      DrawImage(ImageID(#DESKTOP_IMAGE), 0, 0)
      StopDrawing()
      ;FreeImage(#DESKTOP_IMAGE)
      ProcedureReturn #True
    Else
      Debug "can't create sprite #DESKTOP_SPRITE"
      ProcedureReturn #False
    EndIf
  Else
    Debug "can't create image #DESKTOP_IMAGE"
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.i GetBackgroundPart()
  Shared MaskList()
  Shared Desk_Width
  Shared Desk_Height
  Shared Bubble
  Shared BubbleLen
  If Bubble\top < 0 Or Bubble\left < 0 Or Bubble\right > Desk_Width Or Bubble\bottom > Desk_Height
    ProcedureReturn #False
  EndIf
  If IsImage(#GRAB_IMAGE)
    FreeImage(#GRAB_IMAGE)
  EndIf
  GrabImage(#DESKTOP_IMAGE, #GRAB_IMAGE, Bubble\left + #ZOOMINPX, Bubble\top + #ZOOMINPX, BubbleLen - (#ZOOMINPX * 2), BubbleLen - (#ZOOMINPX * 2))
  If Not IsImage(#GRAB_IMAGE)
    Debug "can not grab image #GRAB_IMAGE"
    ProcedureReturn #False
  EndIf
  StartDrawing(SpriteOutput(#GRAB_SPRITE2D))
  DrawingMode(#PB_2DDrawing_Default)
  DrawImage(ImageID(#GRAB_IMAGE), 0, 0)
  ForEach MaskList()
    Plot(MaskList()\x, MaskList()\y, #SPRITE2D_TRANSCOL)
  Next
  StopDrawing()
  If IsSprite3D(#GRAB_SPRITE3D)
    FreeSprite3D(#GRAB_SPRITE3D)
  EndIf
  CreateSprite3D(#GRAB_SPRITE3D, #GRAB_SPRITE2D)
  If IsSprite3D(#GRAB_SPRITE3D)
    ProcedureReturn #True
  Else
    Debug "can not create #GRAB_SPRITE3D"
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.s GetFPS()
  Static timer.i
  Static counter.i
  Static lastFPS.s
  counter + 1 : Debug counter
  If ElapsedMilliseconds() - timer >= 1000
    lastFPS = Str(counter)
    counter = 0
    timer   = ElapsedMilliseconds()
  EndIf
  ProcedureReturn lastFPS
EndProcedure

; font
LoadFont(#TEXTFONT, "Verdana", 14, #PB_Font_HighQuality|#PB_Font_Bold)

; open screen
If OpenScreen(Desk_Width, Desk_Height, Desk_Depth, "BUBBLE", #PB_Screen_SmartSynchronization, Desk_Freq)
  StartDrawing(ScreenOutput())
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(#TEXTFONT))
  DrawText((Desk_Width - 60) / 2, (Desk_Height - 8) / 2, "LOADING ...", $FFFFFF)
  StopDrawing()
  FlipBuffers()
Else
  Debug "can not open screen"
  End
EndIf

; graphics
TransparentSpriteColor(#PB_Default, #SPRITE2D_TRANSCOL)
If CatchSprite(#SPRITE2D_HANDLE, ?BUBBLE, #PB_Sprite_Texture)
  ;TransparentSpriteColor(#SPRITE2D_HANDLE, #SPRITE2D_TRANSCOL)
  CreateSprite3D(#SPRITE3D_HANDLE, #SPRITE2D_HANDLE)
  BubbleLen = SpriteWidth(#SPRITE2D_HANDLE)
Else
  Debug "can not catch bubble"
  End
EndIf
If CreateSprite(#GRAB_SPRITE2D, BubbleLen - (#ZOOMINPX * 2), BubbleLen - (#ZOOMINPX * 2), #PB_Sprite_Texture)
  ;TransparentSpriteColor(#GRAB_SPRITE2D, #SPRITE2D_TRANSCOL)
Else
  Debug "can not create #GRAB_SPRITE2D"
  End
EndIf
If Not GetTransparencyMask()
  Debug "creating mask list failed"
  End
EndIf
If Not GetDesktopBackgroundAsSprite()
  Debug "creating desktop backgrd as sprite failed"
  End
EndIf

; starting position
With Bubble
  \top    = 0 - BubbleLen
  \left   = 0 - BubbleLen
  \right  = 0
  \bottom = 0
EndWith

; loop
Repeat
  ; backgrd
  DisplaySprite(#DESKTOP_SPRITE, 0, 0)
  ; move the bubble
  With Bubble
    If \top <= 0 And SpeedV = #BUBBLE_SPEED * -1
      SpeedV = #BUBBLE_SPEED
    ElseIf \bottom >= Desk_Height And SpeedV = #BUBBLE_SPEED
      SpeedV = #BUBBLE_SPEED * -1
    EndIf
    If \left <= 0 And SpeedH = #BUBBLE_SPEED * -1
      SpeedH = #BUBBLE_SPEED
    ElseIf \right >= Desk_Width And SpeedH = #BUBBLE_SPEED
      SpeedH = #BUBBLE_SPEED * -1
    EndIf
    \top    = \top  + SpeedV
    \left   = \left + SpeedH
    \right  = \left + BubbleLen
    \bottom = \top  + BubbleLen
    Start3D()
    If GetBackgroundPart()
      ZoomSprite3D(#GRAB_SPRITE3D, BubbleLen, BubbleLen)
      DisplaySprite3D(#GRAB_SPRITE3D, \left, \top, 224)
    EndIf
    DisplaySprite3D(#SPRITE3D_HANDLE, \left, \top, 128)
    Stop3D()
  EndWith
  If ShowFPS = #True
    StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#TEXTFONT))
    DrawText(Desk_Width - 90, 5, "FPS: " + GetFPS(), $000000)
    StopDrawing()
  EndIf
  ; testing
  DisplayTransparentSprite(#GRAB_SPRITE2D, 0, 0)
  ; input
  ExamineMouse()
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_F)
    If ShowFPS = #True
      ShowFPS = #False
    Else
      ShowFPS = #True
    EndIf
  EndIf
  ; buffer management
  FlipBuffers()
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)

End
DataSection
  BUBBLE:
  IncludeBinary "bubble.bmp" ; Paint.NET Forum: http://forums.getpaint.net/index.php?/topic/12294-a-way-to-create-bubbles/
EndDataSection
Die Grafik die ich einbinde ist hier: Bild

Hat jemand einen Tip warum das zweite Sprite das ich erstelle die Transparenz nicht berücksichtigt ? Auch wenn ich das Sprite als Transparentes-Sprite anzeigen lassen, wird die Transparenz nicht berücksichtigt.

Hier noch ein Bild wie sich der Fehler bei mir darstellt: Bild

Re: TransparentSpriteColor - mal gehts, mal nicht

Verfasst: 14.10.2011 16:18
von Makke
Eigentlich gehört es sich nicht auf den eigenen Thread zu antworten, aber ich habe das beschriebene Problem anders aus dem Weg geräumt. Siehe:

Code: Alles auswählen

      DrawingMode(#PB_2DDrawing_Outlined)
      Circle(size / 2, size / 2, (size - (#ZOOMINPX * 2)) / 2, #SPRITE2D_TRANSCOL)
      DrawingMode(#PB_2DDrawing_Default)
      FillArea(0, 0, #SPRITE2D_TRANSCOL, #SPRITE2D_TRANSCOL)
      StopDrawing()
Das ist fast genau so schnell wie die Liste mit Plot, aber leider im extrem Fall (pinker Bildschirmhintergrund) auch Fehleranfällig.

Falls doch nochmal jemand eine Idee (oder ist es ein Bug in PB) zu dem oben beschriebenen Problem hat, ich würd mich freuen.

Re: TransparentSpriteColor - mal gehts, mal nicht

Verfasst: 14.10.2011 16:48
von Ramihyn_
Vielleicht missverstehe ich ja etwas und ich hab auch nicht den ganzen Source durchgeschaut um zu sehen was Du genau machst, aber hast Du es mal mit einem PNG mit Transparenz Infos probiert? Du benutzt ja eine BMP Datei und die haben keine Transparenzdaten.

Re: TransparentSpriteColor - mal gehts, mal nicht

Verfasst: 14.10.2011 19:59
von Makke
In der PB-Hilfe steht, dass die Transparenz von PNG nicht berücksichtigt wird (ausser bei den Gadgets). Ist das nicht mehr der Fall ?

Zudem erstelle ich bei meinem Problem ein Sprite zur Laufzeit, bei diesem soll eine bestimmter Bereich (quasi eine Maske) transparent sein. Das Erstellen, Speichern und wieder laden eines Bildes ist (ohne es ausprobiert zu haben) aber mit Sicherheit zu langsam. Trotzdem Danke für den Vorschlag.

Re: TransparentSpriteColor - mal gehts, mal nicht

Verfasst: 15.10.2011 14:48
von Thorium
Makke hat geschrieben:In der PB-Hilfe steht, dass die Transparenz von PNG nicht berücksichtigt wird (ausser bei den Gadgets). Ist das nicht mehr der Fall ?

Zudem erstelle ich bei meinem Problem ein Sprite zur Laufzeit, bei diesem soll eine bestimmter Bereich (quasi eine Maske) transparent sein. Das Erstellen, Speichern und wieder laden eines Bildes ist (ohne es ausprobiert zu haben) aber mit Sicherheit zu langsam. Trotzdem Danke für den Vorschlag.
Es wird berücksichtigt, wenn du 3D Sprites verwendest. Natürlich kannst du auch Sprites mit Alphakanal erstellen. Einfach mit 32 Bit Farbtiefe erstellen und dann kannst du auf den Alphakanal zugreifen genau wie auf die 3 Farbkanäle.