来自关卡编辑器的SpriteKit参考节点

时间:2016-06-20 20:22:04

标签: ios swift sprite-kit

我正在使用SpriteKit中的场景编辑器来放置颜色精灵,并使用属性检查器为它们指定纹理。我的问题是试图弄清楚如何从我的GameScene文件中引用这些精灵。例如,我想知道精灵何时距离我的主角一定距离。

修改 - 添加了代码
我正在添加代码,因为出于某种原因,appzYourLife的答案在一个简单的测试项目中很有用,但在我的代码中却没有。我能够使用Ron Myschuk的答案,我也将其包含在下面的代码中以供参考。 (虽然,现在我看一下,我认为元组的数组对我来说太过分了。)正如你所看到的,我有一个带有一些简单动画的Satellite类。有一个LevelManager类,用正确的对象替换场景编辑器中的节点。最后,所有内容都会添加到GameScene.swift中的world节点。

卫星类

func spawn(parentNode:SKNode, position: CGPoint, size: CGSize = CGSize(width: 50, height: 50)) {
        parentNode.addChild(self)
        createAnimations()
        self.size = size
        self.position = position
        self.name = "satellite"
        self.runAction(satAnimation)
        self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
        self.physicsBody?.affectedByGravity = false
        self.physicsBody?.categoryBitMask = PhysicsCategory.satellite.rawValue
        self.physicsBody?.contactTestBitMask = PhysicsCategory.laser.rawValue
        self.physicsBody?.collisionBitMask = 0
    }

    func createAnimations() {
        let flyFrames:[SKTexture] = [textureAtlas.textureNamed("sat1.png"),
                                     textureAtlas.textureNamed("sat2.png")]
        let flyAction = SKAction.animateWithTextures(flyFrames, timePerFrame: 0.14)
        satAnimation = SKAction.repeatActionForever(flyAction)

        let warningFrames:[SKTexture] = [textureAtlas.textureNamed("sat8.png"),
                                         textureAtlas.textureNamed("sat1.png")]
        let warningAction = SKAction.animateWithTextures(warningFrames, timePerFrame: 0.14)
        warningAnimation = SKAction.repeatActionForever(warningAction)
    }

    func warning() {
        self.runAction(warningAnimation)
    }

级别经理班级

import SpriteKit

class LevelManager
{
    let levelNames:[String] = ["Level1"]
    var levels:[SKNode] = []

    init()
    {
        for levelFileName in levelNames {
            let level = SKNode()
            if let levelScene = SKScene(fileNamed: levelFileName) {
                for node in levelScene.children {
                        switch node.name! {
                        case "satellite":
                            let satellite = Satellite()
                            satellite.spawn(level, position: node.position)
                        default: print("Name error: \(node.name)")
                        }
                    }
                }
            levels.append(level)
        }
    }

    func addLevelsToWorld(world: SKNode)
    {
        for index in 0...levels.count - 1 {
            levels[index].position = CGPoint(x: -2000, y: index * 1000)
            world.addChild(levels[index])
        }
    }
}

GameScene.swift - didMoveToView

world = SKNode()
world.name = "world"
addChild(world)

physicsWorld.contactDelegate = self

levelManager.addLevelsToWorld(self.world)
levelManager.levels[0].position = CGPoint(x:0, y: 0)

//This does not find the satellite nodes
let satellites = children.flatMap { $0 as? Satellite }

//This does work
self.enumerateChildNodesWithName("//*") {
   node, stop in
   if (node.name == "satellite") {
      self.satTuple.0 = node.position
      self.satTuple.1 = (node as? SKSpriteNode)!
      self.currentSatellite.append(self.satTuple)
   }
}

2 个答案:

答案 0 :(得分:2)

障碍类

首先,您应该像这样创建一个Obstacle类。

class Obstacle: SKSpriteNode { }

现在进入场景编辑器将Obstacle类与障碍图像相关联

enter image description here

玩家类

为玩家做同样的事情,创建一个类

class Player: SKSpriteNode { }

并将其与您的玩家精灵相关联。

检查碰撞

现在进入GameScene.swift,改变像这样的updated方法

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */

    let obstacles = children.flatMap { $0 as? Obstacle }
    let player = childNodeWithName("player") as! Player

    let obstacleNearSprite = obstacles.contains { (obstacle) -> Bool in
        let distance = hypotf(Float(player.position.x) - Float(obstacle.position.x), Float(player.position.y) - Float(obstacle.position.y))
        return distance < 100
    }

    if obstacleNearSprite {
        print("Oh boy!")
    }

}

它做了什么?

第一行将所有障碍物检索到场景中。 第二行检索播放器(如果不存在则会崩溃)。

接下来,如果至少有一个障碍物距离obstacleNearSprite不超过100个点,它会将Player常数加到真值中。

最后使用obstacleNearSprite打印一些东西。

优化

更新的方法每秒调用60次。我们将这两行放入其中

let obstacles = children.flatMap { $0 as? Obstacle }
let player = childNodeWithName("player") as! Player

为了检索我们需要的精灵。使用现代硬件不是问题,但你应该保存对Obstacle和Player的引用,而不是在每一帧中搜索它们。

打造精彩游戏;)

答案 1 :(得分:1)

您必须循环遍历场景的子项并将它们分配给要在代码中使用的本地对象

假设您的SKS文件中的对象被命名为Obstacle1,Obstacle2,Obstacle3

进入本地对象后,您可以检查并随意执行任何操作

let obstacle1 = SKSpriteNode()
let obstacle2 = SKSpriteNode()
let obstacle3 = SKSpriteNode()
let obstacle3Location = CGPointZero


func setUpScene() {

    self.enumerateChildNodesWithName("//*") {
        node, stop in

        if (node.name == "Obstacle1") {
            self.obstacle1 = node
        }
        else if (node.name == "Obstacle2") {
            self.obstacle2 = node
        }
        else if (node.name == "Obstacle3") {
            self.obstacle3Location = node.position
        }
    }
}