我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

时间:2021-02-22 22:50:44

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

From the image above, given an initial position of b0(x, y), an end position of b1(x, y) and positions a(x, y) and c(x, y). How can I predetermine if square B0 will move from b0(x, y) to b1(x, y) without getting into contact with rectangle A and C? I believe that the angle will be needed.

从上图中,给定b0(x, y)的初始位置,b1(x, y)的结束位置,以及a(x, y)和c(x, y)的位置。我相信这个角度是必要的。

1 个解决方案

#1


11  

Some observations...

一些观察…

If box B's initial position is to the right of the ending position (in the gap), then the box can successfully move to the ending position without colliding with the other boxes only if theta is a counter-clockwise angle (see Figure below). For this test, use the box B's top-right corner and the bottom-left corner of C.

如果盒子B的初始位置在结束位置的右侧(间隙中),那么只有当是逆时针的角度(见下图)时,盒子才能成功移动到结束位置而不与其他盒子发生碰撞(见下图)。在这个测试中,使用方框B的右上角和C的左下角。

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Similarly, If box B's initial position is to the left of the ending position, then it can successfully move to the ending position without colliding with the other boxes only if theta is a counter-clockwise angle (see Figure below). For this test, use the box B's top-left corner and the bottom-right corner of A.

同样,如果box B的初始位置是在结束位置的左边,那么它就可以成功地移动到结束位置,而不与其他的盒子发生碰撞,只有当是一个逆时针的角度(见下图)。对于这个测试,使用方框B的左上角和A的右下角。

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Some code...

一些代码…

First, extend CGPoint to determine the corners of a box.

首先,扩展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)
    }
}

The following code allows the user to drop/drag box B. While the user moves the box, the code performs an on-the-fly test to see if the box can move into the gap without colliding with the other boxes.

下面的代码允许用户删除/拖动方框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<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)
    }
}

and a video clip...

和一个视频…

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Box B turns green if it can move into the gap without colliding and turns red if not.

如果盒子B可以进入空隙而不发生碰撞,它就会变成绿色,如果没有,它就会变成红色。

#1


11  

Some observations...

一些观察…

If box B's initial position is to the right of the ending position (in the gap), then the box can successfully move to the ending position without colliding with the other boxes only if theta is a counter-clockwise angle (see Figure below). For this test, use the box B's top-right corner and the bottom-left corner of C.

如果盒子B的初始位置在结束位置的右侧(间隙中),那么只有当是逆时针的角度(见下图)时,盒子才能成功移动到结束位置而不与其他盒子发生碰撞(见下图)。在这个测试中,使用方框B的右上角和C的左下角。

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Similarly, If box B's initial position is to the left of the ending position, then it can successfully move to the ending position without colliding with the other boxes only if theta is a counter-clockwise angle (see Figure below). For this test, use the box B's top-left corner and the bottom-right corner of A.

同样,如果box B的初始位置是在结束位置的左边,那么它就可以成功地移动到结束位置,而不与其他的盒子发生碰撞,只有当是一个逆时针的角度(见下图)。对于这个测试,使用方框B的左上角和A的右下角。

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Some code...

一些代码…

First, extend CGPoint to determine the corners of a box.

首先,扩展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)
    }
}

The following code allows the user to drop/drag box B. While the user moves the box, the code performs an on-the-fly test to see if the box can move into the gap without colliding with the other boxes.

下面的代码允许用户删除/拖动方框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<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)
    }
}

and a video clip...

和一个视频…

我如何确定一个正方形是否可以在不与其他精灵接触的情况下达到它的位置?

Box B turns green if it can move into the gap without colliding and turns red if not.

如果盒子B可以进入空隙而不发生碰撞,它就会变成绿色,如果没有,它就会变成红色。