【问题标题】:Swift Spritekit isometric map touch locationSwift Spritekit 等距地图触摸位置
【发布时间】:2014-09-16 23:47:03
【问题描述】:

我已经开始做一个小型的 swift / spritekit 项目来自学游戏开发。 它从我设法绘制的等距地图开始。 但是我无法在地图的不同图块上获得精确的触摸位置。 它有效,但有点不合时宜,而且似乎不一致。

这是我的功能:

class PlayScene: SKScene {

let map = SKNode()
    override func didMoveToView(view: SKView) {

        let origin = view.frame.origin
        let mapOrigin = CGPointMake(origin.x + self.frame.width / 4, origin.y - self.frame.height / 4)


        let mapConfig: Int[][] =

       [[0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [2, 2, 2, 2, 1, 2, 2, 2],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0]]

    drawMap(mapConfig, mapOrigin: mapOrigin)
}

与:

 func drawMap(mapConfig:Int[][], mapOrigin:CGPoint)
{
    let tileHeight:CGFloat = 25.5
    let numColumns:Int = 8
    let numRows:Int = 8

    var position = mapOrigin
    var column: Int = 0
    var row: Int = 0

    for column = 0; column < numColumns; column++
    {
        for row = 0; row < numRows; row++
        {
            position.x = mapOrigin.x + CGFloat(column) * tileHeight
            position.y = mapOrigin.y + CGFloat(row) * tileHeight
            let isoPosition = twoDToIso(position)
            placeTile(isoPosition, mapConfig: mapConfig[row][column])
        }
    }
    self.addChild(map)
}

func placeTile(position:CGPoint, mapConfig:Int)
{
 switch mapConfig
    {
    case 0:
        let sprite = SKSpriteNode(imageNamed:"grassTile")
        sprite.position = position
        sprite.setScale(0.1)
        sprite.name = "\(position)"
        self.map.addChild(sprite)
    case 1:
        let sprite = SKSpriteNode(imageNamed:"roadTile")
        sprite.position = position
        sprite.setScale(0.1)
        sprite.name = "\(position)"
        self.map.addChild(sprite)
    default:
        let sprite = SKSpriteNode(imageNamed:"roadTileLTR")
        sprite.position = position
        sprite.setScale(0.1)
        sprite.name = "\(position)"
        self.map.addChild(sprite)
    }
}

然后我想隐藏我触摸的图块(用于测试):

override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
{
    for touch: AnyObject in touches
    {
        let locationNode = touch.locationInNode(self)
        nodeAtPoint(locationNode).hidden = true
    }
}

但它并不总是隐藏正确的图块。 那么我应该如何解决这个问题呢?我的代码从根本上是错误的(可能)吗?还是我需要以某种方式将位置转换为 iso 坐标?或者玩瓷砖位掩码?

无论如何感谢您的帮助!

【问题讨论】:

    标签: ios swift sprite-kit isometric


    【解决方案1】:

    等轴测图也有类似的问题。

    问题是你点击的节点比显示的大(它有透明的部分)。请参阅my question here 以获得对该问题的更好解释。

    这是我解决它的方法(抱歉,代码在 Objective-C 中):

    1.创建一个CGPathRef 跟随瓦片的边缘(tileSize 是纹理的大小)。此代码适用于常规等距瓷砖,而不是六边形,但想法是相同的。

    // 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.创建一个函数来检查给定点是否在 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.对于每个接触的节点,检查我们在哪个textureFrame。

    // 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
        }
    }
    

    我不知道这是否是最佳解决方案,但效果很好。 希望对你有帮助:)

    编辑:添加了 Swift 版本的代码

    【讨论】:

    • 太好了,谢谢。我很快就会试试这个,如果我能解决的话,我会发布 Swift 等价的。
    • 自从我发布了这篇文章后,我开始学习 Swift。我更新了答案;)我是凭记忆写的,现在无法测试,所以可能有一些错误
    猜你喜欢
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多