Swift Spritekit isometric map touch location

前端 未结 1 1481
孤城傲影
孤城傲影 2021-02-06 10:06

I\'ve started doing a small swift / spritekit project to teach myself game dev. It starts with an isometric map, which I managed to draw. But I\'m having trouble getting a prec

1条回答
  •  深忆病人
    2021-02-06 10:27

    I had a similar issue with isometric map.

    The problem is that the node you click on is bigger than displayed (it has transparent parts). See my question here for a better explanation of the issue.

    Here is how I solved it (sorry code is in Objective-C) :

    1.Create a CGPathRef following the edges of the tile (tileSize being the size of the texture). This code is for regular isometric tiles, not hexagonal but the idea is the same.

    // ObjC
    -(CGPathRef)createTextureFrame:(CGSize)tileSize
    {
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, 0, -(self.tileSize.height / 2));
        CGPathAddLineToPoint(path, NULL, (self.tileSize.width / 2), 0);
        CGPathAddLineToPoint(path, NULL, 0, (self.tileSize.height / 2));
        CGPathAddLineToPoint(path, NULL, -(self.tileSize.width / 2), 0);
        CGPathCloseSubpath(path);
        return path;
    }
    
    // Swift
    func createTextureFrame(tileSize:CGSize) -> CGPathRef {
        CGMutablePathRef path = CGPathCreateMutable()
        CGPathMoveToPoint(path, nil, 0, -(self.tileSize.height / 2))
        CGPathAddLineToPoint(path, nil, (self.tileSize.width / 2), 0)
        CGPathAddLineToPoint(path, nil, 0, (self.tileSize.height / 2))
        CGPathAddLineToPoint(path, nil, -(self.tileSize.width / 2), 0)
        CGPathCloseSubpath(path)
        return path
    }
    

    2.Create a function that checks if a given point is inside the CGPathRef (textureFrame).

    // ObjC
    -(BOOL)isPointOnNode:(CGPoint)point
    {
        return CGPathContainsPoint(textureFrame, NULL, point, YES);
    }
    
    // Swift
    func isPointOnNode(point:CGPoint) -> Bool {
        return CGPathContainsPoint(textureFrame, nil, point, YES)
    }
    

    3.For each touched nodes, check which textureFrame we're in.

    // ObjC
    UITouch *touch = [touches anyObject];
    NSArray *nodes = [self nodesAtPoint:[touch locationInNode:self]];
    for (SKNode *node in nodes)
    {
        CGPoint locationInNode = [touch locationInNode:node];
        if ([node isPointOnNode:locationInNode])
        {
            node.hidden = YES;
        }
    }
    
    // Swift
    var touch = touches.anyObject() as UITouch
    var nodes = self.nodesAtPoint(touch.locationInNode(self))
    for node in nodes as [SKNode] {
        var locationInNode = touch.locationInNode(node)
    
        if node.isPointOnNode() {
            node.hidden = true
        }
    }
    

    I do not know if it's the best solution but it works great. I hope it helps :)

    Edit : Added Swift version of the code

    0 讨论(0)
提交回复
热议问题