Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Troubles to detect if a CGPoint is inside a square (diamond-shape)

I have 2 SKSpriteNode:

  • a simple square (A)
  • the same square with a rotation (-45°) (B)

I need to check, at any time, if the center of another SKSpriteNode (a ball) is inside one of these squares. The ball and the squares have the same parent (the main scene).

override func update(_ currentTime: TimeInterval) {

    let spriteArray = self.nodes(at: ball.position)

    let arr = spriteArray.filter {$0.name == "square"}

    for square in arr {
        print(square.letter)

        if(square.contains(self.puck.position)) {
             print("INSIDE")
        }

    }
}

With the simple square (A), my code works correctly. The data are right. I know, at any time, if the CGPoint center is inside or outside the square.

But with the square with the rotation (B), the data aren't as desired. The CGPoint is detected inside as soon as it's in the square which the diamond-shape is contained.

demo

The SKSpriteNode squares are created via the level editor.

How can I do to have the correct result for the diamond-shape?

EDIT 1

Using

view.showsPhysics = true

I can see the bounds of all the SKSpriteNode with physicsBody. The bounds of my diamond-square is the diamond-square and not the grey square area.

 square.frame.size -> return the grey area
 square.size -> return the diamond-square

In the Apple documentation, func nodes(at p: CGPoint) -> [SKNode], the method is about node and not frame, so why it doesn't work?

like image 627
cmii Avatar asked Aug 23 '16 20:08

cmii


1 Answers

There are many ways to do it, usually I like to work with paths so , if you have a perfect diamond as you describe I would like to offer a different way from the comments, you could create a path that match perfectly to your diamond with UIBezierPath because it have the method containsPoint:

let f = square.frame
var diamondPath = UIBezierPath.init()
diamondPath.moveToPoint(CGPointMake(f.size.width-f.origin.x,f.origin.y))
diamondPath.addLineToPoint(CGPointMake(f.origin.x,f.size.height-f.origin.y))
diamondPath.addLineToPoint(CGPointMake(f.size.width-f.origin.x,f.size.height))
diamondPath.addLineToPoint(CGPointMake(f.size.width,f.size.height-f.origin.y))
diamondPath.closePath()
if diamondPath.containsPoint(<#T##point: CGPoint##CGPoint#>) {
   // point is inside diamond
}
like image 95
Alessandro Ornano Avatar answered Oct 13 '22 19:10

Alessandro Ornano