GDI+ Spielerei

  • Hi Community


    Das hier präsentierte Skript ist lediglich eine Spielerei von mir und NOCH NICHT FERTIG :) !

    Weitere Features (und zum Schluss natürlich Zeilen Optimierung) kommen noch dazu.


    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    UPDATE 31.10.18 (Version 1.2):

    - Die Gui ist nun im OnEvent Modus

    - Die Variablendeklaration wurde überarbeitet, evtl. noch verbesserungswürdig (Vorschläge erwünscht)

    - Das "sizinig" ist etwas grösser, aber noch nicht fertig optimiert

    - Der Parameter "bias" sorgt für eine definierte "Verschiebung" der Kurve, was coole "Surfaces" erzeugen kann

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    UPDATE 05.11.18 (Version 1.3):

    - Button "RAND" hinzugefügt:

    Initialisiert neue "random" Settings"

    - Checkbox "SBS" (StepByStep) hinzugefügt:

    Wenn nicht angewählt, berechnet es 50 Schritte ($calc_forward) im Voraus und bildet diese danach ab.

    Jedoch fehlt immer der Zwischenschritt, welcher nicht gezeichnet wird (wirkt Skizzenhaft, wird jedoch noch behoben)

    - Slider "Fading" hinzugefügt (momentan mithilfe von "graphicsclear" um eine Vorstellung zu bekommen, wird evtl. noch optimiert)

    - Slider "Speed" hinzugefügt

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    AUSBLICK:

    - Farbenhandling

    - Beschriftungen im Skript (Nachvollziehbar) nachtragen

    - Speichern von Bildern, Settings

    - Laden von Settings

    - Zeilenoptimierung

    - Variablennamen Optimierung

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    Falls das Skript bei jemandem Probleme macht, getestet habe ich es bisher nur auf meinem Laptop:

    - HP-Omen

    - Intel(R) Core(TM) i5-7300HQ

    CPU @ 2.50GHz (4 Kerne)

    - 8.00 GB RAM

    - 64-Bit,

    - 1920x1080



    V 1.3:



    Vielen Dank im Voraus für Eure Hilfe.:)

  • AutoIt version: 3.0.103

    Das ist garantiert nicht deine AutoIt-Version, eher deine SciTE-Version.


    Du solltest mit einem Buffer arbeiten wenn du Legs anhast, ansonsten clearst du ständig das Graphics-Objekt und deswegen flackert das ganze.

    Wenn du in einen Buffer zeichnest und am Ende das Buffer immer auf die Graphics zeichnest (ohne zu clearen) flackert es nicht.


    Dass das Script schneller läuft liegt vermutlich daran, dass Mausevents an das Fenster gesendet werden und der Windows-Scheduler dem Programm mehr Zeit zuweist.

    Du kannst das beheben indem du nicht so schnell wie möglich, sondern zeitlich basiert zeichnest.

  • Ich habe versucht einen zweiten Buffer, sowie ein zweites Bitmap zu erstellen.

    Die funktion _Draw() habe ich nach besstem Wissen und gewissen angepasst wie folgt:


    Ich denke ich habe es nicht richtig verstanden, denn es flackert immernoch :/

  • Das ist nicht so einfach anzupassen, wenn du den Zeiger drauf haben möchtest.

    Ohne Zeiger musst du einfach nur in das Buffer zeichnen und am Ende die Bitmap auf die Graphics drauf.


    Jetzt hast du das Problem, dass du ja das, was du bisher gezeichnet hast, speichern willst und den Zeiger löschen möchtest.

    Du könntest dazu noch einen Buffer nehmen den du nur für den Zeiger reservierst, diesen clearst du dann jedes Mal beim neu zeichnen.


    So hast du dann auf der hGraphics erst das was du bisher gezeichnet hast und darüber den Zeiger.

    Den Zeigerbuffer clearst du vor jedem Zeichnen, den HistoryBuffer musst du nicht clearen (du zeichnest ja von dort aus immer weiter).

  • Ok, ich hab mich mal kurz in dein Skript eingearbeitet und habs implementiert.

    Ich hätte das ganze anders strukturiert aber ich wollte das jetzt nicht komplett über den Haufen werfen, da es einfach zu viel Zeit kosten würde also hab ich das so mal beibehalten.


    Idee:


    Wir haben ein Buffer für das GraphicControl, ein Buffer für die History und einen für die Legs.

    Wir zeichnen die History ins Historybuffer, die Legs ins Legsbuffer und anschließend zeichnen wir erst das Historybuffer und dann das Legsbuffer in das GraphicsControl Buffer.


    Da wir die Bitmap nicht komplett transparent färben können (keine Ahnung ob das möglich ist) überschreiben wir beim nächsten Durchlauf die Legs mit dem Historybuffer, so wirkt es als ob wir

    die alten Legs gelöscht hätten und zeichnen die neuen oben drauf.


    Ist zwar ein bisschen doppelt gemoppelt aber es funkioniert, optimieren kannst du es ja noch selber.

    Immerhin flackerts nicht mehr :)

  • Zitat

    Ok, ich hab mich mal kurz in dein Skript eingearbeitet und habs implementiert.

    Ich hätte das ganze anders strukturiert aber ich wollte das jetzt nicht komplett über den Haufen werfen, da es einfach zu viel Zeit kosten würde also hab ich das so mal beibehalten.

    Ich bin begeistert, vielen dank für diese super Hilfe ^^

    Für mich jungen "Hobby" Programmierer ist das bereits sehr viel Wert!


    Ich werde dann Updates mit weiteren Features Posten und bin auch dann gespannt und offen für Verbesserungsvorschläge 8)

  • Hi,

    schönes Projekt!

    - Warum läuft das Programm schneller, wenn die Maus bewegt wird?

    Weil du den sog. "Message"-Modus nutzt, statt den "Event"-Modus.

    In der Funktion GuiGetMsg() ist eine Abfrage implementiert, welche dafür sorgt, dass bei "länger" ausbleibenden Eingaben (Maus, Tastatur, usw.) die Prozessorlast minimiert wird. Das hat bei GUI´s Vorteile, die auf User-Interaktionen warten, also Buttonklicks usw., aber eher wenig Berechnungen durchführen.

    Um nur auf Events zu reagieren, also die volle Prozessorleistung an das Programm zu übergeben, nutzt man den GUIOnEventMode


    Ich werde dann Updates mit weiteren Features Posten und bin auch dann gespannt und offen für Verbesserungsvorschläge

    :klatschen:

    Na, dann fang ich mal an......

    - Farbe gehört ins Spiel! Am Besten Farbverläufe.....

    - Interaktionen kommen immer gut, indem bspw. der User mit der Maus ins Bild klickert und dort dann eine Reaktion auslöst...

    - Die Funktion ist schon recht schnell "fertig". Mir würde es gefallen, dass man noch einen Winkel festlegen könnte, um den das fertige Muster dann mehrfach gedreht werden würde. Letztendlich könnte man damit wunderschöne Mandalas kreieren.

  • Zitat

    - Die Funktion ist schon recht schnell "fertig". Mir würde es gefallen, dass man noch einen Winkel festlegen könnte, um den das fertige Muster dann mehrfach gedreht werden würde. Letztendlich könnte man damit wunderschöne Mandalas kreieren.

    Das war auch mein Gedanke :) habe bereits versucht was umzusetzen. Was dabei herauskam ist im Anhang zu finden.


    Zitat
    - Interaktionen kommen immer gut, indem bspw. der User mit der Maus ins Bild klickert und dort dann eine Reaktion auslöst...

    Finde ich gut, evtl. könnte ich das in einen "Interaktionsmodus" einlagern, welcher dann beliebig ein-, bzw. ausgeschaltet werden kann.

  • - Warum läuft das Programm schneller, wenn die Maus bewegt wird? Hat das etwas mit Multiprocessing, bzw. Multithreading zu tun? Wenn ja, wie kann ich es beheben?

    Du handelst deine GUI im MessageLoop Modus (GuiGetMsg), wenn du auf den OnEvent Modus wechsels ist dies behoben. Die benötigten Funktionen sind:


  • Ah, das erinnert mich an die gute alte Zeit, in den 90ern, als ich noch Lasereffektgeräte baute.

    Damals programmierte ich dann auch Simulationen solcher Geräte, noch auf den Atari, in GFA-Basic (schwelg in Nostalgie) ...


    Erstaunlicherweise läuft Deine Routine auf dem PC nicht schneller, als meine, damals auf dem Atari.

    Spontan würde ich vermuten, dass einer der Gründe dafür der ist, dass Deine vorausberechneten Werte $x[$i] und $y[$i] Vom Typ her Fließkommazahlen sind. Möglicherweise bremst das die eigentliche Zeichenroutine unnötig aus.

    Probiere doch mal, dort in den vorausberechneten Arrays ganzzahlige Werte zu erzwingen.


    Weiterer Verbesserungsvorschlag:

    Mache den Hintergrund schwarz und zeichne die Figur in leuchtend grellem Rot. Dann kommt das einem Lasereffektgerät schon viel näher,

    Und dann kann man noch eine nette Sache machen:

    Vorausgesetzt, Du kriegst die Zeichnerei noch deutlich beschleunigt, müssen die von der Zeichenfunktion gesetzten Pixel "ausfaden", so ca. eine knappe halbe Sekunde nachdem sie gesetzt wurden.


    Für das Ausfaden müsste in einer Schleife jeder einzelne Pixel bei jedem Durchlauf ein kleines Stückchen dunkler gestellt werden, bis am Ende Schwarz erreicht ist, wie bei der von mir vorgeschlagenen Hintergrundfarbe.


    Ein echtes Lasereffektgerät brutzelt ja auch nicht seine Spur fest in die damit angestrahlte Wand. Sondern dort wird nur ein Laserpunkt bewegt und im Auge stellt sich so ein verblassender Nachleuchteffekt ein, der es überhaupt erst ermöglicht, solche schönen Muster wahrzunehmen.


    Wenn das mit dem Ausfaden umgesetzt ist, dann wird es denkbar, die Figur zur Laufzeit zu beeinflussen, indem man mit der Maus Schieber betätigt.


    Und noch ein Vorschlag:

    Was mir damals bei den echten Geräten irgendwie den "Kick" gab, das war dieses Surren der Motoren.

    Meine Geräte arbeiteten mit vier Motoren und das was man sah, war unmittelbar das, was man auch hörte. Abgefahren!

    Besonders effektvoll war der Effekt dadurch, dass die Motoren trotz aller Stabilisierung nie zu 100% eine eingestellte Geschwindigkeit hielten. Da war immer etwas "Leben" im Spiel, in Form von "Schwebungen", was sich natürlich unmittelbar auf die Muster auswirkte und den dabei produzierten Sound.

    Es wäre daher eine Überlegung wert, noch per Zufallsgenerator etwas wohldosierte Ungenauigkeit mit ins Spiel zu bringen und weiterhin diesen ganzen Sinuskram in Töne zu verwandeln und an die Soundkarte zu schicken.

  • Für das Ausfaden müsste in einer Schleife jeder einzelne Pixel bei jedem Durchlauf ein kleines Stückchen dunkler gestellt werden, bis am Ende Schwarz erreicht ist, wie bei der von mir vorgeschlagenen Hintergrundfarbe.

    Dafür bietet sich _GDIPlus_ImageAttributesSetColorMatrix() an, aber allein diese Funktion dauert aber (auf meinem Laptop) 32ms.....für die Aufgabe daher völlig ungeeignet, wie übrigens (mit Hinsicht auf hohe Geschwindigkeit) das ganze GDIPlus(mit PLUS!!!)-Gedöns!


    Will man wirklich schnelle Grafik, bleibt einem (wie gehabt) GDI(OHNE Plus!), oder eine der anderen Bibliotheken.

    Ggf. kommt man mit dem letzten Parameter von BitBlt() weiter, da hänge ich mich mal rein, ansonsten schreibt man da schnell was in ASM :P

  • Code
    1. #Region Functions
    2. Func _LegVar($q = 5)
    3. Global $quantity = $q
    4. Global $length[$quantity+1]
    5. Global $x[$quantity+1], $y[$quantity+1], $alpha[$quantity+1], $step[$quantity+1]
    6. EndFunc

    NIEMALS Globale Variablen innerhalb von Funktionen deklarieren, da rastet dir Au3Check mit Warnungen nur aus, es ist auch kein sicherer Stil.

    Erstelle deine Globals ganz oben und in der Funktion weißt du den Wert dann zu.

  • Zitat

    NIEMALS Globale Variablen innerhalb von Funktionen deklarieren, da rastet dir Au3Check mit Warnungen nur aus, es ist auch kein sicherer Stil.

    Erstelle deine Globals ganz oben und in der Funktion weißt du den Wert dann zu.

    Ist aufgenommen und wird bei der nächsten Version angepasst sein. Danke für den Input :)