【问题标题】:Setting position of custom SKSpriteNode from GameScene从 GameScene 设置自定义 SKSpriteNode 的位置
【发布时间】:2016-01-19 19:55:17
【问题描述】:

我正在制作一个自定义的 SKSpriteNode,当我逐步调用 createShip 时,类中的 heroShip 常量是正确的,但是当我跳回游戏场景时,那里的 heroShip 常量没有我在调用 createShip 时分配的属性,我我不确定我做错了什么。我尝试过使用类函数,但使用 height 和 width 属性不起作用。

自定义 SKSpriteNode 类

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)


    }
}

【问题讨论】:

    标签: ios swift sprite-kit skspritenode


    【解决方案1】:

    你跑

    heroShip.createShip()
    

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

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

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

    var heroShip = hero(imageNamed: "heroShip")
    

    移动到hero 类,func createShip() -&gt; SKSpriteNode { 应该变成func createShip() {。由于您现在已经使用图像纹理设置了节点,并且正在使用 hero 类作为节点,因此无需返回 SKSpriteNode

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

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

    【讨论】:

    • 为什么要将其设为两步流程?只需重写方便的 init 来处理SKPhysicsBody,这样在创建新英雄时就少了 1 步
    • @Knight0fDragon 我不确定 OP 的计划是什么,所以我没有碰它。
    • 我必须验证当我回到家时,我不相信你必须实现它,因为你使用的是基类的指定构造函数,但我可能错了。
    • @Gliderman 那么您将如何处理使位置动态化以便针对所有屏幕尺寸进行缩放?那一直是我的主要问题是如何将“GameScene.size”放入 createShip
    • 获取你的英雄的父节点大小
    【解决方案2】:

    您似乎不了解您的代码发生了什么。

    截至目前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 = hero(imageNamed:"heroShip",sceneSize:self.size)
    • 您还有其他问题,您的其他问题是 bodyA 永远不能保证是子弹,因此您需要考虑 bodyA 是子弹和 bodyB 是子弹的两种情况,并且您的类别需要是在 2 的幂中,这些是位掩码标志,所以 3 实际上意味着 sceneCategory 和 collissionHero,因为在二进制中,3 是 0011(因此是 2 个类别),但是您需要将其设为二进制 0100 以赋予它一个唯一的类别跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多