Glücksrad! via GDI+?

  • Post aktualisiert! Bitte in diesen Beitrag zur Aktualisierung schauen.

    Hey folks,

    ich beschäftige mich seit langem mal wieder mit AutoIt. Als "Aufwärmübung" wollte ich'n Glücksrad basteln.
    Sprich ein Kreis der sich auf Klick drehen lässt, wobei dieser in Bereiche unterteilt werden kann.

    Kurz um:
    - drehender Kreis
    - Kreis in X Bereiche unterteilbar
    - Fixpunkt um zu ermitteln in welchem Bereich der Fixpunkt nach dem Drehen ist

    Ich dachte dabei natürlich an GDI+ und unter anderem an _GDIPlus_GraphicsDrawArc, aber damit lassen sich innerhalb des Kreisen ja keine Bereiche festlegen.

    Da die Suche nichts hilfreiches ergeben hat die Frage: In welche Richtig sollte ich mich orientieren bzw. welche Funktionen wären hilfreich?
    Speziell um Bereiche zu definieren (die an den Abschnitt gebunden sind) usw.

    Cheers,
    Matricus

    5 Mal editiert, zuletzt von Matricus (25. November 2013 um 08:10)

  • du kannst auch nur die Farben rotieren lassen. Ich hab ein beispiel angehängt, aber erst schauen wenn du selber eine Lösung hast!! sonst hat es ja keinen zweck ;)

    Spoiler anzeigen
    [autoit]

    #include <Gdip.au3>
    #include <GUIConstantsEx.au3>
    Global $rotate=0 ,$segmente=20 ,$farbe[$segmente] ,$zaehler=0
    $form1=GUICreate("" ,500 ,500)
    GUISetState(@SW_SHOW)
    _GDIPlus_Startup()
    $hgraphics=_GDIPlus_GraphicsCreateFromHWND($form1);Grafik Objekt von dem Fenster erstellen
    AdlibRegister("_rotate" ,500);alle 500 ms Funktion _rotate() aufrufen
    For $i0=0 to $segmente-1
    $farbe[$i0]=_GDIPlus_BrushCreateSolid(Random(0xFF000000 ,0xFFFFFFFF));Farben für die einzelnen segmente erzeugen
    Next

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

    While 1
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    _Exit()
    Case $GUI_EVENT_PRIMARYDOWN
    $rotate=BitXOR($rotate ,1);toggle $rotate bei jedem maus klick
    EndSwitch
    WEnd

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

    Func _rotate()
    If $rotate Then
    $angle=0;immer startposition auf 0 setzen
    $zaehler+=1;zähler und somit startfarbe um eins erhöhen gleichzeitig anzeige welches segment oben steht.
    For $i1=0 to $segmente-1
    $zaehler+=1
    _GDIPlus_GraphicsfillPie($hgraphics ,100 ,100 ,300 ,300 ,$angle ,360/$segmente ,$farbe[Mod($zaehler ,$segmente)]);einzelne "Kuchenstücke" zeichenen
    $angle+=360/$segmente;anfangswinkel um segmentwinkel inkrementieren
    Next
    EndIf
    EndFunc

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

    Func _exit();Alle erzeugten elemente Freigeben und beenden
    For $1=0 to $segmente-1
    _GDIPlus_BrushDispose($farbe[$1])
    Next
    _GDIPlus_GraphicsDispose($hgraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]
  • Danke euch beiden soweit! Wie immer schnelle und gute Hilfe. :)

    Ich mach recht wenig mit Grafik, aber zu Glücksrad würden mir als erstes
    _GDIPlus_GraphicsDrawPie und
    _GDIPlus_MatrixRotate
    einfallen. Lies dich da mal ein und probiere die Bsp.

    Mit _GraphicsDrawPie komm ich klar und kann die Abschnitt auch dynamisch berechnen lassen - ist ja nicht sonderlich schwer - aber mit _MatrixRotate komm' ich nicht zurecht.
    Ick schau mal ob ich es nicht noch hinbekomme, aber hab' dafür nach der Arbeit und am Abend kaum noch einen Nerv für. ;)

    Zitat von bollen

    du kannst auch nur die Farben rotieren lassen. Ich hab ein beispiel angehängt, aber erst schauen wenn du selber eine Lösung hast!! sonst hat es ja keinen zweck ;)


    Ich hab reingeschmult - ich bin böse und hab das Geschenk schon vor allen anderen geöffnet. :whistling:
    Bitte nicht verhauen. ^^

    Wenn ich recht sehe, zeichnest du im Skript bei jeder "Rotation" die Felder neu bzw. lässt die Farben einfach aktualisieren/eine Position weiterrücken, sodass ein Rotationseffekt entsteht, hm?
    Jedenfalls eine interessante Methode. :)

    Kann man dazu auch noch Text in die Felder einblenden? Es würde reichen, wenn es am Anfang (vorm Drehen) und am Ende (nach dem Drehen) angezeigt wird.
    Ich würde spontan sagen, dass man zu Beginn bei der Bestimmung der Farben diesen direkt ein label mit abspeichert.

    Aber: Lassen sich labels mit Rotation X anzeigen, sodass man sie am Anfang & Ende in den Feldern mit einblenden kann?

    Edit: Beim Rumdoktorn an deinem Skript bollen ist mir auch aufgefallen, dass der pointer, der letztlich das ausgewählte Feld bestimmt z.B. nicht "zwischen" 2 Feldern sein kann ("knappe Drehungen" usw.), da die Felder ja nicht wirklich rotieren, sondern nur 'weitergereicht' werden.
    Wäre natürlich superb, wenn die tatsächliche Rotation möglich wäre.

    Einmal editiert, zuletzt von Matricus (23. Oktober 2013 um 20:52)

  • Hier mal ein Prototyp.

    Spoiler anzeigen
    [autoit]


    ;coded by UEZ 2013-10-24
    #include <GUIConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <StaticConstants.au3>

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

    AutoItSetOption("GUIOnEventMode", 1)
    _GDIPlus_Startup()
    Global Const $iW = 600, $iH = 600, $iW2 = $iW / 2, $iH2 = $iH / 2
    Global Const $hGUI = GUICreate("Glücksrad Prototyp", 800, 600)
    Global Const $iPic = GUICtrlCreatePic("", 0, 0, $iW, $iH), $hPic = GUICtrlGetHandle($iPic)
    Global Const $iBtn_Drehen = GUICtrlCreateButton("&Drehen", 650, 500, 110, 50)
    GUICtrlSetFont(-1, 20, 400, 0, "Arial")
    Global Const $iLbl_Gewinn = GUICtrlCreateLabel("Dein Gewinn:", 610, 20, 110, 30)
    GUICtrlSetFont(-1, 14, 400, 0, "Arial")
    Global Const $iLbl_Preis = GUICtrlCreateLabel("", 610, 50, 180, 50, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    GUICtrlSetBkColor(-1, 0xF0F0C0)
    GUICtrlSetFont(-1, 14, 400, 0, "Arial")

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

    GUICtrlSetOnEvent($iBtn_Drehen, "Btn_Drehen")
    GUISetState()
    Global Const $hGfx = _GDIPlus_GraphicsCreateFromHWND($hPic)
    Global Const $hBmp = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGfx)
    Global Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetSmoothingMode($hCtxt, 2)
    _GDIPlus_GraphicsClear($hCtxt, 0xFF000000)

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

    Global Const $hBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)

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

    Global Const $hMatrix = _GDIPlus_MatrixCreate()
    Global Const $hBmp_Hintergrund = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\Glücksrad Scheibe.png")
    Global Const $hBmp_Rotation = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    Global Const $hCtxt_Rotation = _GDIPlus_ImageGetGraphicsContext($hBmp_Rotation)

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

    Global $aPoints[4][2] = [[3, 0], [$iW2, $iH2 - 50], [$iW2, $iH2 + 50], [$iW2 + 180, $iH2]]
    Global $aFelder[25] = ["Kippe", 600, 400, 200, 900, 200, 400, "Aussetzen", 450, 200, 700, 200, "Extra Dreh", _
    200, 300, 400, 500, 1000, "SKL", 300, 750, 800, 350, "Bankrott", 250]

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")

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

    Global $f, $ff, $iRunden
    Drehen()

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

    Do
    Until False * Sleep(100000)

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

    Func Btn_Drehen()
    $f = Random(3, 15)
    Do
    If $f > 0 Then
    Drehen($f)
    $ff += $f
    $f -= 0.1
    Else
    $iRunden = Floor($ff / 360)
    $iSegment = Mod($iRunden + Ceiling($ff / 15), 25)
    If Not $iSegment Then $iSegment += 1
    If Mod($ff, 15) > 14.45 Or Mod($ff, 15) < 0.55 Then $iSegment = 0
    GUICtrlSetData($iLbl_Preis, $aFelder[$iSegment])
    $f = 0
    ExitLoop
    EndIf
    Until False * Sleep(30)
    EndFunc

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

    Func _Exit()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_MatrixDispose($hMatrix)
    _GDIPlus_GraphicsDispose($hCtxt)
    _GDIPlus_GraphicsDispose($hCtxt_Rotation )
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_BitmapDispose($hBmp_Rotation)
    _GDIPlus_BitmapDispose($hBmp_Hintergrund)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI)
    Exit
    EndFunc

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

    Func Drehen($fGrad = 0)
    _GDIPlus_GraphicsClear($hCtxt, 0xFF202020)
    _GDIPlus_MatrixTranslate($hMatrix, $iW2, $iH2)
    _GDIPlus_MatrixRotate($hMatrix, -$fGrad)
    _GDIPlus_MatrixTranslate($hMatrix, -$iW2, -$iH2)
    _GDIPlus_GraphicsSetTransform($hCtxt_Rotation, $hMatrix)
    _GDIPlus_GraphicsDrawImageRect($hCtxt_Rotation, $hBmp_Hintergrund, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDrawImageRect($hCtxt, $hBmp_Rotation, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsFillPolygon($hCtxt, $aPoints, $hBrush)
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBmp, 0, 0, $iW, $iH)
    EndFunc

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

    Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iPixelFormat = $GDIP_PXF32ARGB, $iStride = 0, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(10, $aResult[0], 0)
    Return $aResult[6]
    EndFunc ;==>_GDIPlus_BitmapCreateFromScan0

    [/autoit]

    Im Anhang das Glücksrad Bild.

    Gruß,
    UEZ

  • UEZ nett, aber er hält manchmal (jedes 2te Mal bei mir) auf dem schwarzen Strich, evtl. sollte man dann noch 2-3cm weiter drehen :D

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Wie gesagt, ist das Ding ein Prototyp. Es soll nur als Ideengeber dienen, so dass Matricus was zum basteln hat.

    Ich habe keine Lust ein komplettes Glücksrad Programm zu schreiben.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hier mal ein Prototyp.


    Dank' Dir! Ich werd' mich am Wochenende mal reinlesen.

    Beim spontanen Überfliegen sehe ich, dass die Beschriftungen auf dem Bild rein zur Darstellung sind, richtig?
    Die tatsächlichen Werte sind in $aFelder gespeichert.

    Zitat

    UEZ nett, aber er hält manchmal (jedes 2te Mal bei mir) auf dem schwarzen Strich, evtl. sollte man dann noch 2-3cm weiter drehen :D


    Kann man ja einbauen, dass es sich automatisch ein Stück weiterdreht. Daran soll es letztlich nun nicht scheitern. ;)

    Zitat

    Es soll nur als Ideengeber dienen, so dass Matricus was zum basteln hat.


    Und das ist es, definitiv! Ich werde mir das, wie gesagt, am Wochenende genauer anschauen und solange drehen, bis ich's Rad nicht mehr sehen kann. :D
    Da muss ich mich zwar wieder ein einiges einlesen, aber learning by doing ist eh der beste Weg für so etwas.

    Vielen Dank für deinen Entwurf!

    Ich setz den Thread erst einmal auf solved. Wenn ich weitere Hilfe brauche, lasse ich es euch wissen. ;)

    <3

  • Ich bin's wieder! ;)

    Ich hab' in der wenigen Freizeit nun mal etwas an dem Projekt gearbeitet und bisher das Zustande gebracht:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <GUISlider.au3>
    #include <GUIButton.au3>
    #include <GUIConstants.au3>
    #include <WindowsConstants.au3>
    #include <ComboConstants.au3>
    #include <Date.au3>

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

    ;Opt("MustDeclareVars", 1)
    Opt("GUIOnEventMode", 1)

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

    ; Size of GUI, Wheel and Modifier Vars
    Global Const $AC_SRC_ALPHA = 1
    Global Const $PIE_DIAMETER = 600
    Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
    Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
    Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

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

    ;MsgBox(64, "Data Output", $PIE_DIAMETER & @CRLF & $PIE_MARGIN & @CRLF & $PIE_DEPTH & @CRLF & $PIE_AREA)

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

    ; Wheel Data: Sections, Colors etc.
    Global Const $NUM_VALUES = 8 ; amount of parts
    Global $aChartValue[$NUM_VALUES]
    Global $aChartColour[$NUM_VALUES]
    Global $NUM_Radius = 360 / $NUM_VALUES ; size per part (if 1:1)
    For $i = 0 To $NUM_VALUES - 1
    $aChartValue[$i] = $NUM_Radius
    $aChartColour[$i] = (Random(0, 255, 1) * 0x10000) + (Random(0, 255, 1) * 0x100) + Random(0, 255, 1) ; randomize colors
    Next

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

    ; Pi
    Global Const $PI = ATan(1) * 4

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

    _GDIPlus_Startup()

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

    ; Solid Creation
    Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
    For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
    Next

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

    #region GUI CREATION
    ; GUI Creation
    Global $hWnd = GUICreate("Wheel", $PIE_AREA + 250, $PIE_AREA, Default, Default)
    ;SetBitmap($hwnd, $hPointer, 255) ; not yet used

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

    ; Basic Controls
    $hcb = GUICtrlCreateCombo("Preset 1", $PIE_DIAMETER + 90, $PIE_DEPTH - 40, $PIE_DEPTH * 2 - 55, 20, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
    GUICtrlSetData(-1, "Preset 2|Preset 3")
    $Button2 = GUICtrlCreateButton("New Preset", $PIE_DIAMETER + 105, $PIE_DEPTH - 10, $PIE_DEPTH - 50, 25)
    $Button1 = GUICtrlCreateButton("Edit Preset", $PIE_DIAMETER + 190, $PIE_DEPTH - 10, $PIE_DEPTH - 50, 25)

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

    $hSpinIt = GUICtrlCreateButton("Spin It!", $PIE_DIAMETER + 40, $PIE_DIAMETER - 60, 100, 25)
    GUICtrlSetOnEvent($hSpinIt, "_SpinWheel")

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

    ; Wheel Modifier
    Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + 600, $PIE_AREA + 60, 100, 20) ; yet not used
    _GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
    _GUICtrlSlider_SetPos($hSlideAspect, 50)
    Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_DIAMETER + 40, $PIE_DEPTH + 40, $PIE_DEPTH * 2, 20)
    _GUICtrlSlider_SetRange($hSlideRotation, 0, 720)
    Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20) ; not yet used; checked by default
    Global $hStyle = GUICtrlGetHandle($cStyle)
    GUICtrlSetState ($cStyle, $GUI_CHECKED)
    Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_DIAMETER + 40, $PIE_DEPTH + 70, $PIE_DEPTH * 2, 20)
    _GUICtrlSlider_SetRange($hHoleSize, $PIE_DEPTH + 80, $PIE_DEPTH + 155)
    _GUICtrlSlider_SetPos($hHoleSize, $PIE_DEPTH * 2)

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    GUISetState()

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

    ; Set up GDI+
    Global $hDC = _WinAPI_GetDC($hWnd)
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
    Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
    Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)
    #endregion

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

    ; Draw the initial pie chart
    _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
    _GUICtrlSlider_GetPos($hSlideRotation), _
    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
    _GUICtrlSlider_GetPos($hHoleSize))

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

    ; The sliders will send WM_NOTIFY messages
    GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

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

    ; Wait until the user quits
    While 1
    Sleep(10)
    WEnd

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

    ; Release the resources
    For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
    Next
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    _WinAPI_ReleaseDC($hWnd, $hDC)

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

    ; Shut down GDI+
    _GDIPlus_Shutdown()

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

    ; Done
    Exit

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

    Func _Exit()
    Exit
    EndFunc

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

    ; Get a darker version of a colour by extracting the RGB components
    Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
    EndFunc ;==>_GetDarkerColour

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

    Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
    Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
    _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
    _GUICtrlSlider_GetPos($hSlideRotation), _
    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
    _GUICtrlSlider_GetPos($hHoleSize))
    Case $hSpinIt
    ;_SpinWheel(Random(750, 2310))

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

    EndSwitch
    EndFunc ;==>_OnNotify

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

    Func _SpinWheel()
    Local $pRotation = Random(10, 25)
    Local $pStepMissing = $pRotation

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

    While $pStepMissing > 0
    _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
    $pRotation, _
    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
    _GUICtrlSlider_GetPos($hHoleSize))
    ;MsgBox(64, "rotation", $pRotation)
    $pStepMissing -= 0.05 ; countdown for spin end + reducing spin amount per round; should not be higher than 0.1
    $pRotation += $pStepMissing ; keep spinning!
    WEnd
    EndFunc

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

    ; Draw the pie
    Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

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

    ; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
    $nTotal += $Percentage[$nCount]
    Next

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

    ; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
    $Percentage[$nCount] /= $nTotal
    Next

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

    ; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

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

    ; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

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

    ; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
    If $nCount = 0 Then
    $Angles[$nCount] = $rotation
    Else
    $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
    EndIf
    Next

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

    Switch $style
    Case 0
    ; Adjust the angles based on the aspect
    For $nCount = 0 To UBound($Percentage)
    $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
    $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
    $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
    If $X = 0 Then
    $Angles[$nCount] = 90 + ($Y < 0) * 180
    Else
    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
    EndIf
    If $X < 0 Then $Angles[$nCount] += 180
    If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
    $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
    $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
    Next

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

    ; Decide which pieces to draw first and last
    Local $nStart = -1, $nEnd = -1
    For $nCount = 0 To UBound($Percentage) - 1
    $angleStart = Mod($Angles[$nCount], 360)
    $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
    If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
    $nStart = $nCount
    EndIf
    If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
    Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
    $nEnd = $nCount
    EndIf
    If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
    Next

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

    ; Draw the first piece
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)

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

    ; Draw pieces "to the right"
    $nCount = Mod($nStart + 1, UBound($Percentage))
    While $nCount <> $nEnd
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
    $nCount = Mod($nCount + 1, UBound($Percentage))
    WEnd

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

    ; Draw pieces "to the left"
    $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
    While $nCount <> $nEnd
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
    $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
    WEnd

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

    ; Draw the last piece
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
    Case 1
    ; Draw the donut pieces
    For $nCount = 0 To UBound($Percentage) - 1
    $angleStart = Mod($Angles[$nCount], 360)
    $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

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

    ; Draw the outer arc in a darker colour
    $hPath = _GDIPlus_GraphicsPathCreate()
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
    $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
    _GDIPlus_GraphicsPathDispose($hPath)

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

    ; Draw the inner piece in a lighter colour - leave room for the hole
    $hPath = _GDIPlus_GraphicsPathCreate()
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
    $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
    $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][0], $hPath)
    _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
    _GDIPlus_GraphicsPathDispose($hPath)
    Next
    EndSwitch

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

    ; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    EndFunc ;==>_DrawPie

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

    Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

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

    ; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_GraphicsPathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    EndIf
    _GDIPlus_GraphicsPathDispose($hPath)

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

    ; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

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

    EndFunc ;==>_DrawPiePiece

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

    Func _GDIPlus_GraphicsPathCreate($iFillMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $iFillMode, "int*", 0);
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[2])
    EndFunc ;==>_GDIPlus_GraphicsPathCreate

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

    Func _GDIPlus_GraphicsPathAddLine($hGraphicsPath, $iX1, $iY1, $iX2, $iY2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathLine", "hwnd", $hGraphicsPath, "float", $iX1, "float", $iY1, _
    "float", $iX2, "float", $iY2)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsPathAddLine

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

    Func _GDIPlus_GraphicsPathAddArc($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathArc", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
    "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsPathAddArc

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

    Func _GDIPlus_GraphicsPathAddPie($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathPie", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
    "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsPathAddPie

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

    Func _GDIPlus_GraphicsPathCloseFigure($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsPathCloseFigure

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

    Func _GDIPlus_GraphicsPathDispose($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDeletePath", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsPathDispose

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

    Func _GDIPlus_GraphicsDrawPath($hGraphics, $hPen, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsDrawPath

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

    Func _GDIPlus_GraphicsFillPath($hGraphics, $hBrush, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
    EndFunc ;==>_GDIPlus_GraphicsFillPath

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

    Func SetBitmap($hGUI, $hImage, $iOpacity) ; not yet used
    Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend

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

    $hScrDC = _WinAPI_GetDC(0)
    $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage))
    DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage))
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", $AC_SRC_ALPHA)
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hMemDC)
    EndFunc ;==>SetBitmap

    [/autoit]

    Es ist so aus allen Vorschlägen etwas. :)

    UEZ' Vorschlag war gut, jedoch auf lange Sicht gesehen, nicht dynamisch genug.
    bollens' Vorschlag geht in die Richtung, in die ich es auch jetzt habe.

    Also hab ich anhand euer Vorschläge selbst was gebaut.

    Probleme die ich noch habe:
    - Anzeige von Werten auf dem Rad, in den Feldern (als Text, nicht als Bild)
    - Ermittlung in welchem Feld es stehen geblieben ist (*)

    * Das war bei UEZ' Vorschlag zwar mit drin, aber aus den Berechnungen werde ich nicht ganz schlau. Wenn ich es richtig verstehe, wird einfach errechnet, wie weit es sich gedreht hat und welches Feld dann dort sein müsste, hm?
    Wo die Position zur Ermittlung ist, sei erst einmal dahingestellt.

    Jemand'n Ideechen?

  • Welche Dynamik fehlt dir denn?

    Meine Berechnung sieht etwas kompliziert aus, aber sollte nicht so schwer sein zu verstehen, da die Kalkulation sich im Prinzip auf 4 Zeilen beschränkt.

    Im Prinzip werden die Rotationen zusammen gezählt und auf das Glücksrad übersetzt. Insgesamt sind es 24 Segmente zu je 15°. Ferner wird noch geprüft, ob der Zeiger auf der "Kippe" steht.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Welche Dynamik fehlt dir denn?


    Naja, zum Bleistift die simple Tatsache, dass es ein Bild ist. Folglich müssen alle Variationen, ob nun Anzahl der Felder oder dessen (visueller) Inhalt als Bild vorhanden sein.

    Das macht eine Dynamik, z.B. das sich die Werte der Felder jede Runde ändern können, quasi unmöglich.

    Meine Berechnung sieht etwas kompliziert aus, aber sollte nicht so schwer sein zu verstehen, da die Kalkulation sich im Prinzip auf 4 Zeilen beschränkt.

    Im Prinzip werden die Rotationen zusammen gezählt und auf das Glücksrad übersetzt. Insgesamt sind es 24 Segmente zu je 15°. Ferner wird noch geprüft, ob der Zeiger auf der "Kippe" steht.


    Wenn man es auf die Tatsachen reduziert, ja, einfach. Es aber logisch zu übernehmen ist wie eine andere Sache.

    Mag' daran liegen, dass ich die jetzige Version in den 2 vorherigen Tagen nach der Arbeit Abends um 22 Uhr zusammengeschustert habe und mein Gehirn einfach schon abgeschalten hat.
    Vielleicht steig' ich ja jetzt durch, wo ich mal 3 Tage am Stück frei habe und nicht immer so im Arbeit-Frei-Wechsel bin. :rolleyes:

    Zitat

    - Anzeige von Werten auf dem Rad, in den Feldern (als Text, nicht als Bild)


    Da ist mir spontan selbst eine Idee gekommen - ja, jetzt wo man frei hat, kann man den Geist auf Wanderschaft schicken :).
    Ich setz' einfach 1 bis 3 labels ein, die am Punkt an dem letztlich der Marker liegt die Werte anzeigen; den aktuellen, sowie den vom vorherigen und nächsten Feld.
    Diese werden dann beim spin auch permanent aktualisiert.

    Ist zwar nicht die optimale Lösung, aber besser als eine Legende oder gar keine Anzeige.

    Wenn jemand 'ne andere oder bessere Idee hat, dann immer her damit. :)

  • Na ja, ich würde es mehr Flexibilität nennen, anstatt Dynamik.

    Anstatt das Glücksrad immer wieder neu zu berechnen, würde ich an deiner Stelle es nur einmal zeichnen und es nur noch rotieren lassen.
    Wenn du was verändern möchtest, dann eben nur dann neuzeichnen.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Irgendwie komme ich mir vor wie ein Grundschüler, der gerade das erste Mal Mathematik Unterricht hat und nichts versteht.
    Ich steig' nicht hinter die Berechnungen von UEZ zur Erfassung des "Siegesfeldes".

    Hier noch mal seine Funktion:

    Spoiler anzeigen
    [autoit]

    Func Btn_Drehen()
    $f = Random(3, 15)
    Do
    If $f > 0 Then
    Drehen($f)
    $ff += $f
    $f -= 0.1
    Else
    $iRunden = Floor($ff / 360)
    $iSegment = Mod($iRunden + Ceiling($ff / 15), 25)
    If Not $iSegment Then $iSegment += 1
    If Mod($ff, 15) > 14.45 Or Mod($ff, 15) < 0.55 Then $iSegment = 0
    GUICtrlSetData($iLbl_Preis, $aFelder[$iSegment])
    $f = 0
    ExitLoop
    EndIf
    Until False * Sleep(30)
    EndFunc

    [/autoit]

    Floor - Abrunden, Ceiling - Aufrunden ... klar.
    Mod ist schon komplexer - Berechnung des Restes aus einer Division, aber sollte klar sein.

    [autoit]

    $iRunden = Floor($ff / 360)
    $iSegment = Mod($iRunden + Ceiling($ff / 15), 25)
    [...]
    If Mod($ff, 15) > 14.45 Or Mod($ff, 15) < 0.55 Then $iSegment = 0

    [/autoit]


    Meine Frage dazu: Warum teilst du bei Ceiling und später beim Modulos durch 15? Was hat es mit dieser 15 auf sich - da grüble ich jetzt schon' bisschen dran. :S
    Den Zusammenhang verstehe ich nicht ganz.

    Und steht die 25 als Divisor bei der $iSegment-Berechnung für die Anzahl der Felder oder wofür?

    Naja, wenn ich's nicht hinbekomme, mache ich einfach 'ne Color-PixelSearch. :D

    Einmal editiert, zuletzt von Matricus (23. November 2013 um 18:50)

  • Ich habe einige Kommentare hinzugefügt:

    [autoit]


    Func Btn_Drehen()
    $f = Random(5, 15) ;zufälligen Drehwinkel in Grad erstellen
    Do
    If $f > 0 Then
    Drehen($f) ;drehe Scheibe um $f Grad
    $ff += $f ;addiere Drehwinkel zur Drehwinkel Summe ($ff)
    $f -= 0.1 ;reduziere Drehwinkel um 1/10 Grad pro Schleifendurchgang
    Else
    $iRunden = Floor($ff / 360) ;messe Anzahl der Runden
    $iSegment = Mod($iRunden + Ceiling($ff / 15), 25) ;bestimme Segment -> 24 Segmente zu je 15°
    If Not $iSegment Then $iSegment += 1 ;korrigiere, wenn Segment Kalulation = 0 ist
    If Mod($ff, 15) > 14.45 Or Mod($ff, 15) < 0.55 Then $iSegment = 0 ;finde "Kippe"
    GUICtrlSetData($iLbl_Preis, $aFelder[$iSegment]) ;zeige "Gewinn"
    ExitLoop
    EndIf
    Until False * Sleep(30)
    EndFunc

    [/autoit]

    Ich hoffe, dass es jetzt "klarer" wird.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯


  • Ein wahrer Augenöffner, gar keine Frage. ;)
    Danke!

    Erst einmal wieder 'solved', wie zu nächsten Frage. :S