1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • Turnierspiel Kombinationen

    • Mars
    • 24. Februar 2018 um 18:25

    Ich habs mal grafisch dargestellt. Da gibt es natürlich irgendwelche Muster, aber ich wüsste nicht wie man die sinnvoll in Formeln fassen kann. (Es kann auch sein, dass ich da völligen Unfug gefärbt habe^^)

    Edit: Folgende Regeln wurden berücksichtigt:

    - In jeder Runde muss jeder Spieler 1x drankommen

    - Kein Spieler darf 2x hintereinander drankommen

    Edit2: Die zahlen in der letzten Reihe ignorieren, die waren für mich zur Orientierung und ich habe sie ausversehen mit drin.

    Edit3: Es gibt wahrscheinlich unglaublich viele Kombinationsmöglichkeiten die die oben genannten Regeln erfüllen. Ggf ist eine davon durch einfache Formeln fassbar...

    lg

    M

  • Infinite Image Zoom Flight build 2018-01-10

    • Mars
    • 6. Januar 2018 um 11:09

    Eine AlphaBlend Funktion mit Skalierungsmethode haben wir vor ca. 5 Jahren doch mal irgendwo in ASM gebastelt... Ich finde sie aber nicht mehr :(

  • Random in ASM

    • Mars
    • 23. Dezember 2017 um 23:39

    oh das mit dem @f kannte ich garnicht. Dachte man muss die Labels immer gleich benennen. Wieder was gelernt. :D

  • Random in ASM

    • Mars
    • 22. Dezember 2017 um 22:23

    Das Einzige was ich ändern würde wäre ein "@f" aus dem "@@", oder ich habe Assembleit nicht verstanden.

  • GetUniqueColors

    • Mars
    • 19. Dezember 2017 um 22:49

    Von Intel gibts auch integrierte Grafikchips die anständig Leistung haben, die werden aber irgendwie nie verbaut (z.B. Iris 650 die etwa so stark wie 50-60€ Grakas ist, also ca. 2x so schnell wie die 620). Wenn das Teil allerdings nur auf einem einzigen Prozessor der von Schamanen in einem heiligen Ritual unterwasser am Nordpol um 12 Uhr Mittags geweiht wurde verbaut wird kann man damit nix reißen.

    Wenn AMD da angreift und integrierte Chips rausbringt die wie eine 1050 laufen muss Intel liefern, sonst sind sie geliefert.

  • GetUniqueColors

    • Mars
    • 19. Dezember 2017 um 21:46
    Code
    verwendetes Device  2;1;4;GPU;GeForce GTX 1060 3GB;515176674480;515176674720
    @@ Debug(539) : $MAX_WORK_GROUP_SIZE = 1024
    @@ Debug(547) : $LOCAL_WORKGROUP_SIZE = 1024
    @@ Debug(107) : Kernelruntime = 653ms
    @@ Debug(111) : Speicherkopierzeit = 11ms
    @@ Debug(112) : Anzahl Kernelaufrufe = 300
    
    verwendetes Device  1;1;2;CPU;       Intel(R) Core(TM) i5-3570K CPU @ 3.40GHz;61252735744;61115876800
    @@ Debug(539) : $MAX_WORK_GROUP_SIZE = 1024
    @@ Debug(547) : $LOCAL_WORKGROUP_SIZE = 1024
    @@ Debug(107) : Kernelruntime = 8861ms
    @@ Debug(111) : Speicherkopierzeit = 33ms
    @@ Debug(112) : Anzahl Kernelaufrufe = 300
    
    verwendetes Device  2;2;4;GPU;GeForce GT 630;939019941040;939019940240
    @@ Debug(539) : $MAX_WORK_GROUP_SIZE = 1024
    @@ Debug(547) : $LOCAL_WORKGROUP_SIZE = 1024
    @@ Debug(107) : Kernelruntime = 4482ms
    @@ Debug(111) : Speicherkopierzeit = 319ms
    @@ Debug(112) : Anzahl Kernelaufrufe = 300
    Alles anzeigen

    Wie zu erwarten. CPU < Billigstgrafikkarte < Einsteiger Gamingkarte

    Man sieht: Die Intel HD620 ist ähnlich schnell wie eine Nvidia 630GT^^

  • GetUniqueColors

    • Mars
    • 15. Dezember 2017 um 18:44

    Das hier ist der beste Thread seit langem. So viel Elan für etwas das bereits auf 5 Arten erfolgreich gelöst wurde :love:

  • GetUniqueColors

    • Mars
    • 26. November 2017 um 15:49

    Lang lebe das Bitmap Dateiformat, dort ist es wenigstens eindeutig definiert welchen Wert welche Farbe hat...

  • GetUniqueColors

    • Mars
    • 26. November 2017 um 14:25

    Ich finde es immer super sich auf ein eigentlich nebensächliches Problem mit voller Kraft draufzustürzen :D

  • GetUniqueColors

    • Mars
    • 25. November 2017 um 19:21

    Zum Überlauf:

    Sobald eine Farbe ein Mal aufgetreten ist, ist der Wert von byte[col] >0 und die Farbe wird nicht erneut gezählt, also ist es nur wichtig wie viele Threads existieren (da bei gleichzeitigem Lesen der Farbe die einzige Möglichkeit besteht, dass sie doppelt gezählt wird) und nicht wie oft die Farbe im Bild vorkommt.

    Zum parallelen Schreiben in die gleiche Variable:

    Das wusste ich nicht, da ich noch nicht viel mit MT betrieben habe. Ich dachte bei gleichzeitigem erhöhen einer Variable wird das irgendwie Prozessorintern behandelt, sodass beide Erhöhungen stattfinden. Wenn da quasi alles von 1 bis 4 herauskommen kann funktioniert mein Ansatz natürlich nicht...

    Scheint doch nicht so einfach zu sein wie zuerst gedacht :D

    Edit: Ich hatte dein Beispiel weiter oben schon gelesen, aber wohl falsch interpretiert. Da hätte mir eigentlich klar sein müssen wie das abläuft.

  • GetUniqueColors

    • Mars
    • 25. November 2017 um 18:35

    Man könnte MT nutzen und das Array statt auf den Wert 1 zu setzen um 1 erhöhen (Das Array ist ja sowieso mit byte[] besetzt). Damit springen wir zwar wieder zurück auf die Abfrage "> 0" statt "==0" das sollte in C und ASM aber keinen Unterschied machen (je 1 Takt). Die "zuviel" gezählten Farben müssen nun den "zuviel" gezählten Werten im Array entsprechen.

    Beispiel:

    4 Threads, alle 4 testen gleichzeitig einen Pixel mit der gleichen Farbe.

    -> byte[col] = 4 (nachdem alle Threads fertig sind)

    -> farbcounter = 4 (nachdem alle Threads fertig sind)

    Die Tatsächliche Anzahl Farben ist also: farbcounter MINUS (Summe der Bytestruct MINUS 1 für jedes Element >0) = 4 - 3 = 1

    Zusatzaufwand:

    - Summe der 4 farbcounter (das sind nur ein paar Takte, oder kann man hier Threadübergreifend den gleichen nehmen?)

    - Summe der (Bytestruct - 1) für jedes Element >0. (das wird etwas Zeit brauchen, bei 2^24 Elementen und angenommenen 3ghz -> ca. 15-20 Millisekunden, wobei sich dieser Vorgang ebenfalls parallelisieren lässt in z.B. 4*2^22 Elemente)

    Voraussetzungen:

    - Weniger als 256 Threads (da die Bytestruct sonst im Zweifelsfall überläuft)

    - Information was passiert, wenn 2 oder mehr Threads eine Speicherstelle um 1 erhöhen. Werden dann tatsächlich alle Erhöhungen gemacht?

    M

  • GetUniqueColors

    • Mars
    • 23. November 2017 um 15:37

    Die unterschiedlichen Farben habe ich auch bemerkt. Wenn ich das .jpg Bild als .png abspeichere sollte sich ja an den Farben nichts ändern.

  • GetUniqueColors

    • Mars
    • 23. November 2017 um 13:03

    Das liegt vermutlich daran, dass 256^4 * 1 Byte = 4 Gigabyte sind. Versuch mal das Programm mit 64Bit zu kompilieren, oder 256^4 * 1 Bit (also 1 Bit je Pixelfarbe) zu adressieren. (Für die 1 Bit Variante brauchst du dann aber ein paar Bitshifts, damit du die einsen korrekt speichern kannst, da der Zugriff nur auf 8 Bit Blöcke möglich ist. Alernativ kann man auch per OR und 10000000b das erste, mit OR 01000000b das zweite usw Bit setzen und mit AND 10000000b abfragen ob dieses Bit gesetzt wurde)

  • GDI+ Problem mit Kollision für bestimmten Bereich (Collision)

    • Mars
    • 17. November 2017 um 21:04

    Die Sache mit Local und Global ist und bleibt ein Mysterium.

    Prinzipiell wird jede Variable außerhalb von Funktionen Global deklariert, egal was man davorschreibt. Und Innerhalb von Funktionen sollte man normalerweise nicht "Global" als Statement verwenden, da hier das Programm keinen zu jedem Zeitpunkt fest definierten Pool an globalen Variablen mehr hat und dem Programmierer das Leben nur unnötig schwer macht. (z.B. könntest du eine Initialisierungsfunktion schreiben die alle globalen Deklarationen enthält und diese gleich zu Beginn aufrufen. Das wird dir aber an vielen Stellen Warnungen a la "Variable possibly not declared yet" entgegenwerfen, dem muss man dann mit forcedef usw entgegenwirken). Im Regelfall löst man soetwas gekapselt über eigene Dateien. z.B. enthält die GDI+ UDF alle notwendigen globalen Variablen und wenn man ein großes Programm schreibt erstellt man auch einzelne "Module" die jeweils gewisse Programmteile beinhalten die jeweils eigene globale Variablen besitzen.

    Potential hätten diese Scopes, wenn es noch weitere Kategorien wie "Subglobal" = "Lokal außerhalb von Funktionen" oder "Superlocal" = "Global innerhalb einer Funktion" geben würde. Soetwas wurde in AutoIt aber nicht implementiert, sodass man prinzipiell auch überall "Dim" benutzen kann, dieses ist in Fuktionen automatisch lokal und außerhalb automatisch global. Für "sauberen Code" benutzt man überlicherweise aber Local in- und Global außerhalb.

    Edit1: Und noch ein kleiner Tip zur Bewegung:

    Mach dir ein Array mit [_IsPressed, ..., ..., ..] für die 4 möglichen Richtungen. Kommt ein verschachteltes Switch oder If Else um unmögliche bzw simultane Bewegungen zu berücksichtigen. z.B. ist es unsinnig nach rechts UND links zu gehen und diagonale Bewegungen brauchen einen Faktor (Wurzel 2). Weiterhin ist es sinnvoll alle Spielerrelevanten Daten in ein Array zu packen und die Indizes via Enum zu deklarieren. Anbei ist auch ein Beispiel was ich meine (OBACHT: Ich bin mir ziemlich sicher, dass man diese unendlich verschachtelten If Abfragen irgendwie effizienter anordnen kann, aber es funktioniert schonmal :) )

    C
    ; includes ---------------------------------------------------------------------
    #include-once
    #include <GDIPlus.au3>
    #include <Misc.au3>
    
    
    
    ; declaration ------------------------------------------------------------------
    Global Const $iGuiWidth             = 1000
    Global Const $iGuiHeight            = 690
    Global Const $iGuiLeft              = 10
    Global Const $iGuiTop               = 10
    Global Const $GUI_EVENT_CLOSE       = -3
    Global $bExit                       = False
    
    Global Enum $iPlayerX, $iPlayerY, $iPlayerW, $iPlayerH, $iPlayerStep, $iPlayerUBound
    
    Global $aPlayer[$iPlayerUBound]
    
    $aPlayer[$iPlayerX] = 16
    $aPlayer[$iPlayerY] = 16
    $aPlayer[$iPlayerW] = Null
    $aPlayer[$iPlayerH] = Null
    $aPlayer[$iPlayerStep] = 4
    
    Global Const $iTreeWidth            = 128
    Global Const $iTreeHeight           = 160
    Global Const $iXPosTree             = 100
    Global Const $iYPosTree             = 100
    
    Global Const $iWidthCollisionBlock  = 40
    Global Const $iHeightCollisionBlock = 20
    Global Const $iXCollisionBlock      = 145
    Global Const $iYCollisionBlock      = 220
    
    Global Const $sPlayerImg            = 'player.png'
    Global Const $sTreeImg              = 'tree.png'
    
    
    
    ; gui --------------------------------------------------------------------------
    Global $hMainGui = GUICreate( '', $iGuiWidth, $iGuiHeight, $iGuiLeft, $iGuiTop )
    GUISetState( @SW_SHOW, $hMainGui )
    
    
    
    ; init -------------------------------------------------------------------------
    Opt( 'GUIOnEventMode', 1 )
    GUISetOnEvent( $GUI_EVENT_CLOSE, '_exitToggle' )
    OnAutoItExitRegister( '_exit' )
    
    _GDIPlus_Startup()
    
    Global $hGraphics  = _GDIPlus_GraphicsCreateFromHWND( $hMainGui )
    Global $hBitmap    = _GDIPlus_BitmapCreateFromGraphics( $iGuiWidth, $iGuiHeight, $hGraphics )
    Global $hBuffer    = _GDIPlus_ImageGetGraphicsContext( $hBitmap )
    Global $vRed       = _GDIPlus_BrushCreateSolid( 0xFFFF0000 )
    Global $hPlayerImg = _GDIPlus_ImageLoadFromFile( $sPlayerImg )
    Global $hTreeImg   = _GDIPlus_ImageLoadFromFile( $sTreeImg )
    
    $aPlayer[$iPlayerW] = _GDIPlus_ImageGetWidth($hPlayerImg)
    $aPlayer[$iPlayerH] = _GDIPlus_ImageGetHeight($hPlayerImg)
    
    ; functions --------------------------------------------------------------------
    Func _isCollisionRect( $iX, $iY, $iWidth, $iHeight, $iXBlock, $iYBlock, $iWidthBlock, $iHeightBlock )
        Return ( $iX + $iWidth > $iXBlock And $iY + $iHeight > $iYBlock And $iX < $iXBlock + $iWidthBlock And $iY < $iYBlock + $iHeightBlock )
    EndFunc
    
    Func _isCollisionPoint( $iX, $iY, $iXBlock, $iYBlock, $iWidthBlock, $iHeightBlock ) ; currently unused
        Return ( $iX > $iXBlock And $iY > $iYBlock And $iX < $iXBlock + $iWidthBlock And $iY < $iYBlock + $iHeightBlock )
    EndFunc
    
    Func _exitToggle()
        $bExit = True
    EndFunc
    
    Func _exit()
        _GDIPlus_ImageDispose($hPlayerImg)
        _GDIPlus_ImageDispose($hTreeImg)
        _GDIPlus_BrushDispose( $vRed )
        _GDIPlus_GraphicsDispose( $hBuffer )
        _GDIPlus_BitmapDispose( $hBitmap )
        _GDIPlus_GraphicsDispose( $hGraphics )
        _GDIPlus_Shutdown()
    
        GUIDelete( $hMainGui )
    EndFunc
    
    
    
    ; processing -------------------------------------------------------------------
    While Not $bExit And Sleep( 25 )
        _GDIPlus_GraphicsClear( $hBuffer )
    
        If $aPlayer[$iPlayerY] >= $iYCollisionBlock Then
            _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hTreeImg, $iXPosTree, $iYPosTree, $iTreeWidth, $iTreeHeight ) ; draw tree
            _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hPlayerImg, $aPlayer[$iPlayerX], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH] ) ; draw player
        Else
            _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hPlayerImg, $aPlayer[$iPlayerX], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH] ) ; draw player
            _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hTreeImg, $iXPosTree, $iYPosTree, $iTreeWidth, $iTreeHeight ) ; draw tree
        EndIf
    
       _GDIPlus_GraphicsFillRect( $hBuffer, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock, $vRed ) ; just for visualization purpose
    
        Local $aButton = [_IsPressed( '25' ), _IsPressed( '27' ), _IsPressed( '26' ), _IsPressed( '28' )] ; lrou
        Local $aCheck[2]
    
        If $aButton[0] And Not $aButton[1] Then ; left
            If $aButton[2] Then
                If Not $aButton[3] Then ; up and not down -> up left
                    ; check both collisions seperately
                    $aCheck[0] = _isCollisionRect( $aPlayer[$iPlayerX] - $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    $aCheck[1] = _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] - $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    If $aCheck[0] Then
                        If $aCheck[1] Then
                            ; do nothing
                        Else
                            $aPlayer[$iPlayerY] -= $aPlayer[$iPlayerStep]
                        EndIf
                    Else
                        If $aCheck[1] Then
                            $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep]
                        Else
                            $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep] / Sqrt(2)
                            $aPlayer[$iPlayerY] -= $aPlayer[$iPlayerStep] / Sqrt(2)
                        EndIf
                    EndIf
                EndIf
            Else
                If $aButton[3] Then ; not up and down -> down left
                    $aCheck[0] = _isCollisionRect( $aPlayer[$iPlayerX] - $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    $aCheck[1] = _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] + $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    If $aCheck[0] Then
                        If $aCheck[1] Then
                            ; do nothing
                        Else
                            $aPlayer[$iPlayerY] += $aPlayer[$iPlayerStep]
                        EndIf
                    Else
                        If $aCheck[1] Then
                            $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep]
                        Else
                            $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep] / Sqrt(2)
                            $aPlayer[$iPlayerY] += $aPlayer[$iPlayerStep] / Sqrt(2)
                        EndIf
                    EndIf
                Else ; -> just left
                    If Not _isCollisionRect( $aPlayer[$iPlayerX] - $aPlayer[$iPlayerStep], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                        $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep]
                    EndIf
                EndIf
            EndIf
        EndIf
    
        If $aButton[1] And Not $aButton[0] Then ; right
            If $aButton[2] Then
                If Not $aButton[3] Then ; up and not down -> up right
                    ; check both collisions seperately
                    $aCheck[0] = _isCollisionRect( $aPlayer[$iPlayerX] + $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    $aCheck[1] = _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] - $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    If $aCheck[0] Then
                        If $aCheck[1] Then
                            ; do nothing
                        Else
                            $aPlayer[$iPlayerY] -= $aPlayer[$iPlayerStep]
                        EndIf
                    Else
                        If $aCheck[1] Then
                            $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep]
                        Else
                            $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep] / Sqrt(2)
                            $aPlayer[$iPlayerY] -= $aPlayer[$iPlayerStep] / Sqrt(2)
                        EndIf
                    EndIf
                EndIf
            Else
                If $aButton[3] Then ; not up and down -> down right
                    $aCheck[0] = _isCollisionRect( $aPlayer[$iPlayerX] + $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    $aCheck[1] = _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] + $aPlayer[$iPlayerStep] / Sqrt(2), $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock )
                    If $aCheck[0] Then
                        If $aCheck[1] Then
                            ; do nothing
                        Else
                            $aPlayer[$iPlayerY] += $aPlayer[$iPlayerStep]
                        EndIf
                    Else
                        If $aCheck[1] Then
                            $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep]
                        Else
                            $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep] / Sqrt(2)
                            $aPlayer[$iPlayerY] += $aPlayer[$iPlayerStep] / Sqrt(2)
                        EndIf
                    EndIf
                Else ; -> just right
                    If Not _isCollisionRect( $aPlayer[$iPlayerX] + $aPlayer[$iPlayerStep], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                        $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep]
                    EndIf
                EndIf
            EndIf
        EndIf
    
        ; Ab hier sind alle folgenden Richtungen abgehandelt:
        ; links, rechts
        ; links oben, links unten
        ; rechts oben, rechts unten
        ; Es fehlen also nur noch oben und unten!
    
        If $aButton[2] And Not $aButton[3] And Not $aButton[0] And Not $aButton[1] Or ($aButton[0] And $aButton[1] And $aButton[2]) Then ; oben
            If Not _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] - $aPlayer[$iPlayerStep], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                $aPlayer[$iPlayerY] -= $aPlayer[$iPlayerStep]
            EndIf
        EndIf
    
        If $aButton[3] And Not $aButton[2] And Not $aButton[0] And Not $aButton[1] Or ($aButton[0] And $aButton[1] And $aButton[3]) Then ; unten
            If Not _isCollisionRect( $aPlayer[$iPlayerX], $aPlayer[$iPlayerY] + $aPlayer[$iPlayerStep], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                $aPlayer[$iPlayerY] += $aPlayer[$iPlayerStep]
            EndIf
        EndIf
    
        ; Fast fertig. Da es oben nicht eingepflegt wurde fehlt noch folgendes:
        ; links wenn 3 Tasten gedrückt sind (also oben + unten + links)
        ; rechts wenn 3 Tasten gedrückt sind
    
        If $aButton[0] And $aButton[2] And $aButton[3] Then ; links
            If Not _isCollisionRect( $aPlayer[$iPlayerX] - $aPlayer[$iPlayerStep], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                $aPlayer[$iPlayerX] -= $aPlayer[$iPlayerStep]
            EndIf
        EndIf
    
        If $aButton[1] And $aButton[2] And $aButton[3] Then ; rechts
            If Not _isCollisionRect( $aPlayer[$iPlayerX] + $aPlayer[$iPlayerStep], $aPlayer[$iPlayerY], $aPlayer[$iPlayerW], $aPlayer[$iPlayerH], $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
                $aPlayer[$iPlayerX] += $aPlayer[$iPlayerStep]
            EndIf
        EndIf
    
        _GDIPlus_GraphicsDrawImageRect( $hGraphics, $hBitmap, 0, 0, $iGuiWidth, $iGuiHeight )
    WEnd
    Alles anzeigen
  • filecopy es lebe der bug

    • Mars
    • 17. November 2017 um 16:03

    Es Lebe das Memoryleak. https://www.autoitscript.com/trac/autoit/ticket/2915

    Intessiert auch niemanden, obwohl soetwas ein absolutes nogo für JEDE Programmiersprache ist.

    Ist zwar leicht OT, aber ich wollte erwähnen, dass es auch kritische Bugs gibt die keinen jucken.

  • GDI+ Problem mit Kollision für bestimmten Bereich (Collision)

    • Mars
    • 17. November 2017 um 15:36

    Hier mal eine zusammenfassende Stellungnahme zu dem Skript: (hoffentlich konstruktive Kritik)

    - Memoryleak bei Zeile 84 und 85. Die Grafiken müssen beim "Start" einmal geladen und beim "Ende" wieder freigegeben werden. Sie bei jedem Zeichnen neu von der Platte zu lesen und nicht wieder freizugeben verursacht ein Speicherleck.

    - Das "exit" am Ende der SetOnEvent Funktion ist "unschön". Besser ist es einen Main Loop zu haben der z.B. via "While Not $bExit" läuft. Via Event lässt sich dann das $bExit auf True umstellen, anschließend durchläuft das Programm die aktuell laufende Schleife aber noch vollständig und kann anschließend in der niedrigsten Ebene (also nicht in einer Funktion, einem Event oder sonstigem) terminieren. Zum freigeben der Ressourcen kann man entweder eine Freigabefunktion nach dem Main Loop aufrufen, oder via OnAutoItExitRegister automatisch ausführen lassen sobald das Programm beendet wird. Hier aber auch unbedingt KEIN "exit" reinschreiben.

    - Kollisionsdetektion kann über mehrere Verfahren die sehr einfach zu bewerkstelligen sind erledigt werden. Erstens wäre der Klassiker RectRectCollision oder PointRectCollision (leider wurden die schon millionenfach implementiert und haben jedes Mal einen anderen Namen), oder man benutzt eine 2te Bitmap und weist den Hindernissen explizite Farbwerte zu, diese kann man mit GDIPlusBitmapGetPixel abfragen. Mit Path Funktionen kenne ich mich leider nicht aus, da muss jemand anderes helfen...

    - Unterhalb deiner Linie wo "declaration ------------" steht wird überall Local als Keyword genutzt. Verwende an dieser Stelle lieber Global. Genauso wie bei den GDI+ Objekten die später auch alle mit Local deklariert werden. AutoIt ist zwar gegen solche "Fehler" abgesichert und interpretiert das "Local" dennoch als "Global" (da man in der niedrigsten Ebene ist), das gehört aber zum guten Stil.

    Code
    Func _Kollision_Viereck_Viereck($x1, $y1, $b1, $h1, $x2, $y2, $b2, $h2) ;Selbsterklärend
    Return ($x1 + $b1 > $x2 And $y1 + $h1 > $y2 And $x1 < $x2 + $b2 And $y1 < $y2 + $h2)
    EndFunc   ;==>_Kollision_Viereck_Viereck
    
    Func _Kollision_Viereck_Punkt($x1, $y1, $x2, $y2, $b2, $h2) ;Selbsterklärend
    Return ($x1 > $x2 And $y1 > $y2 And $x1 < $x2 + $b2 And $y1 < $y2 + $h2)
    EndFunc   ;==>_Kollision_Viereck_Punkt

    Edit1: Allgemein gibt es 2 Möglichkeiten zu verhindern, dass der Spieler über ein verbotenes Gebiet geht.

    - Die Erste ist das Prognostizieren, dass die gewünschte Bewegung nicht geht und diese verhindern bevor sie ausgeführt wird. (Man berechnet also vorher, dass eine Bewegung nicht möglich ist und führt diese dann nicht aus)

    - Als Zweites existiert die Möglichkeit jede Bewegung per sé auszuführen, egal ob sie möglich ist oder nicht. Anschließend wird festgestellt, dass sich der Spieler in einem Verbotenen Gebiet befindet und "sanft" zurückgedrängt bis er wieder wo steht wo er auch stehen darf.

    lg

    M

  • GetUniqueColors

    • Mars
    • 17. November 2017 um 09:37

    Hab eine primitive ASM Version geschrieben. (primitiv im Sinne von "kein SSE und sonstige Extras, sondern wirklich nur extrem einfach"). Da hierbei AutoIt für das calloc zuständig ist (das geht bestimmt auch in asm, aber ich habe das noch nie gemacht und hatte keine Zeit zu googeln :D) gibt es einen größeren Overhead. Daraus folgt, dass die ASM Variante für "kleine" Bilder langsamer als die DLL ist und für große Bilder schneller.

    Code
    #include <GDIPlus.au3>
    ;~ #include "C:\Users\...\OneDrive\AutoIt\UDF\EasyASM\EasyASM.au3"
    
    ;~ _ASM_Startup()
    _GDIPlus_Startup()
    
    Global $iTimer, $iCount
    Global $sImagefile = @ScriptDir & '\testbig.jpg'
    Global $hImage = _GDIPlus_BitmapCreateFromFile($sImagefile)
    Global $hDLL = DllOpen('cuc.dll')
    ;~ Global $iMyASM = _ASM_AddOP(_MyASM())
    
    ; Irgendwie braucht der "erste" Aufruf beider Funktionen weeeesentlich länger als alle weiteren Aufrufe.
    $iCount = _GetUniqueColors($hImage)
    $iCount = _GetUniqueColorsASM($hImage)
    
    
    ConsoleWrite('##################################' & @CRLF)
    $iTimer = TimerInit()
    $iCount = _GetUniqueColors($hImage)
    ConsoleWrite('GesamtZeit: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
    ConsoleWrite('Anzahl der Farben: ' & $iCount & @CR)
    ConsoleWrite('##################################' & @CRLF)
    $iTimer = TimerInit()
    $iCount = _GetUniqueColorsASM($hImage)
    ConsoleWrite('GesamtZeit: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
    ConsoleWrite('Anzahl der Farben: ' & $iCount & @CR)
    ConsoleWrite('##################################' & @CRLF)
    
    _GDIPlus_BitmapDispose($hImage)
    _GDIPlus_Shutdown()
    ;~ _ASM_Shutdown()
    
    
    Func _GetUniqueColors(ByRef $hImage)
        Local $aSize = _GDIPlus_ImageGetDimension($hImage) ; Nur 1 Dllcall statt 2
        Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $aSize[0], $aSize[1], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        Local $tPixel = DllStructCreate('uint[' & $aSize[0] * $aSize[1] & '];', DllStructGetData($tBitmapData, 'Scan0'))
    
        ;int DLL_EXPORT count_colors(unsigned int* pixel, int len)
        $aret = DllCall($hDll, "int:cdecl", "CountUniqueColors", "ptr", DllStructGetPtr($tPixel), "int", $aSize[0] * $aSize[1])
    
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        If Not @error Then Return $aret[0]
    EndFunc
    
    Func _GetUniqueColorsASM(ByRef $hImage)
        Local $aSize = _GDIPlus_ImageGetDimension($hImage) ; Nur 1 Dllcall statt 2
        Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $aSize[0], $aSize[1], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        Local $tPixel = DllStructCreate('uint[' & $aSize[0] * $aSize[1] & '];', DllStructGetData($tBitmapData, 'Scan0'))
    
        ; Zusätzliche Vorbereitungen... hier geht auch einiges an Zeit flöten, da Structs in AutoIt langsamer erzeugt werden als z.B. in C.
        Local $vColor = DllStructCreate('byte[' & 0xFFFFFF + 1 & ']')
        Local $vData = DllStructCreate('ptr;ptr;uint') ;bitmapdaten;acolor;pixelzahl
        DllStructSetData($vData, 1, DllStructGetPtr($tPixel))
        DllStructSetData($vData, 2, DllStructGetPtr($vColor))
        DllStructSetData($vData, 3, $aSize[0] * $aSize[1])
    
    ;~     _ASM_Call($iMyASM, DllStructGetPtr($vData))
    ;~     Local $aret = [DllStructGetData($vData, 3)]
    ;~     ConsoleWrite(_ASM_GetBytecode($iMyASM) & @CRLF)
    
        Local $vByteCode = DllStructCreate("byte[92]")
        DllStructSetData($vByteCode, 1, "0x8B4424048B388B70048B4808BA000000008B1F81E3FFFFFF00803C1E00750542C6041E0183C7044977E7895008C3")
        DllCall('user32.dll', 'ptr', 'CallWindowProcW', 'ptr', DllStructGetPtr($vByteCode), 'ptr', DllStructGetPtr($vData), 'int', 0, 'int', 0, 'int', 0)
        Local $aret = [DllStructGetData($vData, 3)]
    
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        If Not @error Then Return $aret[0]
    EndFunc
    
    #cs
    Func _MyASM()
        _('use32')
    
        _('mov eax, [esp+4]') ; Ptr auf die Datenstruct
    
        _('mov edi, [eax]') ; Ptr der Bitmapdaten
        _('mov esi, [eax+4]') ; Ptr der aColor Struct
        _('mov ecx, [eax+8]') ; Anzahl Pixel
    
        _('mov edx, 0') ; Wer weiß wer weiß
    
        _('_Label_01:') ; Main Loop
    
        _('mov ebx, [edi]') ; pixelfarbe
        _('and ebx, 0xffffff') ; Pixelfarbe & ffffff
    
        _('cmp byte[esi + ebx], 0') ; null ?
        _('jnz _Label_02') ; nein -> weiter
        _('inc edx') ; ja -> +1
        _('mov byte[esi + ebx], 1') ; ja -> setze 1
        _('_Label_02:') ; endif
    
        _('add edi, 4') ; nächster px
        _('dec ecx') ; schleife
        _('ja _Label_01') ; schleife
    
        _('mov dword[eax+8], edx') ; returnwert in vData3 (weil es ein uint ist.....)
    
        _('ret')
    EndFunc
    #ce
    Alles anzeigen

    Edit: Zumindest bei mir lief es für 4K Bilder ca. 30-50% schneller. Aber keine Garantie dass der PC nicht explodiert wenn der Code ausgeführt wird :D

  • GetUniqueColors

    • Mars
    • 17. November 2017 um 07:08

    "calloc() zero-initializes the buffer, while malloc() leaves the memory uninitialized."

  • GetUniqueColors

    • Mars
    • 17. November 2017 um 04:16

    ich hab leider keinen C Compiler hier. Hast du ausprobiert, ob es schneller ist im loop (Zeile 9, 10, 11) VOR die Zuweisung der Zahl 1 eine Abfrage mit If colors[pixel[i] & 0xffffff] == 0 Then colorSum++ einzubauen? Dann muss nicht das komplette Array (was ja von 0 bis 0xffffff geht) durchlaufen werden, sondern nur die Parts die relevant sind. Ich schätze das hilft auch in C und ASM ein wenig.

    Edit1: (je nachdem wie der Compiler intern arbeitet muss man ggf das mehrfache Auftreten von pixel[i] & 0xffffff in eine Variable packen, sonst lässt er das mehrfach ausführen, was mehr Ram-Zugriffe bedeutet und damit langsamer sein sollte)

    Edit2: (wieder je nachdem wie es läuft ist colorsum += (1-colors[pixel[i] & 0xffffff]) schneller als das If)

  • GetUniqueColors

    • Mars
    • 15. November 2017 um 20:00

    Nur als kleiner Tip: Die Arrayvariante lässt sich noch etwas aufbohren, wenn man die Farben nicht "zählt" sondern einfach nur eine 0 oder eine 1 hinterlegt, je nachdem ob die Farbe schonmal aufgetaucht ist. (Dann verbraucht man auch keine wertvollen Takte um abzuspeichern, dass die Farbe FF4265 genau 5531x aufgetaucht ist).

    Code
    Func _GetUniqueColors1(ByRef $hImage) ; inspiriert von der Array-Variante von alpines
        Local $iColorCounter = 0, $aColor[0xFFFFFF + 1]
        Local $iW, $iH, $tBitmapData, $pScan0, $tPixel, $iOffset, $iColor
        $iW = _GDIPlus_ImageGetWidth($hImage)
        $iH = _GDIPlus_ImageGetHeight($hImage)
        $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        $pScan0 = $tBitmapData.Scan0
        $tPixel = DllStructCreate('uint[' & $iW * $iH & '];', $pScan0)
        ConsoleWrite(StringFormat('%d x %d = %d px\n', $iW, $iH, $iW * $iH))
        For $iIndex = 1 To $iW * $iH
            $iColor = DllStructGetData($tPixel, 1, $iIndex) - 0xFF000000
            If Not $aColor[$iColor] Then
                $aColor[$iColor] = 1
                $iColorCounter += 1
            EndIf
        Next
        Local $aData = _WinAPI_GetProcessMemoryInfo()
        ConsoleWrite('MemoryInfo: ' & $aData[2] & ' bytes' & @CRLF)
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        $tPixel = 0
        Return $iColorCounter
    EndFunc   ;==>_GetUniqueColors1
    Alles anzeigen

    ------------------------------------------------------------------------------------------

    Wenn man jetzt von Arrays auf Structs umsteigt kann man (theoretisch) jedes einzelne Bit als Indikator benutzen ob die Farbe bereits vorhanden war (Geringer Speicherverbrauch, langsam) oder man nimmt die Variante, die dem Prozessor am besten schmeckt und nutzt 8Bit (bei Ungerader Pixelzahl muss hier am Ende ein 32er Register vollgestückelt werden glaube ich) oder 32Bit (supereinfach, superschnell, Speicherintensiv. Das Ganze ist auch in ASM ziemlich einfach, ich kann es aber leider gerade nicht machen... sollte für gewisse Leute hier eine Sache von 5 Minuten sein.

    Code
    Func _GetUniqueColors4(ByRef $hImage)
        Local $iW, $iH, $tBitmapData, $pScan0, $tPixel, $iOffset, $iColor, $vColor, $iColorCounter = 0
        $iW = _GDIPlus_ImageGetWidth($hImage)
        $iH = _GDIPlus_ImageGetHeight($hImage)
        $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
        $pScan0 = DllStructGetData($tBitmapData, 'Scan0')
        $tPixel = DllStructCreate('uint[' & $iW * $iH & '];', $pScan0)
        $vColor = DllStructCreate('byte[' & 0xFFFFFF + 1 & ']') ; Das Plus 1, da der 0te Index die 1 ist.
        ConsoleWrite('$iW * $iH = ' & $iW * $iH & ' px' & @CRLF)
        For $iY = 0 To $iH - 1
            $iOffset = $iY * $iW + 1
            For $iX = 0 To $iW - 1
                $iColor = DllStructGetData($tPixel, 1, $iOffset + $iX) - 0xFF000000
                If Not DllStructGetData($vColor, 1, $iColor) Then $iColorCounter += DllStructSetData($vColor, 1, 1, $iColor)
            Next
        Next
        Local $aData = _WinAPI_GetProcessMemoryInfo()
        ConsoleWrite('MemoryInfo: ' & $aData[2] & ' bytes' & @CRLF)
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        $tPixel = 0
        Return $iColorCounter
    EndFunc
    Alles anzeigen

    lg

    M

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™