Cocos2d iPhone Non-Rectangular Sprite Touch Detection

前端 未结 3 561
Happy的楠姐
Happy的楠姐 2021-02-11 06:32

Have a project with a TRIANGLE shaped graphic in a sprite. I am arranging these sprites in a grid so that their rectangles are all overlapping. As sprites get touched their z-or

3条回答
  •  臣服心动
    2021-02-11 07:02

    Instead of testing against a box you can of course test against any shape that you wish.

    I initially posted you can use an NSBezierPath, but appearantly that ins't available on the iPhone kit, only on Macs. Instead, on the iPhone you can use CGPath.

    Create a new path by using CGPathCreateMutable() which returns a const CGPath * (also known as CHPathRef
    Then use CGPathAddRect or CGPathAddLines to create our path.
    CGPathContainsPoint will test if your point was in the shape.

    Alternatively, you can create a customer function that (since you use triangles) just does a simple calculation to check whether your point is inside the triangle shape. Bit of math should do the trick (though when you rotate the shape it'll be slightly more complicated. I write slightly, as you can then just rotate the touch point relative to the shape's origin and do the hit detection)

    For a triangle:

       C
      /\
     /__\
    A    B
    point of touch is P
    

    With the following algorithm you should be able to find the touch:

    /* first test against a box, for performance */
    if( P.y > C.y || P.y < A.y || P.x < A.x || P.X > B.x )
        return false; // false if P falls outside "the box"
    
    /* then check if its within the shape */
    /* split the triangle into 2 parts, around the axle of point C */
    if( P.x < C.x ) // if the x value of point P is on the left of point C
        if( P.y > ((C.y -A.y) / (C.x - A.x)) * P.x )
            return false; // the point is above the triangle's side AC
    else // if the x value of point P is greater than or equal to point C
        if( P.y > C.y - ((C.y - B.y) / ( B.x - C.x )) * ( P.x - C.x ) )
            return false; // the point is above the triangle's side BC
    
    return true; // the point must be in the triangle, so return true.
    

    The above is dry coded, but should be correct.

    The above only works against a triangle in the shape as I drew it (where C.x is between A.x and B.x, and A and B are on the same height, but below C). Of course you can modify this to test against any shape, however, you have to weigh this against just using the available CGPath.

    If you don't get it, or if it's faulty, let me know!

提交回复
热议问题