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

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Ara
Beiträge: 35
Registriert: 29.08.2004 13:40

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

Beitrag 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
Win11 Pro
PureBasic 6.10 LTS
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

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

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
HeX0R
Beiträge: 3042
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

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

Beitrag 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.
Ara
Beiträge: 35
Registriert: 29.08.2004 13:40

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

Beitrag 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
Win11 Pro
PureBasic 6.10 LTS
Antworten