Problem mit Sprung aus einer Schleife

Anfängerfragen zum Programmieren mit PureBasic.
moin
Beiträge: 59
Registriert: 03.07.2007 08:38
Wohnort: Norddeutschland

Problem mit Sprung aus einer Schleife

Beitrag von moin »

Hallo,
ich schlage mich als Anfänger mit wohl einfachen Problemen herum.
Das folgende Program habe ich aus zwei Beispielen zusammen geschrieben.
Es werden erst Kreise und dann ein kreisender Strich gezeichnet.
Das funktioniert auch soweit.
Ich möchte aber in einer andauernden Schleife immer weiter die Striche sich kreisen lassen, bis ich das Fenster schließe.
Könnt ihr mir bei diesem Problemchen helfen?
Danke

Code: Alles auswählen

 ;PureBasic DEMO 4.00
 
  ; Mehrere Kreise in zufälligen Farben


InitSprite() 
InitKeyboard() 
Width=700
  Height=500 

#ScreenBits   = 32 
MiddleX      = Width  / 2 
MiddleY      = Height / 2 
Radius       = 100 

Procedure.f GSin(winkel.f) 
   ; Eingabe: Winkel ( 0 - 360 ) 
   ; Ausgabe: Sinus vom Winkel 
   ProcedureReturn Sin(winkel*(2*3.14159265/360)) 
EndProcedure 

Procedure.f GCos(winkel.f) 
   ; Eingabe: Winkel ( 0 - 360 ) 
   ; Ausgabe: Cosinus vom Winkel 
   ProcedureReturn Cos(winkel*(2*3.14159265/360)) 
EndProcedure 

  Width=700
  Height=500 
  If OpenWindow(0, 0, 0, Width, Height, "Lines", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If StartDrawing(WindowOutput(0))
      x = Width/2
      y = Height/2
      For Radius = Height/3 To 10 Step -10
        Circle(x, y, radius ,RGB(Random(255),Random(255),Random(255)))
      Next
     StopDrawing() 
   EndIf
  EndIf   
 
 Delay(1000)
 
 x = Width/4
 y = Height/4
 
                                                          
                                                           ;If StartDrawing(WindowOutput(0))
                                                           ;   LineXY(410,410,550,655, $0000ff) 
                                                           ;    StopDrawing() 
                                                           ; EndIf  
   
   ;Striche wandern im Kreis  
 If StartDrawing(WindowOutput(0))
     Radius = Height/3
     For grad=0 To 359 Step 1
     LineXY(x,y,x+GSin(grad)*Radius,y+GCos(grad)*Radius, RGB(Random(255),Random(255),Random(255)))
     Delay(10)
     Next
     StopDrawing() 
 EndIf

 Repeat : Event = WaitWindowEvent() : Until  Event = #PB_Event_CloseWindow 
    
   ;Delay(3000)  ;
   
End

;Problem: Ich möchte die letzte Schleige mit den wandernden Strichen solange durchlaufebn lassen,
;bis das Fenster gescholossen wird. Bislang wird das Programm durchlaufen und dann gewartet, dass
;das Fenster geschlossen wird. Eine andauernde Wiederholung habe ich nicht hinbekommen.



Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

;PureBasic DEMO 4.00

; Mehrere Kreise in zufälligen Farben


InitSprite()
InitKeyboard()
Width=700
Height=500

#ScreenBits   = 32
MiddleX      = Width  / 2
MiddleY      = Height / 2
Radius       = 100

Procedure.f GSin(winkel.f)
  ; Eingabe: Winkel ( 0 - 360 )
  ; Ausgabe: Sinus vom Winkel
  ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure

Procedure.f GCos(winkel.f)
  ; Eingabe: Winkel ( 0 - 360 )
  ; Ausgabe: Cosinus vom Winkel
  ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure

Width=700
Height=500
If OpenWindow(0, 0, 0, Width, Height, "Lines", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If StartDrawing(WindowOutput(0))
    x = Width/2
    y = Height/2
    For Radius = Height/3 To 10 Step -10
      Circle(x, y, radius ,RGB(Random(255),Random(255),Random(255)))
    Next
    StopDrawing()
  EndIf
EndIf

Delay(1000)

x = Width/4
y = Height/4

Repeat
  Event = WaitWindowEvent(3000)
  ;Striche wandern im Kreis
  If Not Event
    If StartDrawing(WindowOutput(0))
      Radius = Height/3
      For grad=0 To 359 Step 1
        LineXY(x,y,x+GSin(grad)*Radius,y+GCos(grad)*Radius, RGB(Random(255),Random(255),Random(255)))
        Delay(10)
      Next
      StopDrawing()
    EndIf
  EndIf
Until  Event = #PB_Event_CloseWindow

;Delay(3000)  ;

End
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
moin
Beiträge: 59
Registriert: 03.07.2007 08:38
Wohnort: Norddeutschland

Beitrag von moin »

Danke
jetzt habe ich auch meinen Fehler gefunden (hatte Repeat immer an der falschen Stelle gesetzt)

Jetzt habe ich aber noch zwei Fragen:
-Wann und an welcher Stelle muß ein "StopDrawing()" eingefügt werden?
-Wie kann man die Dicke der Striche ändern ohne gleich einen zweiten Strich mit einem Pixel Abstand zu zeichnen?
Benutzeravatar
D@nte
Beiträge: 324
Registriert: 24.04.2007 15:33
Wohnort: Berlin

Beitrag von D@nte »

>Wann und an welcher Stelle muß ein "StopDrawing()" eingefügt werden?
PureBasic.chm hat geschrieben:Sobald alle benötigten Grafik-Operationen (eingeleitet mit StartDrawing()) durchgeführt wurden, muss dieser Befehl aufgerufen werden, um anderen laufenden Applikationen wieder das Darstellen eigener Grafiken zu ermöglichen.
>Wie kann man die Dicke der Striche ändern ohne gleich einen zweiten Strich mit einem Pixel Abstand zu zeichnen?
Sollte mit Box() gehen

-----

@Thomas
Wieso braucht dein Code eigentlich nach 720° Linien ~4 seks und dann alle 360° ~4 - 8 seks bis weiter gezeichnet wird?!
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ich hab den code noch etwas bearbeitet

Code: Alles auswählen

;PureBasic DEMO 4.00

; Mehrere Kreise in zufälligen Farben


InitSprite()
InitKeyboard()
Width=700
Height=500

#ScreenBits   = 32
MiddleX      = Width  / 2
MiddleY      = Height / 2
Radius       = 100

Procedure.f GSin(winkel.f)
  ; Eingabe: Winkel ( 0 - 360 )
  ; Ausgabe: Sinus vom Winkel
  ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure

Procedure.f GCos(winkel.f)
  ; Eingabe: Winkel ( 0 - 360 )
  ; Ausgabe: Cosinus vom Winkel
  ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure

Width=700
Height=500
If OpenWindow(0, 0, 0, Width, Height, "Lines", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  x = Width/2      ; Berechnungen aus nem Drawing-Block raushalten
  y = Height/2

  If StartDrawing(WindowOutput(0))
    For Radius = Height/3 To 10 Step -10
      Circle(x, y, radius ,RGB(Random(255),Random(255),Random(255)))
    Next
    StopDrawing()
  EndIf
EndIf

;x = Width/4
;y = Height/4

;*** dieser wert ändert sich nicht mehr,
;    also vor der hauptschleife berechnen
Radius = Height/3

;*** startwert für den durchlaufenden grad-wert 
grad = 0

Repeat
  Event = WaitWindowEvent(10)   ; dies hier gibt das tempo vor

  If Not Event            ; wenn der timer abgelaufen ist

    If StartDrawing(WindowOutput(0))

      ; ** nur eine linie pro Durchlauf
      LineXY(x,y,x+GSin(grad)*Radius,y+GCos(grad)*Radius, RGB(Random(255),Random(255),Random(255)))

      StopDrawing() ; und gleich wieder zu, nur draw-operationen in den drawing-block.

      ; ** grad wird bei jedem durchlauf hochgezählt
      grad +1 : If grad > 359 : grad = 0 : EndIf

    EndIf
  EndIf
Until  Event = #PB_Event_CloseWindow

End
hauptsächlich in der hauptschleife, die änderungen sind kommentiert.

noch etwas:
die berechnung Sinus(Radiant) -> Sinus(Grad) in eine Procedure auszulagern,
ist grundsätzlich programmiertechnisch richtig gedacht....

aber wenn man das dann sehr oft braucht, wird das sehr langsam,
weil man eben jedesmal noch einen zusätzlichen Call braucht.
bei besonders zeitkritischen anwendungen wird man sogar eine wertetabelle
vorab berechnen, weil schon der normale sinus zu langsam ist.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
moin
Beiträge: 59
Registriert: 03.07.2007 08:38
Wohnort: Norddeutschland

Beitrag von moin »

Wenn ich mir eure Lösungsvorschläge ansehe bleiben bei mir doch einige Fragen noch offen:
-Warum sollten sich zwischen Start und StopDrawing nur Zeichenoperationen befinden? Wie wirkt sich anderer Programmcode aus?
- Warum zeigt die Programmversion in meinem Ursprungsbeitrag die unschönen Eigenschaften mit dem Rucklen nach einer 720° Drehung?
Wo ist die entscheidene Stelle?
- Wenn ich das Programmfenster durch ein anderes Programmfenster (z.B. Browser) überdecke und dann wieder hervorhole, wird mein Fenster nur teilweise dargestellt. Alle alten Zeichnungen (Kreise) sind nicht mehr zu sehen.
Woran liegt das? Wie kann verhindet werden, dass der Fensterinhalt verfälscht werden kann?
Wie kann es sein, dass ein PC (Athlon 2600) durch 720 Sinus- oder Kosinusfunktionen sich verlangsamt? Bei meinem Mikrocontrollerexperimenten mit einem ATMega128 (16MHz) kann ich das ja noch verstehen, bei einem PC aber nicht. Wo liegt da mein Denkfehler? :roll:
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

1.- :: Es "malt" schneller weil kein anderer "artfremder" Code dazwischen ausgeführt werden muss. Außerdem wird's meist übersichtlicher.
2.- :: 720° werden von deinem UrsprungsCode nie erreicht. Der kneift seinen Hintern zu bei 360°
3.- :: mal in ein Image, welches du als Inhalt eines Imagegadgets darstellst. Den Rest macht das Betriebssystem.
Zuletzt geändert von bobobo am 03.07.2007 17:39, insgesamt 1-mal geändert.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

aaaaalso...

1.
> Warum sollten sich zwischen Start und StopDrawing nur Zeichenoperationen befinden?
weil der offene DX-channel normale CPU-operationen verlangsamen kann.
d.h. wenn du dort etwas berechnest, obwohl du es auch außerhalb tun kannst,
wird dein ganzes programm langsamer.

2.
> mit dem Rucklen nach einer 720° Drehung? Wo ist die entscheidene Stelle?
keine ahnung... hab ich nicht so lange laufen lassen.... guck ich mir vielleicht später nochmal an.

3.
> Wie kann verhindet werden, dass der Fensterinhalt verfälscht werden kann?
das liegt an windows selber. der direkt aufs fenster gemalte inhalt wird nicht gepuffert.
wenn ein fenster verdeckt und wieder freigelegt wird, wird ein REFRESH ausgelöst.
das bewirkt, dass alle fensterelemente (Objekte) neu dargestellt werden.
der bemalte hintergrund ist kein objekt, du müßtest alles noch mal zeichnen.
(oder gleich in ein image zeichnen, wie von bo³ vorgeschlagen)

4.
> Wie kann es sein, dass ein PC (Athlon 2600) durch 720 Sinus- oder Kosinusfunktionen sich verlangsamt?
meinst du, wieviel zeit gebraucht wird um sinusse zu berechnen,
oder meinst du, dass das proggi langsamer läuft wenn es länger läuft?
dein rechner verlangsamt sich nicht.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
moin
Beiträge: 59
Registriert: 03.07.2007 08:38
Wohnort: Norddeutschland

Beitrag von moin »

Als Problemlösung um den Inhalt des Programmfensters zu erhalten habt ihr mir geraten ein Image zu erstellen, welches ich als Inhalt eines Imagegadgets darstellen soll.
Wie mache ich das? Wo finde ich hierfür Tutorials?
Auch meine Suche in den Foren ist ergebnislos verlaufen. (Das liegt wahrscheinlich an meiner Unkenntnis ) Ich würde mich über einen Tipp oder ein Beispielcode freuen, damit ich einen ersten Ansatz finden kann.
Danke
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

dabei hilft dir die Help zu ImageGadget, und das ganze kapitel Image... ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten