Ball soll treu dem Reflexionsgesetz an etwas abprallen.

  • Hallo Community,
    ich bins mal wieder, aber diesmal mit einem Problem, bei dem ich nichtmal ansatzweise eine Lösung weiß.
    Es geht um ein Spiel.
    Nach dem ich Powerball fertig gestellt habe, wollte ich etwas größeres machen.
    Es heißt: Block Breaker (viele kennen es bestimmt von Sony Ericsson Handys)
    Zu meinem Problem:
    Bei dem Spiel steuert man eine Scheibe nach links und rechts.
    Dabei fliegt ein Ball durchs Level, der nicht auf den Boden darf.
    Man muss den Ball halt berühren, dass er wieder hoch fliegt.
    So etwas möchte ich auch machen, aber ich hab keine Ahnung, wie ich es machen soll, dass wenn der Ball z.B im 45° Winkel die Wand berührt, er genau im 45° Winkel wieder abprallen soll ;(


    So mein ich:
    [Blockierte Grafik: http://www.bilder-hochladen.net/files/cjim-1.jpg
    Ich hoffe ihr könnt mir helfen :)
    mfg, tim

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • Hmmm, Eintrittswinkel = Austrittswinkel; Und auch die Bewegung spielt ne Rolle, wegen der Beschleunigung des Austritts. Soviel zu Physik :D
    Nur, wie ermittlest du den Winkel? Ist auch bestimmt GDI+ oder??

  • Du muss einfach das entsprechende Vorzeichen ändern.

    In deinem Beispiel fliegt die Kugel mit 2 Vektoren, sagen wir mal vx und vy. Beim Aufprall unten multipliziert du einfach den Vektor vy mit -1. Dadurch bekommst du den neuen Winkel (Vektor v) und musst im Prinzip nur die Kollision berechnen!

    Hier ein Beispiel in GDI+

    Spoiler anzeigen

    ;coded by UEZ 2009
    #include <GUIConstantsEx.au3>
    #include <GDIplus.au3>
    #include <WindowsConstants.au3>

    Global Const $width = @DesktopWidth / 2
    Global Const $height = @DesktopHeight / 2

    Opt("GUIOnEventMode", 1)
    Global $hwnd = GUICreate("Border Collision!", $width, $height, -1, -1, Default, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
    GUISetOnEvent($GUI_EVENT_CLOSE, "close")
    GUISetState()

    _GDIPlus_Startup()
    Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $graphics)
    Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
    _GDIPlus_GraphicsClear($backbuffer)
    _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 4)
    Global $brush_color
    Global $brush = _GDIPlus_BrushCreateSolid()
    _GDIPlus_BrushSetSolidColor($brush, $brush_color)
    Global $max_dots = 1
    Global $max_speed = 5
    Global $iWidth = 60
    Global $iHeight = 60
    Dim $coordinates[$max_dots][5], $angle
    Dim $brush[$max_dots]
    Initialize()

    Do
    _GDIPlus_GraphicsClear($backbuffer, 0xFF000000)
    Draw_Dots()
    Calculate_New_Position()
    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height)
    Sleep(5)
    Until False

    Func Initialize()
    For $k = 0 To $max_dots - 1
    $r = Random(64, 255, 1)
    $g = Random(64, 255, 1)
    $b = Random(64, 255, 1)
    $brush_color = "0xAF" & Hex($r, 2) & Hex($g, 2) & Hex($b, 2)
    $brush[$k] = _GDIPlus_BrushCreateSolid($brush_color)
    New_Coordinates($k)
    Next
    EndFunc ;==>Initialize

    Func Draw_Dots()
    Local $i, $temp_x, $temp_y
    For $i = 0 To $max_dots - 1
    _GDIPlus_GraphicsFillEllipse($backbuffer, $coordinates[$i][0], $coordinates[$i][1], $iWidth, $iHeight, $brush[$i])
    Next
    EndFunc ;==>Draw_Dots

    Func New_Coordinates($k)
    $coordinates[$k][0] = $width / 2 ;Random($width / 20, $width - $width / 20, 1);start x position
    $coordinates[$k][1] = $height / 2 ;Random($height / 20, $height - $height / 20, 1) ;start y position
    $coordinates[$k][2] = Random(1, $max_speed, 1) ;speed of pixel
    $angle = Random(0, 359, 1)
    ConsoleWrite("Angle: " & $angle & "°" & @CRLF)
    $coordinates[$k][3] = $coordinates[$k][2] * Cos($angle * 3.141592653 / 180)
    $coordinates[$k][4] = $coordinates[$k][2] * Sin($angle * 3.141592653 / 180)
    EndFunc ;==>New_Coordinates

    Func Calculate_New_Position()
    Local $k
    For $k = 0 To $max_dots - 1
    $coordinates[$k][0] += $coordinates[$k][3] ;increase x coordinate with appropriate slope
    $coordinates[$k][1] += $coordinates[$k][4] ;increase y coordinate with appropriate slope
    If $coordinates[$k][0] <= 0 Then ;border collision x left
    $coordinates[$k][0] = 1
    $coordinates[$k][3] *= -1
    ElseIf $coordinates[$k][0] >= $width - $iWidth Then ;border collision x right
    $coordinates[$k][0] = $width - ($iWidth + 1)
    $coordinates[$k][3] *= -1
    EndIf
    If $coordinates[$k][1] <= 0 Then ;border collision y top
    $coordinates[$k][1] = 1
    $coordinates[$k][4] *= -1
    ElseIf $coordinates[$k][1] >= $height - $iHeight Then ;border collision y bottom
    $coordinates[$k][1] = $height - ($iHeight + 1)
    $coordinates[$k][4] *= -1
    EndIf
    Next
    EndFunc ;==>Calculate_New_Position


    Func close()
    _GDIPlus_BrushDispose($brush)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>close

    Func _GDIPlus_BrushSetSolidColor($hBrush, $iARGB = 0xFF000000)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSolidFillColor", "hwnd", $hBrush, "int", $iARGB)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
    EndFunc ;==>_GDIPlus_BrushSetSolidColor

    Ich hoffe, dass das dir das hilft :)

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (18. September 2009 um 23:58)

  • also ich muss es möglichst ohne GDI_Plus machen, da ich den ball mit guictrlsetpos() bewege^^
    aber das mit der formel kapier ich nicht ganz^^

    Spoiler anzeigen
    [autoit]

    #cs ----------------------------------------------------------------------------

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

    AutoIt Version: 3.3.0.0
    Author: myName

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

    Script Function:
    Template AutoIt script.

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

    #ce ----------------------------------------------------------------------------

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

    ; Script Start - Add your code below here

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

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <File.au3>
    #include <Array.au3>
    HotKeySet("{LEFT}", "_player_moveleft")
    HotKeySet("{RIGHT}", "_player_moveright")
    $count = _FileCountLines(@ScriptDir & "/level.lvl")
    Dim $lvl[$count +1]
    $lvl[0] = $count
    for $i = 1 to $count Step 1
    $lvl[$i] = FileReadLine(@ScriptDir & "/level.lvl", $i)
    Next
    $left = 214
    $top = 80
    $ballleft = 408
    $balltop = 664
    $playerleft = 376
    $playertop = 720
    _ArrayDisplay($lvl)
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 866, 757,$left ,$top )
    GUISetBkColor(0x000000)
    $Pic1 = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\horz.jpg", 0, 0, 12, 756, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    $Pic2 = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\horz.jpg", 853, 1, 12, 748, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    $Pic3 = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\vert.jpg", 8, 0, 852, 12, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    $Pic4 = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\vert.jpg", 12, 743, 852, 12, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    $ball = GUICtrlCreateIcon("C:\Users\Tim\Desktop\Block Breaker\circle.ico", 0, $ballleft, $balltop, 16, 16, BitOR($SS_NOTIFY,$WS_GROUP))
    $player = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\shuttle.jpg", $playerleft, $playertop, 84, 12, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###
    Dim $block[$count +1]
    For $i = 1 to $lvl[0]
    $pos = StringSplit($lvl[$i], ",")
    $block[$i] = GUICtrlCreatePic("C:\Users\Tim\Desktop\Block Breaker\" & $pos[3] & "-block.jpg", $pos[1], $pos[2], 24, 12, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS))
    Next
    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit

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

    EndSwitch
    WEnd

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

    Func _player_moveleft()
    if $playerleft -8 > 12 then
    $playerleft = $playerleft -8
    GUICtrlSetPos($player, $playerleft, $playertop)
    EndIf
    EndFunc

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

    Func _player_moveright()
    if $playerleft +8 < 866 - 96 then
    $playerleft = $playerleft +8
    GUICtrlSetPos($player, $playerleft, $playertop)
    EndIf
    EndFunc
    #cs da komm ich nicht weiter
    Func _ballmove()
    GUICtrlSetPos($ball,
    #ce

    [/autoit]
    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • Da ist er ja, unser GDI+ Gott!
    Neee im ernst, ich glaub nicht das sich jemand hier besser mit GDI auskennt als UEZ!!

    Wenn er meint das du vx mit xy Multiplizieren solltest, damit xyz rauskommt; dann ist das so :rock: :rock:


    Will ja nicht Schleimen oder so :rolleyes:

  • Ob das jetzt mit GDI+ oder guictrlsetpos() machst, ist erstmal egal.

    Das Objekt bewegt sich mit vx und vy in eine Richtung. Wenn es jetzt zu einer Kollision kommt (vernachlässigen wir mal Drall und andere Faktoren), dann sollte das Objekt sich in eine andere Richtung bewegen.

    Stell dir mal vor, dass eine Kugel sich nur waagerecht bewegt (<-->) und sich an der linken bzw. rechten Bande abstößt. Das heißt, der x Wert ist z.B. aufsteigend, bis die rechte Bande erreicht ist, danach verkleinert sich der x wieder, bis er wieder an die linke Bande stößt. Analog mit der y Achse.

    In meinem Beispiel siehst du unter Func Calculate_New_Position(), wie die neue Position berechnet wird. Je nach Variante wird der Wert einfach mit -1 multipliziert.

    $coordinates[$k][3] bzw. $coordinates[$k][4] sind die Bewegungsvektoren für die x/y Bewegung.

    Ist schwierig zu erklären, aber vielleicht nimmt ihr ja mal Vektoren in Mathe durch... Ich hatte das in der Oberstufe...

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Da ist er ja, unser GDI+ Gott!
    Neee im ernst, ich glaub nicht das sich jemand hier besser mit GDI auskennt als UEZ!!

    Wenn er meint das du vx mit xy Multiplizieren solltest, damit xyz rauskommt; dann ist das so :rock: :rock:


    Will ja nicht Schleimen oder so :rolleyes:

    Das hat eigentlicht nichts mit GDI+ zu tun, sondern mit Mathe :D GDI+ ist nur ein Darstellungsmedium für die Mathematik/Physik.

    Meine GDI+ Codes finde ich persönlich nicht Gott-Like, sondern nur OK! Ich interessiere mich eben mehr für die grafische Darstellung...

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • ich glaub ich verstehe^^
    ich probiers mal und wenns gar nicht klappt meld ich mich wieder :D
    danke erstmal für eure hilfe :)

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • JUHUUUU
    da mit der Formel klappt perfekt^^
    danke an alle :thumbup::thumbup:
    jetzt kann ich endlich weiter machen 8o:whistling:

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • klar^^

    Spoiler anzeigen
    [autoit]


    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <Array.au3>
    #include <File.au3>
    $left = 214
    $top = 80
    $ballleft = 408
    $balltop = 664
    $x = InputBox("", "Gib den x-wert der func an (1-10)")
    $y = InputBox("", "Bib den y-wert der func an (1-10)")
    $Form1 = GUICreate("Form1", 866, 757,$left ,$top )
    GUISetBkColor(0x000000)
    $ball = GUICtrlCreateIcon("circle.ico", 0, $ballleft, $balltop, 16, 16)
    GUISetState(@SW_SHOW)

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

    While 1
    if GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    _ballmove()
    GUICtrlSetPos($ball, $ballleft + $x, $balltop + $y)
    Sleep(10)
    WEnd
    Func _ballmove()
    if $ballleft < 12 Then $x = $x * -1
    if $ballleft > 850 - 12 Then $x = $x * -1
    if $balltop < 12 then $y = $y * -1
    if $balltop > 757 - 24 Then $y = $y * -1
    $ballleft = $ballleft + $x
    $balltop = $balltop + $y
    EndFunc

    [/autoit]


    Hier das script
    Im Paket: das icon und das Script.
    autoit.de/wcf/attachment/6123/

    [autoit]


    While $Life = True
    $nMSG = BrainGetMsg()
    Switch $nMSG
    Case $Idea
    _Convert_Idea2Code()
    EndSwitch
    WEnd

    [/autoit]
  • War doch nicht so schwer oder? :thumbup:

    Du solltest auf die Pfade achten, wenn du deinen Code postest -> $ball = GUICtrlCreateIcon("C:\Users\Tim\Desktop\Block Breaker\circle.ico", 0, $ballleft, $balltop, 16, 16)...

    Apropos Kollision: kannst ja mal hier schauen: #10 Simple Ball Collision Simulation. Mein Versuch mit Kollisionen zwischen Kugeln...

    UEZ ;)

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (19. September 2009 um 15:26)