Seite 1 von 1

Ruckler bei der Drehung und nach einiger Zeit Die angegebene Ausgabe ist NULL

Verfasst: 03.01.2023 04:49
von Ara
Ich habe PureBasic schon sehr lange, habe aber noch nicht viel damit gemacht.
Hier einmal ein Beispiel, das nur zwei mal die Uhrzeit anzeigt. Die untere dreht sich.

Bei der unteren Anzeige Ruckelt im Sekundentackt, nach einiger Zeit erhalte ich den Fehler:

Code: Alles auswählen

[21:07:04] Warte auf den Start des Executable...
[21:07:04] Executable-Typ: Windows - x64  (64bit, Unicode)
[21:07:04] Executable gestartet.
[22:30:16] [ERROR] test_anzeige.pb (Zeile: 96)
[22:30:16] [ERROR] StartDrawing(): Die angegebene Ausgabe ist NULL (0 Wert).
Was würdet ihr hier anders machen und vor allem warum.
Wie kann man die Drehung flüssig laufen lassen?
Wo kommt der Fehler in Zeile 96 her und wie kann man ihn vermeiden?

Code: Alles auswählen

InitSprite()

Global utime.l
Global text0.s, text1.s
Global a.f, j.f, x1.f, x2.f, x3.f, x4.f, y1.f, y2.f, y3.f, y4.f, z1.f, z2.f, z3.f, z4.f, HalfSizeX, HalfSizeY, Distance

EnableExplicit

Enumeration Window
  #Window
EndEnumeration

Enumeration Font
  #Font_0
  #Font_1
EndEnumeration

Enumeration Font
  #Sprite_0
  #Sprite_1
  #Sprite_2
EndEnumeration

Enumeration Image
  #Image
EndEnumeration

Structure fonttextinfo
  tmA.l               ;Basislinie von oben
  tmD.l               ;Basislinie von unten
  tmH.l               ;Texthöhe
  tmW.l               ;Textbreite
EndStructure

Global Dim fonttextinfo.fonttextinfo(1)

LoadFont(#Font_0, "Arial", 150)
LoadFont(#Font_1, "Arial", 75)

; Ruhezustand abschalten
If OpenLibrary(0, "Kernel32.dll")
  Prototype SetThreadExecutionState(esFlags)
  Define SetThreadExecutionState.SetThreadExecutionState = GetFunction(0, "SetThreadExecutionState")
  CloseLibrary(0)
EndIf
SetThreadExecutionState(#ES_CONTINUOUS | #ES_SYSTEM_REQUIRED | #ES_AWAYMODE_REQUIRED | #ES_DISPLAY_REQUIRED)

Procedure getTextInfo(t, text$)
  Protected tm.TEXTMETRIC
  Protected lg.SIZE
  Protected hdc = GetWindowDC_(WindowID(#Window))
  
  SelectObject_(hdc, FontID(t))
  GetTextMetrics_(hdc, @tm.TEXTMETRIC)
  GetTextExtentPoint32_(hdc, text$, Len(text$), @lg.SIZE)
  fonttextinfo(t)\tmA = tm\tmAscent
  fonttextinfo(t)\tmD = tm\tmDescent
  fonttextinfo(t)\tmH = tm\tmHeight
  fonttextinfo(t)\tmW = lg\cx
EndProcedure

Procedure Open_Window(X = 0, Y = 0, Width = 800, Height = 600)
  If OpenWindow(#Window, X, Y, Width, Height, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    OpenWindowedScreen(WindowID(#Window), 0, 0, Width, Height)
  EndIf
EndProcedure

Open_Window()

Repeat
  If Date() > utime
    utime = Date()
    text0 = "%hh:%ii"
    text1 = "%ss"
    text0 = FormatDate(text0, Date())
    text1 = FormatDate(text1, Date())
    
    getTextInfo(#Font_0, text0)
    
    CreateSprite(#Sprite_0, fonttextinfo(#Font_0)\tmW, fonttextinfo(#Font_0)\tmH)
    StartDrawing(SpriteOutput(#Sprite_0))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#Font_0))
    DrawText(0, 0, text0, RGB(Val("$FF"), Val("$A0"), Val("$20")))
    StopDrawing()
    
    getTextInfo(#Font_1, text1)
    CreateSprite(#Sprite_1, fonttextinfo(#Font_1)\tmW, fonttextinfo(#Font_1)\tmH)
    StartDrawing(SpriteOutput(#Sprite_1))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#Font_1))
    DrawText(0, 0, text1, RGB(Val("$FF"), Val("$A0"), Val("$20")))
    StopDrawing()
    
    CreateSprite(#Sprite_2, fonttextinfo(#Font_0)\tmW+fonttextinfo(#Font_1)\tmW+30, fonttextinfo(#Font_0)\tmH)
    StartDrawing(SpriteOutput(#Sprite_2))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#Font_0))
    DrawText(0, 0, text0, RGB(Val("$FF"), Val("$A0"), Val("$20")))
    
    DrawingFont(FontID(#Font_1))
    DrawText(fonttextinfo(#Font_0)\tmW+30, fonttextinfo(#Font_0)\tmA-fonttextinfo(#Font_1)\tmA, text1, RGB(Val("$FF"), Val("$A0"), Val("$20")))
    StopDrawing()
  EndIf
  
  If IsSprite(#Sprite_0) And IsSprite(#Sprite_1) And IsSprite(#Sprite_2)
    ClearScreen(RGB(0, 0, 0))
    
    HalfSizeX = (fonttextinfo(#Font_0)\tmW+fonttextinfo(#Font_1)\tmW+30)/2
    HalfSizeY = (fonttextinfo(#Font_0)\tmH)/2
    Distance = 200
    
    a = ElapsedMilliseconds()/400
    a*-1
    
    z1 = Distance-Sin(a)*HalfSizeY : z4=z1
    z2 = Distance+Sin(a)*HalfSizeY : z3=z2
    x1 = -Cos(a)*HalfSizeX*Distance/z1 : x4=x1
    x2 =  Cos(a)*HalfSizeX*Distance/z2 : x3=x2
    j = HalfSizeY*HalfSizeY
    y1 = -HalfSizeY-Sin(a)*j/z1 : y2=-HalfSizeY+Sin(a)*j/z2
    y3 =  HalfSizeY-Sin(a)*j/z3 : y4= HalfSizeY+Sin(a)*j/z4
    
    TransformSprite(#Sprite_2, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4)
    
    DisplayTransparentSprite(#Sprite_0, 80, 200-fonttextinfo(#Font_0)\tmA)
    DisplayTransparentSprite(#Sprite_1, 610, 200-fonttextinfo(#Font_1)\tmA)
    DisplayTransparentSprite(#Sprite_2, 400, 600-fonttextinfo(#Font_0)\tmA)
    
    FlipBuffers()
  EndIf
  
  Select WaitWindowEvent(1)
    
    Case #PB_Event_CloseWindow
      Break
      
    EndSelect
ForEver
Vielen Dank schon einmal für eure Hilfe.
Thomas

Re: Ruckler bei der Drehung und nach einiger Zeit Die angegebene Ausgabe ist NULL

Verfasst: 04.01.2023 12:09
von STARGÅTE
Ara hat geschrieben: 03.01.2023 04:49 Was würdet ihr hier anders machen und vor allem warum.
Du solltest nicht jedes mal wenn sich die Zeit ändert auch die Sprites erstellen (CreateSprite), sondern einfach einmal alle drei Sprites erstellen (größtmöglich) und dann immer nur das Sprite leere und den neuen Text draufzeichnen.
Ara hat geschrieben: 03.01.2023 04:49 Wie kann man die Drehung flüssig laufen lassen?
Bei mir dreht es sich flüssig. Habe volle 60 FPS was mein Bildschirm hergibt.
Ara hat geschrieben: 03.01.2023 04:49 Wo kommt der Fehler in Zeile 96 her und wie kann man ihn vermeiden?
Der Fehler kommt, weil das SpriteOutput() Null zurückgibt. Warum es das macht kann ich dir nicht sagen. Wenn es ein problem mit dem Sprite gäbe, dann würde es ehr so eine Fehlermeldung geben: [ERROR] Das angegebene #Sprite ist nicht initialisiert.

Re: Ruckler bei der Drehung und nach einiger Zeit Die angegebene Ausgabe ist NULL

Verfasst: 04.01.2023 13:18
von HeX0R
Ich denke das SpriteOutput-Problem kommt von hier:
https://learn.microsoft.com/en-us/windo ... etwindowdc
After painting is complete, the ReleaseDC function must be called to release the device context. Not releasing the window device context has serious effects on painting requested by applications.
Bei mir ruckelt übrigens auch nix.

Re: Ruckler bei der Drehung und nach einiger Zeit Die angegebene Ausgabe ist NULL

Verfasst: 05.01.2023 04:40
von Ara
Danke für die Hilfe.
Der Fehler scheint weg zu sein.
Geändert habe ich

Code: Alles auswählen

Procedure getTextInfo(t, text$)
  Protected tm.TEXTMETRIC
  Protected lg.SIZE
  Protected hdc = GetWindowDC_(WindowID(#Window))
  
  SelectObject_(hdc, FontID(t))
  GetTextMetrics_(hdc, @tm.TEXTMETRIC)
  GetTextExtentPoint32_(hdc, text$, Len(text$), @lg.SIZE)
  fonttextinfo(t)\tmA = tm\tmAscent
  fonttextinfo(t)\tmD = tm\tmDescent
  fonttextinfo(t)\tmH = tm\tmHeight
  fonttextinfo(t)\tmW = lg\cx
  
  ReleaseDC_(WindowID(#Window), hdc)
EndProcedure
Das mit dem CreateSprite habe ich einfach so abgeändert.

Code: Alles auswählen

    If IsSprite(#Sprite_0) = 0
      CreateSprite(#Sprite_0, fonttextinfo(#Font_0)\tmW, fonttextinfo(#Font_0)\tmH)
    EndIf
Das mit dem ruckeln ist so ein leichtes zucken, wenn die Sprites einen neuen Text bekommen.
Vielleicht ist mein 8 Jahre alter Rechner für so etwas zu alt.
Seit gestern Abend läuft es ohne abzuschmieren und das ist das wichtigste.

Danke und viele Grüße
Thomas