Ios 如何将两种纹理组合为一种
我试图为一个游戏创建一个背景,并有两个背景图像。我可以使用两种不同的SKSpriteNode(),SKTexture,SKAction.sequence..等和一些数学来将它们缝合在一起,但结果有点不稳定,而且我似乎无法得到正确的数学结果。他们应该能够结合起来,使一个长期变化的背景,但它总是偏移 有人能告诉我如何将两种纹理组合成一种,这样我就不必在数学上伤脑筋了。或者如果有人发现我的数学错误,你能指出吗?两个背景的宽度相同,为1200像素Ios 如何将两种纹理组合为一种,ios,swift,sprite-kit,sktexture,Ios,Swift,Sprite Kit,Sktexture,我试图为一个游戏创建一个背景,并有两个背景图像。我可以使用两种不同的SKSpriteNode(),SKTexture,SKAction.sequence..等和一些数学来将它们缝合在一起,但结果有点不稳定,而且我似乎无法得到正确的数学结果。他们应该能够结合起来,使一个长期变化的背景,但它总是偏移 有人能告诉我如何将两种纹理组合成一种,这样我就不必在数学上伤脑筋了。或者如果有人发现我的数学错误,你能指出吗?两个背景的宽度相同,为1200像素 override func didMoveToView(
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)
}
覆盖func didMoveToView(视图:SKView){
/*在这里设置场景*/
var bgTexture=SKTexture(图像名为:“bg_2_middground_1.png”)
var bgTexture2=SKTexture(图像名为:“bg_2_middground_2.png”)
var totalBG=bgTexture.size().width+bgTexture2.size().width
var moveBG1=SKAction.moveByX(-bgTexture.size().width,y:0,持续时间:12)
//将bg移回,以便能够重复自身
var replaceBG1=SKAction.moveByX(bgTexture.size().width,y:0,duration:0.0)//立即移回以替换self
var moveBG1Forever=SKAction.repeatActionForever(SKAction.sequence([moveBG1,replaceBG1]))
var moveBG2=SKAction.moveByX(-bgture2.size().width,y:0,持续时间:12)
//将bg移回,以便能够重复自身
var replaceBG2=SKAction.moveByX(bgture2.size().width,y:0,duration:0.0)//立即移回替换self
var moveBG2Forever=SKAction.repeatActionForever(SKAction.sequence([moveBG2,replaceBG2]))
对于var i:CGFloat=0;i而不是使用SKActions,您可以使用update
功能将所有背景节点移动到一起,在每个节点离开屏幕时将每个节点移动到末尾
为了使事情更易于管理,我们可以创建一个自定义的背景节点
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
}
}
@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
}
}
导入SpriteKit
类背景节点:SKNode{
重写init(){
super.init()
//为所有纹理和节点创建容器
var backgroundTextures=[SKTexture]()
var backgroundSpriteNodes=[SKSpriteNode]()
//加载背景的TextureAtlas
let backgroundAtlas:SKTextureAtlas=SKTextureAtlas(命名为:“BackgroundImages”)
让ImageScont:Int=backgroundAtlas.textureNames.count
//获取所有图像资源并将其存储为纹理和spriteNodes
对于var i=1;i,那么你需要什么?你想在第一个背景开始移动后进入第二个背景?并永远像那样循环?完全正确…或者将两个纹理组合成一个,这样我就可以永远循环一个,它看起来是正确的。现在一些边不合适,因为我的数学显然是错误的这是一个好的解决方案@rakeshbs除非(sprite.position.x<-sprite.size.width){sprite.position.x=lastNode.position.x+lastNode.size.width lastNode=sprite}将在sprite.position.x<-sprite.size()时使位置偏移过多.width值中记录了一个偏移量。速度越高,偏移量越大,我就在我开始的位置。你的背景精灵有多大?你尝试过上面的代码吗?我在最后一个节点后添加一个离开屏幕的节点,并使其成为每次使用的最后一个节点是的,我使用了精确的代码,但始终存在一个间隙b在第一个精灵和新添加的精灵之间。当您增加/减少速度时,间距会增加/减少。我认为这是由于lastNode.position.x在传递到sprite.position.x=lastNode.position.x+lastNode.size.width时不是1200的精确倍数
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
}
}