从 GameScene 设置自定义 SKSpriteNode 的位置

Setting position of custom SKSpriteNode from GameScene

我正在制作自定义 SKSpriteNode,当我逐步调用 createShip 时,class 中的 heroShip 常量是正确的,但是当我跳回 gameScene 时,那里的 heroShip 常量没有我的属性调用 createShip 时分配,我不确定我做错了什么。我试过使用 class 函数,但是使用高度和宽度属性不起作用。

自定义 SKSpriteNode class

class hero: SKSpriteNode {
    var width: CGFloat = 0.0
    var height: CGFloat = 0.0

     func createShip() -> SKSpriteNode {
        let heroShip = SKSpriteNode(imageNamed: "heroShip")
            heroShip.anchorPoint = CGPointMake(1.0, 0.5)
            heroShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
            heroShip.physicsBody?.usesPreciseCollisionDetection = true
              heroShip.zPosition = 1.0
            heroShip.physicsBody?.mass = 0.02
            heroShip.physicsBody?.dynamic = true
            heroShip.physicsBody?.affectedByGravity = false
            heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
            heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
            heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue

            //heroShip.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)

        heroShip.position = CGPointMake(width, height)

        return heroShip


    }
}

我的游戏场景

class GameScene: SKScene,SKPhysicsContactDelegate{


    let background = SKSpriteNode(imageNamed: "background")
    var score:Int = 0
    let scoreLabel = SKLabelNode(fontNamed: "Courier")
    let MotionManager = CMMotionManager()
    var heroShip = hero()
    override func didMoveToView(view: SKView) {
        heroShip.width = self.size.width/6.0
        heroShip.height = self.size.height/2.0
        heroShip.createShip()
        let enemyShip = SKSpriteNode(imageNamed: "enemyShip")
        /* Setup your scene here */
        self.physicsWorld.contactDelegate = self
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0,heroShip.size.width/1.25,frame.width,frame.height - heroShip.size.width*1.6))
        scene?.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
        scene?.physicsBody?.categoryBitMask = ObjectCategory.sceneCategory.rawValue
        background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
        scoreLabel.fontColor = SKColor.whiteColor()
        scoreLabel.text = String(format: "Score: %01u",score)
        scoreLabel.position = CGPointMake(frame.size.width/2, frame.size.height - scoreLabel.frame.size.width/1.2)
        scoreLabel.zPosition = 1.0


        enemyShip.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
        enemyShip.zPosition = 1.0
        enemyShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
        enemyShip.physicsBody?.usesPreciseCollisionDetection = true
        enemyShip.physicsBody?.mass = 0.02
        enemyShip.physicsBody?.dynamic = true
        enemyShip.physicsBody?.affectedByGravity = false
        enemyShip.physicsBody?.categoryBitMask = ObjectCategory.collisionEnemyCategory.rawValue
        enemyShip.physicsBody?.contactTestBitMask = ObjectCategory.collisionBulletCategory.rawValue
        enemyShip.physicsBody?.collisionBitMask = 0x0

        self.addChild(enemyShip)
        self.addChild(background)
        self.addChild(self.heroShip)
        self.addChild(scoreLabel)

        if MotionManager.accelerometerAvailable{
            MotionManager.startAccelerometerUpdates()
        }

    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let bullet = SKSpriteNode(imageNamed: "bullet")
        bullet.position = CGPointMake(heroShip.position.x, heroShip.position.y)
        bullet.zPosition = 1.0
        // Add physics body for collision detection
        bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
        bullet.physicsBody?.dynamic = true
        bullet.physicsBody?.affectedByGravity = false
        bullet.physicsBody?.categoryBitMask = ObjectCategory.collisionBulletCategory.rawValue
        bullet.physicsBody?.contactTestBitMask = ObjectCategory.collisionHeroCategory.rawValue
        bullet.physicsBody?.collisionBitMask = 0x0;
        let action = SKAction.moveToX(CGRectGetMaxX(self.frame) + bullet.size.width, duration: 0.75)
        self.addChild(bullet)
        bullet.runAction(action, completion: {
            bullet.removeAllActions()
            bullet.removeFromParent()
        })
    }

    func didBeginContact(contact: SKPhysicsContact) {
        if contact.bodyB.categoryBitMask == ObjectCategory.collisionBulletCategory.rawValue && contact.bodyA.categoryBitMask == ObjectCategory.collisionEnemyCategory.rawValue{
        score++
        }
    }



    override func update(currentTime: CFTimeInterval) {
        let data = MotionManager.accelerometerData
        if data?.acceleration.x == nil{
            print("nil")
        }
        else if fabs((data?.acceleration.x)!) > 0.2 {
            heroShip.physicsBody?.applyForce(CGVectorMake(0.0, CGFloat(40 * (data?.acceleration.x)!)))
        }

        scoreLabel.text = String(format: "Score: %01u",score)


    }
}

您似乎没有理解您的代码发生了什么。

截至目前createShip()正在创建一艘英雄飞船,但您从未使用过它。

通过查看您的代码,似乎甚至不需要 createShip()。看hero是heroShip,你init里的代码也是。

    convenience init(imageNamed: String,sceneSize:CGSize) {
    let heroTexture = SKTexture(imageNamed: imageNamed)

    self.init(texture: heroTexture, color: UIColor.whiteColor(), size: heroTexture.size()) //This may need to be tweeked, my mac is dead right now to verify.
    self.anchorPoint = CGPointMake(1.0, 0.5)
    self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
    self.physicsBody?.usesPreciseCollisionDetection = true
    self.zPosition = 1.0
    self.physicsBody?.mass = 0.02
    self.physicsBody?.dynamic = true
    self.physicsBody?.affectedByGravity = false
    heroShip.physicsBody?.categoryBitMask = ObjectCategory.collisionHeroCategory.rawValue
        heroShip.physicsBody?.contactTestBitMask = ObjectCategory.sceneCategory.rawValue
        heroShip.physicsBody?.collisionBitMask = 0x0 | ObjectCategory.sceneCategory.rawValue

    //self.position = CGPointMake((scene?.frame.size.width)!/6.0, (scene?.frame.size.height)!/2.0)

    self.position = CGPointMake(sceneSize.width, sceneSize.height)



}

你现在遇到了另一个问题,那就是你的SKPhysicsBody不会对齐你的锚点。

要解决此问题,请像这样创建 SKPhysicsBody

let centerPoint = CGPointMake(self.size.width / 2 - (self.size.width * self.anchorPoint.x), self.size.height / 2 - (self.size.height * self.anchorPoint.y))
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size, center: centerPoint)

你运行

heroShip.createShip()

然后永远不要对 returned 的 SKSpriteNode 做任何事情。据我所知,英雄 class 英雄船。对于这个答案的其余部分,我将放弃这个假设。

GameScene 的顶部开始,您应该进行一些重构。

var heroShip = hero() 将被替换为使用 SKSpriteNode 结构的 init:

var heroShip = hero(imageNamed: "heroShip")

移动到hero class,func createShip() -> SKSpriteNode {应该变成func createShip() {。由于您现在已经使用图像纹理设置了节点,并且正在使用 hero class 作为节点,因此不需要 return a SKSpriteNode.

删除 let heroShip = SKSpriteNode(imageNamed: "heroShip") 因为 hero class 将成为我们的 heroShip.

heroShip.whatever 变量的所有用法替换为 self.whatever。最后,删除 return heroShip.