2016-01-04 6 views
10

enter image description hereWie kann ich feststellen, ob ein Quadrat die Position ohne Kontakt mit anderen Sprites erreichen kann?

aus dem obigen Bild, eine Anfangsposition von b0 (x, y), eine Endposition b1 (x, y) und positioniert ein (x, y) und c (x, y) gegeben. Wie kann ich vorbestimmen, wenn sich das Quadrat B0 von b0 (x, y) nach b1 (x, y) bewegt, ohne in Kontakt mit dem Rechteck A und C zu kommen? Ich glaube, dass der Winkel benötigt wird.

+0

Kein Winkel wird benötigt, Sie kennen Ihre Startbox, und Ihre Endbox, machen Sie einfach Linien von jedem Punkt auf B0 zu seinem jeweiligen Punkt auf B1, und sehen, ob diese Linien mit A oder C schneiden – Knight0fDragon

+3

@ Knight0fDragon bitte I ' Ich bin mir nicht sicher, wie man einfach Linien von jedem Punkt auf B0 zu seinem jeweiligen Punkt auf B1 macht und ob diese Linien sich mit A oder C schneiden. – ItsMeAgain

+0

Das ist grundlegende Mathematik, google wie man eine Linie mit 2 Punkten macht und wie Um zu überprüfen, ob eine Linie mit einer Box – Knight0fDragon

Antwort

11

Einige Beobachtungen ...

Wenn Box B Ausgangsposition rechts von der Endposition ist (in dem Spalte), dann kann die Box in die Endposition bewegt erfolgreich mit den anderen Boxen nur, ohne kollidieren, wenn Theta ist ein gegen den Uhrzeigersinn Winkel (siehe Abbildung unten). Für diesen Test verwenden Sie die Box B oberen rechten Ecke und der linken unteren Ecke von C.

enter image description here

Und falls Feld B Ausgangsposition links von der Endposition ist, dann kann es erfolgreich Bewegen Sie sich in die Endposition, ohne mit den anderen Boxen zu kollidieren, nur wenn Theta gegen den Uhrzeigersinn ist (siehe Abbildung unten). Für diesen Test verwenden Sie die Box B linken oberen Ecke und der rechten unteren Ecke von A.

enter image description here

Einige Code ...

Zuerst erweitern CGPoint die Ecken eines Kastens zu bestimmen .

extension CGPoint { 
    func bottomLeftCorner(size:CGSize) -> CGPoint { 
     return CGPoint (x:x - size.width/2.0, y:y - size.height/2.0) 
    } 

    func bottomRightCorner(size:CGSize) -> CGPoint { 
     return CGPoint(x:x + size.width/2.0, y:y - size.height/2.0) 
    } 

    func topLeftCorner(size:CGSize) -> CGPoint { 
     return CGPoint (x:x - size.width/2.0, y:y + size.height/2.0) 
    } 

    func topRightCorner(size:CGSize) -> CGPoint { 
     return CGPoint(x:x + size.width/2.0, y:y + size.height/2.0) 
    } 
} 

Der folgende Code ermöglicht es der Benutzer löschen/Drag Box B. Während der Benutzer das Feld bewegt, führt der Code einen On-the-fly-Test, um zu sehen, wenn die Box in den Spalt bewegen kann, ohne kollidieren die anderen Boxen.

class GameScene: SKScene { 

    let size1 = CGSize(width: 100, height: 50) 
    let size2 = CGSize(width: 50, height: 50) 
    let size3 = CGSize(width: 100, height: 50) 

    var boxA:SKSpriteNode! 
    var boxB:SKSpriteNode! 
    var boxC:SKSpriteNode! 

    var center:CGPoint! 

    override func didMove(to view: SKView) { 

     // This is box B's ending position 
     center = CGPoint (x:0,y:0) 

     // Define and add the boxes to the scene 
     boxA = SKSpriteNode(color: SKColor.yellow, size: size1) 
     boxB = SKSpriteNode(color: SKColor.red, size: size2) 
     boxC = SKSpriteNode(color: SKColor.blue, size: size3) 

     boxA.position = CGPoint(x: -size1.width, y: 0) 
     boxB.position = CGPoint(x: 0, y: 0) 
     boxC.position = CGPoint(x: size3.width, y: 0) 

     boxB.zPosition = 1 

     addChild(boxA) 
     addChild(boxB) 
     addChild(boxC) 
    } 

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
     for touch in touches { 
      let location = touch.location(in: self) 

      // Allow user to drag box to a new location 
      boxB.position = location 

      // Find the appropriate corners 
      var cornerA:CGPoint! 
      var cornerB:CGPoint! 
      var cornerC:CGPoint! 
      if (boxB.position.x < center.x) { 
       cornerA = boxA.position.bottomRightCorner(size: boxA.size) 
       cornerB = boxB.position.topLeftCorner(size: boxB.size) 
       cornerC = center.topLeftCorner(size: boxB.size) 
      } 
      else { 
       cornerA = center.topRightCorner(size: boxB.size) 
       cornerB = boxB.position.topRightCorner(size: boxB.size) 
       cornerC = boxC.position.bottomLeftCorner(size: boxC.size) 
      } 
      // Test if box B can move in the gap without colliding 
      if isCounterClockwise(A: cornerA, B: cornerB, C: cornerC) { 
       boxB.color = SKColor.green 
      } 
      else { 
       boxB.color = SKColor.red 
      } 
     } 
    } 

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 
     // Move box B to the ending position 
     let action = SKAction.move(to: center, duration: 2) 
     boxB.run(action) 
    } 

    // Test direction of angle between line segments AB and AC 
    func isCounterClockwise (A:CGPoint, B:CGPoint, C:CGPoint) -> Bool { 
     return (C.y-A.y)*(B.x-A.x) > (B.y-A.y)*(C.x-A.x) 
    } 
} 

und ein Videoclip ...

enter image description here

Box B wird grün, wenn es in die Lücke nicht, ob rot, ohne kollidieren und dann bewegen kann.