2015-01-31 3 views
1

Я пытаюсь создать фоновую фоновую игру и иметь два фоновых изображения. Я могу использовать два разных SKSpriteNode(), SKTexture, SKAction.sequence..etc и некоторую математику, чтобы сшить их вместе, но это выглядит как изменчивое, а также я не могу получить математику в самый раз. Предполагается, что они могут быть объединены, чтобы сделать длинный изменяющийся фон, но он всегда смещается.Как объединить две SKTextures в один

Может кто-нибудь сказать мне, как объединить обе текстуры в одну, поэтому мне не нужно ломать голову с помощью математики. Или, если кто-то заметил некоторые ошибки в моей математике, можете ли вы указать их? и фон имеют одинаковую ширину 1200 пикселей

override func didMoveToView(view: SKView) { 
    /* Setup your scene here */ 

    var bgTexture = SKTexture(imageNamed: "bg_2_midground_1.png") 
    var bgTexture2 = SKTexture(imageNamed: "bg_2_midground_2.png") 

    var totalBG = bgTexture.size().width + bgTexture2.size().width 

    var moveBG1 = SKAction.moveByX(-bgTexture.size().width, y: 0, duration: 12) 
    //shift bg back to be able to repeat itself 
    var replaceBG1 = SKAction.moveByX(bgTexture.size().width, y: 0, duration: 0.0) //move immediately back to replace self 
    var moveBG1Forever = SKAction.repeatActionForever(SKAction.sequence([moveBG1,replaceBG1])) 

    var moveBG2 = SKAction.moveByX(-bgTexture2.size().width, y: 0, duration: 12) 
    //shift bg back to be able to repeat itself 
    var replaceBG2 = SKAction.moveByX(bgTexture2.size().width, y: 0, duration: 0.0) //move immediately back to replace self 
    var moveBG2Forever = SKAction.repeatActionForever(SKAction.sequence([moveBG2,replaceBG2])) 

    for var i:CGFloat = 0; i<2; i++ { 
     var bg = SKSpriteNode(texture: bgTexture) 
     var bg2 = SKSpriteNode(texture: bgTexture2) 

     bg.position = CGPointMake(bgTexture.size().width/2.0 + bgTexture.size().width * i + bgTexture2.size().width * i, CGRectGetMidY(self.frame)) 
     bg2.position = CGPointMake(bgTexture.size().width/2.0 + bgTexture2.size().width + bgTexture2.size().width * 2 * i, CGRectGetMidY(self.frame)) 

     bg.runAction(moveBG1Forever) 
     bg2.runAction(moveBG2Forever) 

     self.addChild(bg) 
     self.addChild(bg2) 

     println(bg.position) 
     println(bgTexture.size().width) 

     println(bg2.position) 
     println(bgTexture2.size().width) 
    } 

}

+0

так что вам нужно? Вы хотите, чтобы второй фон появился после первого запуска? и петля такая навсегда? – rakeshbs

+0

точно ... ИЛИ объединить обе текстуры в одну, так или иначе, чтобы я мог просто зацикливать один навсегда, и он выглядел правильно. Прямо сейчас некоторые грани неуместны, потому что моя математика явно неверна –

ответ

2

Вместо использования SKActions, вы можете использовать функцию update, чтобы переместить все фоновые узлы вместе, перемещая каждый узел до конца, как только каждый узел выходит из экрана.

Чтобы сделать вещи более управляемыми, мы можем создать пользовательский фоновый SKNode.

class BackgroundNode : SKNode 
{ 
    override init() { 
     super.init() 

     var bgTexture1 = SKTexture(imageNamed: "b1.jpg") 
     var bgTexture2 = SKTexture(imageNamed: "b2.png") 


     let totalBG = bgTexture1.size().width + bgTexture2.size().width 

     for index in 0..<2 
     { 
      var bg1 = SKSpriteNode(texture: bgTexture1) 
      var bg2 = SKSpriteNode(texture: bgTexture2) 
      bg1.anchorPoint = CGPointMake(0, 0) 
      bg2.anchorPoint = CGPointMake(0, 0) 

      let i = CGFloat(index) 

      bg1.position = CGPointMake(i * bgTexture1.size().width + i * bgTexture2.size().width, 0) 
      bg2.position = CGPointMake((i+1) * bgTexture1.size().width + i * bgTexture2.size().width, 0) 

      self.addChild(bg1) 
      self.addChild(bg2) 
      lastNode = bg2 
     } 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    var speedOfBackground : CGFloat = 300.0 
    var previousTime : CFTimeInterval = -1 
    var lastNode : SKSpriteNode! 

    func update(currentTime: CFTimeInterval) { 

     if previousTime != -1 
     { 
      var outOfBoundsSprite : SKSpriteNode? = nil 
      let deltaX = speedOfBackground * CGFloat(currentTime - previousTime) 
      for sknode in self.children 
      { 
       if let sprite = sknode as? SKSpriteNode 
       { 
        sprite.position = CGPointMake(sprite.position.x - deltaX, sprite.position.y) 
        if (sprite.position.x < -sprite.size.width) 
        { 
         outOfBoundsSprite = sprite 
        } 
       } 
      } 
      if (outOfBoundsSprite != nil) 
      { 
       outOfBoundsSprite?.position.x = lastNode.position.x + lastNode.size.width 
       lastNode = outOfBoundsSprite! 
      } 
     } 
     previousTime = currentTime 
    } 

} 

Вы можете изменять speedOfBackground свойство изменять скорость движения.

Он может быть использован в SKScene как этого

class GameScene: SKScene ,SKPhysicsContactDelegate { 

    var background : BackgroundNode! 

    override func didMoveToView(view: SKView) { 

     background = BackgroundNode() 
     background.speedOfBackground = 500.0 
     self.addChild(background) 
    } 


    override func update(currentTime: CFTimeInterval) { 
     background.update(currentTime) 
    } 
} 
+0

Это хорошее решение @rakeshbs, за исключением того, что if (sprite.position.x <-sprite.size.width) { sprite.position.x = lastNode.position.x + lastNode.size.width lastNode = спрайт } сдвинет положение слишком сильно, так как к времени sprite.position.x <- sprite.size(). ширина есть смещение, записанное в Значение. Чем выше скорость, тем выше смещение, и я прав, где я начинал –

+0

Насколько велики справочные спрайты ура? Вы пробовали код выше? Я добавляю узел, который выходит из экрана после последнего узла и делает его последним узлом каждый раз – rakeshbs

+0

да Я использовал точный код, но всегда есть разрыв между первыми спрайтами и новыми. Разрыв увеличивается/уменьшается при увеличении/уменьшении скорости. Я думаю, что это связано с тем, что lastNode.position.x не является точным кратным 1200, когда он передается в sprite.position.x = lastNode.position.x + lastNode.size.width –

0

@rakeshbs - Ваш ответ был совершенен, я решил расширить его немного. Это позволит кому-то бросить атлас в своем проекте и создать прокрутку фона любого количества изображений. ОДНАКО, следите за загрузкой сразу многих активов, если вы делаете это, вам нужно удалить их из игры, или могут произойти плохие вещи. = P

import SpriteKit 

class BackgroundNode: SKNode { 
    override init() { 
     super.init() 

     // create containers for all the Textures and Nodes 
     var backgroundTextures = [SKTexture]() 
     var backgroundSpriteNodes = [SKSpriteNode]() 

     // load the TextureAtlas for the Background 
     let backgroundAtlas : SKTextureAtlas = SKTextureAtlas(named: "BackgroundImages") 
     let imagesCount:Int = backgroundAtlas.textureNames.count 

     // fetch all of the image resources and store them as both textures and spriteNodes 
     for var i = 1; i <= imagesCount; i++ { 
      let imageTextureName = "background_\(i)" 
      let imageTexture = backgroundAtlas.textureNamed(imageTextureName) 

      let spriteNode = SKSpriteNode(texture: imageTexture) 
      spriteNode.anchorPoint = CGPointMake(0, 0) 

      backgroundTextures.append(imageTexture) 
      backgroundSpriteNodes.append(spriteNode) 
     } 

     // for each image figure out what the x value of the location should be 
     for var i = 0; i < imagesCount; i++ { 
      var addtionalWidth:CGFloat = 0 

      // add the x value of all the images before this image to come up with the latest x 
      for var j = 0; j < i; j++ { 
       addtionalWidth += backgroundTextures[j].size().width 
      } 

      // assign each SKNode a position 
      backgroundSpriteNodes[i].position = CGPointMake(0 + addtionalWidth, 0) 

      // add the Node to the scene 
      self.addChild(backgroundSpriteNodes[i]) 
     } 

     // keep track of where you are to reset scrolls images 
     lastNode = backgroundSpriteNodes[imagesCount - 1] 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    var speedOfBackground : CGFloat = 300.0 
    var previousTime : CFTimeInterval = -1 
    var lastNode : SKSpriteNode! 

    func update(currentTime: CFTimeInterval) { 
     if previousTime != -1 { 
      var outOfBoundsSprite : SKSpriteNode? = nil 
      let deltaX = speedOfBackground * CGFloat(currentTime - previousTime) 

      for sknode in self.children { 
       if let sprite = sknode as? SKSpriteNode { 
        sprite.position = CGPointMake(sprite.position.x - deltaX, sprite.position.y) 

        if (sprite.position.x < -sprite.size.width) { 
         outOfBoundsSprite = sprite 
        } 
       } 
      } 

      if (outOfBoundsSprite != nil) { 
       outOfBoundsSprite?.position.x = lastNode.position.x + lastNode.size.width 
       lastNode = outOfBoundsSprite! 
      } 
     } 

     previousTime = currentTime 
    } 

} 

 Смежные вопросы

  • Нет связанных вопросов^_^