从上图中,给定初始位置b0(x,y),b1(x,y)的结束位置和a(x,y)和c(x,y)的位置.如何在不与矩形A和C接触的情况下预先确定方形B0是否从b0(x,y)移动到b1(x,y)?我相信这个角度是必要的.
一些观察......
如果方框B的初始位置位于结束位置的右侧(在间隙中),则只有当theta是逆时针角度时,方框才能成功移动到结束位置而不与其他方框发生碰撞(见下图).对于此测试,请使用方框B的右上角和C的左下角.
类似地,如果框B的初始位置在结束位置的左侧,那么只有当θ是逆时针角度时,它才能成功地移动到结束位置而不与其他框碰撞(见下图).对于此测试,请使用方框B的左上角和A的右下角.
一些代码......
首先,扩展CGPoint
以确定盒子的角落.
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) } }
以下代码允许用户删除/拖动框B.当用户移动框时,代码执行即时测试以查看框是否可以移动到间隙而不与其他框冲突.
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, 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 , 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) } }
和视频剪辑......
如果盒B在没有碰撞的情况下移动到间隙中则变为绿色,否则变为红色.