Gute Collisionsabfrage gesucht???

  • Also, ich habe gerade Probleme mit der Collisionsabfrage meines neuen Spieles. Es ist ein 2D-SidescrollGame. Das Scrollen geht sehr einfach dank Prospeed.dll. Also ich erstelle einen Background und setze Objekte (Sprites) in die Welt, in diesem Fall die Solid-Objects. Nun hab ich noch ein weiteres Sprite, meine Figur. Diese kann sich in der Welt bis jetzt nach links oder rechts bewegen. Kommt aber ein Solid-Object, dann kommt es an diesem nicht vorbei.
    Nun suche ich eine Collisionsabfrage die gut funktioniert. Ich hab schon einiges ausprobiert:

    • 4 Seiten mit dem Abstand von ca 2 Pixel zur Figur. Bevor ich mich nach rechts bewegte fragte ich die rechte Seite ab ob es eine Collision mit einem Solid-Object gibt. Nachteil: Beim Bewegen der Figur müssen auch die 4 Seiten mitbewegt werden, was nicht immer sauber läuft. Auch das anpassen der Seiten an die Position der Figur läuft schlecht, da sie immer "nachdröddeln".
    • Die Game Help von OgerLord mit Prospeed-Befehlen umgeschrieben. Nachteil: Mit verschiedenen Befehlen (zb.SetSpeedSprite) konnte ich auf das erzeugte Sprite nicht mehr zugreifen. Dazu kam, das das aufbauen der Bilder sehr langsam ging.
    • Eine Funktion, mit der ich überprüfte, ob 2 Pixel vor mir ein Solid-Object ist. Hier bin ich leider klaglich gescheitert. Der Grund ist, das ich einfach nicht check wie ich das schaffe.

    Womit wir schon beim Thema sind. Ich brauche jemanden der mir Tips oder gleich eine funktionierende Funktion liefert. Natürlich freue ich mit über Anregungen oder Beispiele.
    In folgenden Link könnt ihr meine soweitige Spiel-Programmierung finden.
    Download
    Ich möchte mich auch für den langen Text entschuldigen, aber kürzer gings nicht.

  • Hi,

    bei mir Funktioniert dein Spiel nicht, ich grig nur ein Schwarzen Hintergrund :S

    zur Collisions Abfrage benutz ich immer das hier:

    Spoiler anzeigen
    [autoit]

    Func _RectCollision($Rect1X1,$Rect1Y1,$Rect1X2,$Rect1Y2, $Rect2X1, $Rect2Y1, $Rect2X2, $Rect2Y2)
    ; Prog@ndy
    Local Const $tagRECT = "long;long;long;long"
    Local $1 = DllStructCreate($tagRECT)
    Local $2 = DllStructCreate($tagRECT)
    Local $3 = DllStructCreate($tagRECT)
    DllStructSetData($1,1,$Rect1X1)
    DllStructSetData($1,2,$Rect1Y1)
    DllStructSetData($1,3,$Rect1X2)
    DllStructSetData($1,4,$Rect1Y2)
    DllStructSetData($2,1,$Rect2X1)
    DllStructSetData($2,2,$Rect2Y1)
    DllStructSetData($2,3,$Rect2X2)
    DllStructSetData($2,4,$Rect2Y2)
    Local $r = DllCall("User32.dll", "int", "IntersectRect", "ptr", DllStructGetPtr($3), "ptr", DllStructGetPtr($1), "ptr", DllStructGetPtr($2))
    If @error Then Return SetError(1,0,0)
    Return $r[0]<>0
    EndFunc

    [/autoit]
  • Kollisionsabfragen sind nicht trivial!!!

    Bei AUTOITEROIDS habe ich um die Objekte Kreise gelegt und die Distanz zwischen den Kreisen gemessen.

    Kollision genau dann, wenn Distanz(obj1, obj2) -(r1 +r2) <= 0

    Distanz = Mittelpunkt Obj1 - Mittelpunkt Obj2
    r1 = Radius vom Objekt 1
    r2 = Radius vom Objekt 2


    Bei rechtwinkeligen Objekten, die sich nicht drehen, ist die Kollisionsabfrage nicht so komplex!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Vielen Dank an euch 2.
    @killz: ja, das ist meien misslungene Collisionsabfrage. Geh in die Zeile 203 und ändere bei dem Befehl:

    [autoit]

    $player[0] = Sprite($kreuz, $hdc, 0, 0, 51, 68, 4 , 1, 15, 200,300)

    [/autoit]

    den letzten Parameter in 250 um. So setzt du die Figur auf der x-Achse höher und sie stößt dann nicht mehr an den Stein an. Dann kannst du auch das scrollen bewundern.
    Vielen dank für dein Script, ich schaus mir mal an.
    Greek: allso mei meinen Computern funktioniert es einwandfrei. Vielleicht liegt es am Windows. (das ist immer das Opfer... :rofl: ).
    deine Collisionsabfrage ist interessant. Also wenn ich das richtig verstehe muss ich in die ersten 4 Parameter diese Sachen des ersten Eckes eintragen:

      X-Wert

      Y-Wert

      Weite

      Länge

    bei der 4 weiteren Parameter die 4 Werte des 2 Viereckes.

    -->Bei einer Collision kommt dann ein Wert zurück.

    Nun dies gibt es schon bei Prospeed:

      Collision (genau abfrage)

      Collide (nicht pixelgenau)

      Collide More (gruppenabfrage)

      Collide All (alle collidierende Objekte)

    Aber alle diese Funktionen sagen mir nicht wos collidiert. Also rechts, links, oben...so was mein ich.?

    Wer noch was weis, bitte postet mir euer Wissen. Ich bin am verzweifeln. ?(

  • Greek: Großes Lob für deine Funktion, sie ist perfekt für mich. Das ist genau das was ich brauche...
    Gib mir mal deine Adresse, dann lass ich dir einen Blumenstrauß vorbeischicken. :rofl:

  • Hi,
    hast du mal ne Mail an Frank Abbing geschrieben? Wäre die erste Anlaufstelle wenn du nicht genau weißt wie irgendetwas bei prospeed funktioniert^^
    Die Kollisionsabfragen sind ja schon in die dll integriert. Bekommst du dort Ergebnisse, bei z.B. CollideUnknown() ?

    Zitat

    Aber alle diese Funktionen sagen mir nicht wos collidiert.

    Natürlich sagen es die Funktionen, wahrscheinlich denkst du nur zu kompliziert^^

    Beispiel:
    Deine Spielfigur läuft nach rechts. CollideUnknown() meldet dir nun eine Kollision zwischen der Spielfigur und einem der Solids. Dann MUSS, da sich das Solid ja nicht bewegt, die Kollision auf der rechten Seite der Spielfigur stattgefunden haben.
    Beispiel 2:
    Die Spielfigur steht etwas links vor einer Wand. Eine Falle schiesst von einiger Entfernung von links einen Ball auf die Spielfigur. Die Spielfigur duckt sich, der Ball stösst gegen die Wand (Erkennung einer Kollision!) Aus der Richtung des Balles und der Kollision mit der Wand weisst du, dass der Ball wieder genau in die andere Richtung zurückfliegen muss. Der Ball fliegt nun in die andere Richtung und trifft die Spielfigur.Kollision! Wenn der Ball nach links fliegt, KANN DIE SPIELFIGUR NUR AUF DER RECHTEN SEITE getroffen werden!

    ciao
    Andy

  • Stimmt, da hast du vollkomen recht. Seltsam warum ich da nicht darauf kam. Naja, ich habs jetzt anderst gelöst. Soweit ich weis bekommt man die Objekte die collidieren bei Collide Unknown. Aber die Befehle sind meist anderst wie in der Hilfe-Datei beschrieben, da sie für Profan gelten.
    So, bevor ich den guten Frank nerve, frage ich euch noch ob jemand weiß wie ich mit diesem Befehl:

    [autoit]

    ;###################################################################################################################################
    ; PngFromResource
    ; Loads png with alphachannel from resource file to memory
    ; $loadPng = PngFromResource("name", "Resource_File", Password)
    ; name = name of file in the resource file
    ; Resource_File = name of the resource file
    ; Password = Password of the resource file , created by the "Resource file maker"
    ; Return value = Handle to Image Data
    ;###################################################################################################################################
    Func PngFromResource($L_name, $L_Resource, $L_Pass)
    $L_Read = ReadFilePieceFast(0, "char", $L_Resource, 0, 4, 0)
    Crypt($L_Read, 4, $L_Pass, StringLen($L_Pass))
    $L_offset = DllStructGetData($S_ReadStruct[0],1)

    $L_Split = StringSplit($L_offset,"|")

    $L_Read = ReadFilePieceFast(0, "char", $L_Resource, 0, $L_Split[1], 0)
    Crypt($L_Read, $L_offset, $L_Pass, StringLen($L_Pass))
    $L_data = DllStructGetData($S_ReadStruct[0],1)

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

    $L_str = StringSplit($L_data,"|")
    For $i = 2 To ($L_str[0]-1)
    $L_fileinfo = StringSplit($L_str[$i],",")
    If $L_fileinfo[1] = $L_name Then ExitLoop
    Next
    If $L_fileinfo[1] <> $L_name Then
    MsgBox(0,"Error","File not found")
    Return 0
    Else
    $L_readResource = ReadFilePieceFast(0, "byte", $L_Resource, 0, $L_fileinfo[2], $L_offset+$L_fileinfo[3])
    Crypt($L_readResource, $L_fileinfo[2], $L_Pass, StringLen($L_Pass))
    Return DllStructGetPtr($S_ReadStruct[0],1)
    EndIf
    EndFunc

    [/autoit]


    ein PNG-Bild aus einer einer dll hole. Es sollte gehen. Ich habe schon vieles ausprobiert aber AutoIt stürzte immer ab.
    Wer eine Idee hat bitte melden. Vielen Dank