【问题标题】:select a point in the scene to place a node (SpriteKit, Swift)在场景中选择一个点来放置一个节点(SpriteKit,Swift)
【发布时间】:2016-06-13 11:20:51
【问题描述】:

我想这样做,当玩家按下标签时,他必须再次按下屏幕上的一个点来选择建造房屋的地方。到现在为止,这就是我所得到的:当玩家按下标签“build”时,布尔值(“wantsToBuild”)被设置为 true,但现在显然房子是建在标签之上的。我不知道如何检查那个地方是否已经很忙,或者玩家是否可以在那里建造。我想过有一些占位符,但我不知道如何正确设置它们。你能帮我解决这个问题吗?谢谢你。 编辑:我已经按照答案中的建议更改了问题中的代码,但现在我遇到了几个问题:即使我',操纵杆(我之前没有提到过)也会移动m 不要触摸操纵杆本身。另外,即使我已经用打印语句检查了想要构建的值,并且它似乎设置为 false,但每当我按下屏幕时,总是会建造房子。你能帮我进一步吗?

类 GameScene:SKScene {

var ship  = LCDShip()
var shipSpeed : CGFloat = 0.08
var base = SKSpriteNode(imageNamed: "base")
var joystick = SKSpriteNode(imageNamed: "joystick")
var joystickActive = false

var length:CGFloat! = nil
var xDist:CGFloat! = nil
var yDist:CGFloat! = nil

var deltaVector:CGVector! = nil

let build = SKLabelNode()
var wantsToBuild = false

override func didMoveToView(view: SKView) {

    build.name = "build"
    build.fontName = "Chalkduster"
    build.fontSize = 25
    build.text =  "Build a house"
    build.zPosition = 2
    build.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
    addChild(build)


    backgroundColor = SKColor.blackColor()
    ship.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
    addChild(ship)

    base.position = CGPoint(x: 150, y: 200)
    base.setScale(2)
    base.alpha = 0.3
    addChild(base)

    joystick.position = base.position
    joystick.setScale(2)
    joystick.alpha = 0.4
    joystick.name = "base"
    addChild(joystick)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    for touch in touches {
        let house = SKSpriteNode(imageNamed: "house")
        let location = touch.locationInNode(self)
        let node = nodeAtPoint(location)
        let label = self.childNodeWithName("build")!

        if node.name == "build"{
            print("where should i build the hosue?")
            wantsToBuild = true
        } else if wantsToBuild == true && node.name != "house" && location.x <= label.position.x - 15 || location.x >= label.position.x + 15 || location.y >= label.position.y + 15 || location.y <= label.position.y - 15 {
            house.position = location
            house.name = "house"
            addChild(house)
            wantsToBuild = false
        }
    }
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)
        deltaVector = CGVector(dx: location.x - base.position.x, dy: location.y - base.position.y)

        let angle = atan2(deltaVector.dy, deltaVector.dx)

        length = base.frame.size.height/2

        xDist = sin(angle - 1.57079633) * length
        yDist = cos(angle - 1.57079633) * length

        if(CGRectContainsPoint(base.frame, location)){
            joystick.position = location
        } else {
            joystick.position = CGPointMake(base.position.x - xDist, base.position.y + yDist)
        }

        ship.zRotation = angle - 1.57079633
    }
}

override func update(currentTime: NSTimeInterval) {
    if deltaVector != nil {
        ship.position.x += deltaVector.dx * shipSpeed
        ship.position.y += deltaVector.dy * shipSpeed
    }
}

}

【问题讨论】:

    标签: ios xcode swift touchesbegan


    【解决方案1】:

    Bogy 的方法可行,但您可能希望它是 && node.name!= "build",除非您要建造多个房屋,在这种情况下您可能会同时希望 node.name != "build" &amp;&amp; node.name != "house"

    无论如何... 这种方法会起作用,除非你的房子精灵足够大,当你触摸标签旁边而不是实际标签时,房子可能会与标签重叠,并且基本上仍然在标签的顶部。同样,IDK 精灵大小和所有内容。要处理这种情况,您可以在标签周围创建一个不允许放置的范围,方法是:

     let label = self.childNodeWithName("build")!
    
     if wantsToBuild == true && (location.x <= label.position.x - 15 || location.x >= label.position.x + 15 || location.y <= label.position.y - 15 || location.y >= label.position.y + 15) {
            let sprite = SKSpriteNode(imageNamed: "house")
            sprite.position = location
            addChild(sprite)
            wantsToBuild = false
        }
    

    这会在标签周围创建一个更大的盒子,并且不允许您将房子放在那个盒子里,所以如果你把盒子做得足够大(你可能不得不修补 + 15 和 - 15's),即使您将其尽可能靠近标签,也无法将其放置得足够近以重叠。

    如果你的标签是一个精灵,而不是一个 SKLabelNode,你可以按照 Bogy 的说法去做,只需在实际的精灵图像上添加一个不可见空间的边框,这样离不在的精灵最近的点精灵将足够远,不会重叠。

    【讨论】:

    • 感谢两位的回答!现在我遇到了几个问题(我已经用整个代码提出了我的问题)。无论如何你可以帮助我更多吗?
    • 是的,我想我知道它为什么会构建,即使想要构建为假。我不小心遗漏了一个括号,现在它已修复。之前我有:if wantsToBuild == true &amp;&amp; location.x &lt;= ... ) {,但它应该是if wantsToBuild == true &amp;&amp; (location.x &lt;=...) {。上一篇文章中的代码现在已修复,所以请看一下。抱歉弄错了
    • 另外,对于您的操纵杆,我认为它正在四处移动,因为您有这个:if(CGRectContainsPoint(base.frame, location)){ joystick.position = location } else { joystick.position = CGPointMake(base.position.x - xDist, base.position.y + yDist) } 如果您触摸底座,则移动操纵杆 ELSE 将操纵杆移动到 base.position.x 。 .etc. 所以不管你是否在底座里面按,它都会移动。我不确定你希望操纵杆如何表现,但我会去掉“else”部分,如果你不按下底座,它就不会做任何事情。
    • 没问题,非常感谢您的帮助!你的建议正是我想要的。为了解决操纵杆的问题,我添加了一个布尔值(虽然它阻止了我进行多次触摸,因为当我在操纵杆外部点击时它显然停止了)似乎现在正在工作。
    • 酷。很高兴我能帮上忙! :)
    【解决方案2】:

    我觉得你的条件不好,我没有什么可以尝试的,但我会做这样的事情:

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    
        for touch in touches {
            let location = touch.locationInNode(self)
            let node = nodeAtPoint(location)
    
            if node.name == "build"{
                print("where should i build the house?")
                wantsToBuild = true
            }
            else if wantsToBuild == true && node.name != "house" {
                let sprite = SKSpriteNode(imageNamed: "house")
                sprite.position = location
                sprite.name = "house"
                addChild(sprite)
                wantsToBuild = false
            }
        }
    }
    

    【讨论】:

    • 感谢两位的回答!现在我遇到了几个问题(我已经用整个代码提出了我的问题)。无论如何你可以帮助我更多吗?
    【解决方案3】:

    所以我实际上通过清理我的代码并更好地使用您的建议来解决问题。不确定这是不是很棒的代码,但它可以工作。我添加了一个成本和几个 if 语句。这是我现在拥有的,以防有人发现它有用:)

       override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    
        for touch in touches {
            let location = touch.locationInNode(self)
            let node = nodeAtPoint(location)
            if CGRectContainsPoint(base.frame, location){
                joystickActive = true
            }else {
                joystickActive = false
                if node.name == "build" {
                    wantsToBuild = true
                } else if node.name != "house" {
                    checkPlace(location)
                    wantsToBuild = false
                }
            }
        }
    }
    
    func checkPlace(location : CGPoint) {
        let label = self.childNodeWithName("build")!
        let deltaX = location.x - label.position.x
        let deltaY = location.y - label.position.y
        let houseRadius : CGFloat = 60
    
        let distance = sqrt(deltaX * deltaX + deltaY * deltaY)
        if distance <= houseRadius{
            print("YOU CANNOT BUILD HERE")
        } else if distance > houseRadius && wantsToBuild == true{
            if money > 0 {
                buildConstruction(10, location: location)
            }
        }
    }
    
    func buildConstruction(cost: Int, location: CGPoint) {
        let house = SKSpriteNode(imageNamed: "house")
        house.position = location
        house.name = "house"
        addChild(house)
        money -= cost
        print(money)
    }
    

    再次感谢@Arkidillo 和@Bogy 让我走上正轨:)

    【讨论】:

      猜你喜欢
      • 2021-07-12
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      相关资源
      最近更新 更多