3 Stimmen

Corona/Box2D erkennt Kollisionen mit sich nicht bewegenden statischen Objekten

Aus Gründen des Postings ist hier eine einfache Version dessen, was ich zu tun versuche.

Auf dem Bildschirm habe ich ein einfaches Kreisobjekt, das statisch ist und sich nicht bewegt. Der Benutzer kann dann eine gerade Linie ziehen und ablegen. Wenn die Linie durch diesen Kreis geht, hoffe ich, dass das Kollisionsereignis ausgelöst wird.

Es hat den Anschein, dass die Kollision nur dann erkannt wird, wenn sich eines der Objekte bewegt. Kann ich die Kollision erkennen, wenn die Linie gezeichnet wird?

Kollisionsereignis

function onHit(e)
    print("hit");
end
Runtime:addEventListener("collision", onHit)

Touch-Ereignis

local startX = 0;
local startY = 0;
local endX = 0;
local endY = 0;

function onTouch(e)
    if(e.phase == "began") then
        startX = e.x
        startY = e.y
    elseif(e.phase == "moved") then
        endX = e.x
        endY = e.y
    elseif(e.phase == "ended") then
        local line = display.newLine(startX, startY, endX, endY)
        line:setColor(100, 100, 100)
        line.width = 2
        physics.addBody(line, "static", {   })
    end
end
Runtime:addEventListener("touch", onTouch)

Kreis erstellen

local c = display.newCircle(50, 50, 24)
physics.addBody(c, "static", { radius = 24 })

2voto

JeffK Punkte 2989

Diese Seite aus dem Corona SDK-Dokumente beschreibt die bodyType etwa in der Mitte der Seite. Bei der Beschreibung der "statischen" Körper heißt es (meine Hervorhebung):

statische Körper bewegen sich nicht, und nicht miteinander interagieren ; Beispiele für statische Objekte wären der Boden oder die Wände eines Flipperautomaten.

Das bedeutet, dass eines der Objekte etwas anderes sein muss als static .

Hier eine Idee, die ich allerdings selbst noch nicht ausprobiert habe: (Siehe Update unten). Machen Sie die Linie dynamic wenn Sie es zum ersten Mal erstellen. Setzen Sie ihn auf static ein paar Millisekunden später mit einer timer.performWithDelay Funktion. Wenn in der Zwischenzeit ein Kollisionsereignis eintritt, wissen Sie, dass es eine Überschneidung gibt, und können die Funktion bodyType zurück zu static sofort. Wenn Sie kein Kollisionsereignis erhalten, wird die bodyType wird noch dynamic in der verzögerten Routine, und Sie werden wissen, dass Sie keine Überschneidung hatten. In diesem Fall müssen Sie die Zeile trotzdem auf static in der verzögerten Routine.


UPDATE: Ich habe dies getestet, indem ich Ihren Code als Ausgangspunkt verwendet habe

Ich habe das Kollisionsereignis so geändert, dass beide Objekte immer die bodyType zu statisch:

function onHit(e)
    print("hit")
    e.object1.bodyType = "static"
    e.object2.bodyType = "static"
end

Dann habe ich die addBody Aufruf für die Zeile, um sie als dynamic Körper, mit neuem Code zur Einrichtung einer timer.PerformWithDelay Funktion, um nach kurzer Zeit zu überprüfen:

physics.addBody(line, "dynamic", {   })

timer.performWithDelay(10, 
    function()
        if line.bodyType == "dynamic" then
            print ("NO OVERLAP")
            line.bodyType = "static"
        end
    end)

Die Ergebnisse waren leider gemischt. Die meiste Zeit, vielleicht 95 %, funktioniert es, aber gelegentlich schlägt es fehl, wenn eine Linie gezeichnet wird, die außerhalb des Kreises beginnt und innerhalb endet, was eine Überlappung sein sollte, aber manchmal als keine Überlappung gemeldet wird. Ich konnte nicht herausfinden, warum dies der Fall war. Ich poste das trotzdem, in der Hoffnung, dass es Sie weiterbringt, und auch in der Hoffnung, dass jemand in der Lage ist, das inkonsistente Verhalten herauszufinden und uns beide aufzuklären.

Andernfalls könnten Sie eine zusätzliche Prüfung für den Fall "keine Überschneidung" hinzufügen, um zu prüfen, ob einer der beiden Endpunkte der Linie näher als der Radius des Kreises vom Mittelpunkt entfernt ist. Das würde die Dinge zum Laufen bringen, aber ich nehme an, es verfehlt den Sinn, die Physik-Engine die Arbeit machen zu lassen.

Wie auch immer, viel Glück!

0voto

DCurro Punkte 1697

Führen Sie einen Raycast durch, wenn Sie die Maustaste loslassen. Auf diese Weise können Sie beide Objekte statisch halten und wissen, dass sie sich über den Raycast-Callback kreuzen.

(Ich weiß, dass dies ein alter Beitrag ist, aber es war der erste Treffer bei meiner Google-Suche und ist afaic korrekt)

0voto

Kidd Punkte 35

Legen Sie den Körpertyp als kinematisch fest, legen Sie ihn als Sensor fest, und aktualisieren Sie seine Position in jedem Frame mit der Entität, an die er gebunden ist. Im Gegensatz zu static kann kinematic mit static interagieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X