GDI+ Partikelexplosion

  • Schon mal vorab: Es ist nichts besonderes! Und ich habe nicht vor das irgendwie weiter zu verbessern. :P
    Dennoch hoffe ich es bringt irgendjemandem etwas. :D
    Am Anfang des Scripts sind ein paar Variablen für die Einstellungen. Viel Spaß.

    Spoiler anzeigen
    [autoit]

    #include <GDIP.au3>
    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    Global $iParticleCount = 40 ;Anzahl der Partikel (bitte nicht übertreiben ;))
    Global $iMaxRotationSpeed = 10 ;Maximale Rotationsgeschwindigkeit der Partikel
    Global $iMaxSpeedX = 10 ;Maximale X - Geschwindigkeit der Partikel
    Global $iMaxSpeedY = 10 ;Maximale Y - Geschwindigkeit der Partikel
    Global $iMinSize = 1 ;Minimale Größe der Partikel
    Global $iMaxSize = 3 ;Maximale Größe der Partikel
    Global $iResistance = 0.95 ;Luftwiederstand (Wert zwischen 0 und 1, 1 = keine Reibung)

    [/autoit] [autoit][/autoit] [autoit]

    $hWnd = GUICreate("Particles", 400, 400)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(400, 400, $hGraphic)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

    [/autoit] [autoit][/autoit] [autoit]

    Global $aMousePos[2]
    $aMousePos[0] = 200
    $aMousePos[1] = 200

    [/autoit] [autoit][/autoit] [autoit]

    Global $aParticles[$iParticleCount + 1][8]
    $aParticles[0][0] = $iParticleCount

    [/autoit] [autoit][/autoit] [autoit]

    $hBrush_Explosion = _GDIPlus_PathBrushCreatePie(-25, -25, 50, 50, 0, 361, 0xFFFF0F00, 0x00000000)

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $aParticles[0][0]
    $aParticles[$i][0] = 200
    $aParticles[$i][1] = 200
    $aParticles[$i][2] = Random($iMinSize, $iMaxSize, 1)
    $aParticles[$i][3] = Random(0, 359, 1)
    $aParticles[$i][4] = _GDIPlus_BrushCreateSolid("0xFF" & Hex(Random(200, 255, 1), 2) & Hex(Random(0, 100, 1), 2) & Hex(Random(0, 100, 1), 2))
    $aParticles[$i][5] = Random(-$iMaxSpeedX, $iMaxSpeedX)
    $aParticles[$i][6] = Random(-$iMaxSpeedY, $iMaxSpeedY)
    $aParticles[$i][7] = Random(-$iMaxRotationSpeed, $iMaxRotationSpeed)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "_Restart")

    [/autoit] [autoit][/autoit] [autoit]

    $iTimerExplosion = TimerInit()

    [/autoit] [autoit][/autoit] [autoit]

    While Sleep(20)
    _GDIPlus_GraphicsClear($hBuffer)
    For $i = 1 To $aParticles[0][0]
    $aParticles[$i][0] += $aParticles[$i][5]
    $aParticles[$i][1] += $aParticles[$i][6]
    $aParticles[$i][3] += $aParticles[$i][7]
    $aParticles[$i][5] *= $iResistance
    $aParticles[$i][6] *= $iResistance
    $aParticles[$i][7] *= $iResistance
    _GDIPlus_GraphicsFillRectWithAngle($hBuffer, $aParticles[$i][0], $aParticles[$i][1], $aParticles[$i][2], $aParticles[$i][2], $aParticles[$i][3], $aParticles[$i][4])
    Next
    If TimerDiff($iTimerExplosion) < 50 Then
    _GDIPlus_GraphicsTranslateTransform($hBuffer, $aMousePos[0], $aMousePos[1])
    _GDIPlus_GraphicsFillRect($hBuffer, -25, -25, 50, 50, $hBrush_Explosion)
    _GDIPlus_GraphicsResetTransform($hBuffer)
    EndIf
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, 400, 400)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BrushDispose($hBrush_Explosion)
    For $i = 1 To $aParticles[0][0]
    _GDIPlus_BrushDispose($aParticles[$i][4])
    Next
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func _Restart()
    $aMousePos = GUIGetCursorInfo($hWnd)
    For $i = 1 To $aParticles[0][0]
    $aParticles[$i][0] = $aMousePos[0]
    $aParticles[$i][1] = $aMousePos[1]
    $aParticles[$i][2] = Random($iMinSize, $iMaxSize, 1)
    $aParticles[$i][3] = Random(0, 359, 1)
    _GDIPlus_BrushSetSolidColor($aParticles[$i][4], "0xFF" & Hex(Random(200, 255, 1), 2) & Hex(Random(0, 100, 1), 2) & Hex(Random(0, 100, 1), 2))
    $aParticles[$i][5] = Random(-$iMaxSpeedX, $iMaxSpeedX)
    $aParticles[$i][6] = Random(-$iMaxSpeedY, $iMaxSpeedY)
    $aParticles[$i][7] = Random(-$iMaxRotationSpeed, $iMaxRotationSpeed)
    Next
    $iTimerExplosion = TimerInit()
    EndFunc ;==>_Restart

    [/autoit] [autoit][/autoit] [autoit]

    Func _GDIPlus_GraphicsFillRectWithAngle($hGraphics, $iX, $iY, $iWidth, $iHeight, $iAngle, $hBrush = 0)
    _GDIPlus_GraphicsTranslateTransform($hGraphics, $iX - $iWidth / 2, $iY - $iHeight / 2)
    _GDIPlus_GraphicsRotateTransform($hGraphics, $iAngle)
    _GDIPlus_GraphicsFillRect($hGraphics, -$iWidth / 2, -$iHeight / 2, $iWidth, $iHeight, $hBrush)
    _GDIPlus_GraphicsResetTransform($hGraphics)
    EndFunc ;==>_GDIPlus_GraphicsFillRectWithAngle

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_PathBrushCreatePie
    ; Beschreibung ..: Erstellt einen Farbverlauf in Form eines "Kuchens" (Teil eines Kreises) mit 2 Farben eine beginnend in der Mitte der Ellipse aus der der "Kuchen" erstellt wird und eine die auf dem Umkreis der Ellipse verläuft.
    ; Syntax.........: _GDIPlus_PathBrushCreatePie($iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle, $ARGB_Center, $ARGB_Surround, [$iWrapMode = 4])
    ; Parameter .....: $iX - X - Koordinate der linken oberen Ecke des Rechtecks aus dem die Ellipse des Kuchenstücks erstellt wird
    ; $iY - Y - Koordinate der linken oberen Ecke des Rechtecks aus dem die Ellipse des Kuchensstücks erstellt wird
    ; $iWidth - Breite der Ellipse
    ; $iHeight - Höhe der Ellipse
    ; $iStartAngle - Startwinkel des Kuchenstücks
    ; $iSweepAngle - Winkel der zum Startwinkel addiert wird und den Endwinkel bestimmt (Ein negativer Wert bedeutet eine "Rotation" nach links)
    ; $ARGB_Center - Farbe für den Mittelpunkt der Ellipse
    ; $ARGB_Surround - Farbe für den Umkreis der Ellipse
    ; $iWrapMode - Wrap mode der die Aufteilung und die Spiegelung des Brushes definiert (Standard 4):
    ; |0 - Teilen ohne spiegeln
    ; |1 - Teile werden horizontal gespiegelt wenn die Größe des Brush in X Richtung überschritten wird
    ; |2 - Teile werden vertikal gespiegelt wenn die Größe des Brush in Y Richtung überschritten wird
    ; |3 - Kombination aus 1 und 2
    ; |4 - Keine Teilung
    ; Rückgabewerte .: Success - Pointer zu einem neuen Brush Objekt
    ; Failure - -1 und setzt @error:
    ; |1 - $iSweepAngle ist = 0
    ; Bemerkungen ...: Um die Ressourcen für den Brush freizugeben, muss _GDIPlus_BrushDispose aufgerufen werden
    ; Autor .........: name22 @ http://www.autoit.de/
    ; ===============================================================================================================================
    Func _GDIPlus_PathBrushCreatePie($iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle, $ARGB_Center, $ARGB_Surround, $iWrapMode = 4)
    Local Const $Pi_Div_180 = ACos(-1) / 180

    [/autoit] [autoit][/autoit] [autoit]

    If $iStartAngle <= 0 Then $iStartAngle = 1
    If $iSweepAngle = 0 Then Return SetError(1, 0, -1)
    If $iSweepAngle < 0 Then
    $iSweepAngle *= -1
    $iStartAngle = 360 - $iSweepAngle + $iStartAngle
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aPoints_Path[$iSweepAngle + 2][2]
    $aPoints_Path[0][0] = $iSweepAngle + 1
    $iI = 1
    For $i = $iStartAngle To $iStartAngle + $iSweepAngle - 1
    $aPoints_Path[$iI][0] = $iX + $iWidth / 2 + Cos(($i - 90) * $Pi_Div_180) * $iWidth / 2
    $aPoints_Path[$iI][1] = $iY + $iHeight / 2 + Sin(($i - 90) * $Pi_Div_180) * $iHeight / 2
    $iI += 1
    Next
    $aPoints_Path[UBound($aPoints_Path) - 1][0] = $iX + $iWidth / 2
    $aPoints_Path[UBound($aPoints_Path) - 1][1] = $iY + $iHeight / 2

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aColors_Path[$iSweepAngle + 1]
    $aColors_Path[0] = $iSweepAngle
    $iI = 1
    For $i = $iStartAngle To $iStartAngle + $iSweepAngle - 1
    $aColors_Path[$iI] = $ARGB_Surround
    $iI += 1
    Next

    [/autoit] [autoit][/autoit] [autoit]

    $hBrush_Pie = _GDIPlus_PathBrushCreate($aPoints_Path, $iWrapMode)
    _GDIPlus_PathBrushSetCenterPoint($hBrush_Pie, $iX + $iWidth / 2, $iY + $iHeight / 2)
    _GDIPlus_PathBrushSetCenterColor($hBrush_Pie, $ARGB_Center)
    _GDIPlus_PathBrushSetSurroundColorsWithCount($hBrush_Pie, $aColors_Path)

    [/autoit] [autoit][/autoit] [autoit]

    Return $hBrush_Pie
    EndFunc ;==>_GDIPlus_PathBrushCreatePie

    [/autoit]


    Für das Script wird allerdings wieder die GDIP.au3 benötigt ;). (alles im Anhang)

    Edit: Habe mal eine Screensaver Version angehängt, wer ihn installieren will: Einfach kompilieren und in .scr umbenennen ;).

  • name22, du entwickelst dich ganz gut in Sachen GDI+ :!: Weiter so :thumbup:

    Btw, ich hatte auch mal so was ähnliches geschrieben - > Particle Explosions

    In meinem Kopf schwirrt immer noch die Implementierung eines Feuerwerks rum :wacko: Mal sehen, wann ich es umsetzen kann...

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat


    In meinem Kopf schwirrt immer noch die Implementierung eines Feuerwerks rum :wacko: Mal sehen, wann ich es umsetzen kann...


    Das wollte ich eigentlich auch machen... Aber für so viele Partikel ist AutoIt zu langsam. :S
    Man muss auf jeden Fall ein bisschen Tricksen. :D
    Dein Script sieht auch cool aus. :thumbup: Und ist dank fehlender Rotation um einiges schneller als meins. :(

  • Zitat

    Man könnte auch Mathe verwenden, dadurch wäre es dann noch schneller :P


    Stimmt, aber ursprünglich wollte ich damit auch Teile/Parikel eines Bildes drehen, und da helfen mir meine Mathekenntnisse recht wenig, weswegen ich wieder auf Matrizen zurückgreife :P.

  • Hi!

    Also ich find es toll was mit GDI+ alles machbar ist...gerade diese Partikel Explosion ist echt stylisch!

    Frage mich ob man das so "umbauen" könnte das dieses Programm ohne (zumindest sichtbare) GUI auskommt und damit direkt auf den Desktop zeichnet, also als "mouse - effekt"...quasi wie bei Linux Compiz?


    mfg oernzz

    noob aus erfahrung

  • Siehe meine Programme wie Interaktive Desktoptutorials, moment ich suche es mal heraus. In Autoit geht es auch, habe ich auch mal gemacht:

    Spoiler anzeigen
    [autoit]


    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_icon=x.ico
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    ;~ #NoTrayIcon
    #include <GDIPlus.au3>
    #include <Misc.au3>
    ToolTip("Anleitung:"&@CRLF&"Mit der Maus steuern, mit Einfg/Ins "&@CRLF&"malen und mir NumPad+ Bild wechseln, Esc ist Ende")
    Sleep(5000)
    ToolTip("")
    ;~ $name=getname(@AutoItExe)
    ;~ if @Compiled Then ProcessSetPriority($name,4)
    $nr=IniRead("wichtig.ini","data","Nummer",1)
    $save=1
    $pos=MouseGetPos()
    $xx=@DesktopWidth
    $yy=@DesktopHeight
    $tit=InputBox("Fenstertitel","Eingabe des Fenstertitels des zu bemalenden Fensters (Falscher/Kein Titel wird zu Desktopfenster):","Startseite - ")
    if $tit="" then $tit="zzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
    $title=WinGetTitle($tit)
    ;~ $y=_WinAPI_GetDesktopWindow()
    $y=WinGetHandle($title)
    $x=_WinAPI_GetWindowDC($y)
    _GDIPlus_Startup()
    $gra=_GDIPlus_GraphicsCreateFromHDC($x)
    $buffer=_GDIPlus_BitmapCreateFromGraphics($xx,$yy,$gra)
    $backgra=_GDIPlus_ImageGetGraphicsContext($buffer)
    $datei=IniRead("wichtig.ini","data","Bild","x.png");"mauer.png"
    $img=_GDIPlus_ImageLoadFromFile($datei)
    $brush=_GDIPlus_BrushCreateSolid(0xFF00FF00)
    $timer=TimerInit()
    while 1
    ;~ if WinActive($title)=0 Then WinWaitActive($title,"",1)
    if _IsPressed("1B") Then ExitLoop
    if _IsPressed("2D") Then
    ;~ _GDIPlus_GraphicsDrawString($gra,"Hallo",500,500,"Arial",100)
    $pos=MouseGetPos()
    $mpos=WinGetPos($title)
    ;
    ;~ _GDIPlus_GraphicsFillRect($backgra,$pos[0],$pos[1],5,5,$brush)
    ;
    _GDIPlus_GraphicsDrawImage($backgra,$img,$pos[0]-$mpos[0],$pos[1]-$mpos[1])
    EndIf
    if _IsPressed("6B") Then
    _GDIPlus_ImageDispose($img)
    $datei=FileOpenDialog("Bild auswählen...","","Alle(*.*)")
    $img=_GDIPlus_ImageLoadFromFile($datei)
    EndIf
    _GDIPlus_GraphicsDrawImageRect($gra,$buffer,0,0,$xx,$yy)
    WEnd
    _GDIPlus_ImageDispose($img)
    $fop = "x"&$nr&".bmp"
    $sCLSID = _GDIPlus_EncodersGetCLSID ("BMP")
    if $save=1 then
    $nr+=1
    _GDIPlus_ImageSaveToFileEx($buffer, $fop, $sCLSID)
    EndIf
    IniWrite("wichtig.ini","data","Bild",$datei)
    IniWrite("wichtig.ini","data","Nummer",$nr)
    _GDIPlus_BrushDispose($brush)
    _GDIPlus_GraphicsDispose($gra)
    _GDIPlus_BitmapDispose($buffer)
    _GDIPlus_GraphicsDispose($backgra)
    _GDIPlus_Shutdown()
    ;~ $name=getname(@AutoItExe)
    ;~ if @Compiled Then ProcessSetPriority($name,0)
    Exit

    [/autoit]

    Interaktive Desktoptutorials

  • Ersetz Zeile 21 mal so:

    [autoit]

    $hWnd = GUICreate("Particles", $iGUIWidth, $iGUIHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST)

    [/autoit]

    Ansonsten ist sie nicht im Vordergrund, und füllt nicht die ganze Fläche aus. ;)

    Zitat

    [Heute, 11:39] Raupi: Soll ich es dir machen?
    [Heute, 11:47] BugFix: "Soll ich es dir machen? " - also Raupi !! bitte nicht so öffentlich :rofl:

    Zitat

    [Heute, 11:51] BugFix: und ich werde es mir jetzt machen - das Mittagessen :P

    AMsg UDF v1.00.00 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 100%
    OwnStyle UDF Version 1.10.00 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 100%