系列:用Swift作個(gè)游戲
作者:pmst(1345614869)
微博:PPPPPPMST
本節(jié)任務(wù):
- 隨機(jī)生成障礙物裹唆,且一對障礙物上下相距距離固定贸街,但位置隨機(jī)。
幾種情況:
y position = 0
的情況:
y position = playableStart
的情況:
y position = playableStart - 障礙物.size.height/2
的情況:
推導(dǎo)一般情況下的公式:y position = playableStart - 障礙物.size.height/2 + (10%~60%)playgroundHeight
:
上下兩個(gè)障礙物之間距離固定為3.5倍的Player尺寸的高度:
注意推導(dǎo)公式:y position = playableStart - 障礙物.size.height/2
此時(shí)障礙物的頂部剛好與地面齊平,而(10%~60%)playgroundHeight
是一個(gè)浮動(dòng)范圍框仔,表明障礙物超出地面的高度。顯然我們的障礙物的層級關(guān)系是在背景上面但是在Foreground的下面啃炸,因此修改早前的Layer:
enum Layer: CGFloat {
case Background
case Obstacle //添加障礙物層級關(guān)系
case Foreground
case Player
}
01.產(chǎn)生障礙物的構(gòu)造方法
我們需要增添一個(gè)方法用于實(shí)例化一個(gè)紋理(圖片)為仙人掌的精靈(SpriteNode),設(shè)置其zPosition為Obstacle,請?jiān)?code>flapPlayer()方法上方新增如下方法:
func createObstacle()->SKSpriteNode{
let sprite = SKSpriteNode(imageNamed: "Cactus")
sprite.zPosition = Layer.Obstacle.rawValue
return sprite
}
注意到實(shí)例方法生成一個(gè)紋理為Cactus的精靈并返回畦娄,這是之后源源不斷生成障礙物的基礎(chǔ)。
緊接著我們要有一個(gè)實(shí)例方法熟尉,作用是隨機(jī)產(chǎn)生成對的障礙物到場景中归露,步驟如下:
- 使用
createObstacle()
得到下方障礙物的實(shí)例,并將其放置緊貼右側(cè)屏幕邊線斤儿。 - 障礙物y軸上的放置位置范圍為10%~60%,分別計(jì)算最小與最大的y軸點(diǎn)位剧包,通過隨機(jī)函數(shù)得到兩者之間的一個(gè)數(shù)作為y值,設(shè)置障礙物的position,最后添加到worldNode節(jié)點(diǎn)中雇毫。
- 同理實(shí)例化上方障礙物玄捕,將其旋轉(zhuǎn)180°后放置距離下方障礙物3.5倍Player尺寸的地方,添加到worldNode節(jié)點(diǎn)中棚放。
- 給上下障礙物增添一個(gè)移動(dòng)Action,已一定速度自右向左移動(dòng)枚粘,倘若超出屏幕,則從父節(jié)點(diǎn)中移除飘蚯。
//新增三個(gè)常量
let kBottomObstacleMinFraction: CGFloat = 0.1
let kBottomObstacleMaxFraction: CGFloat = 0.6
let kGapMultiplier: CGFloat = 3.5
// 在createObstacle()實(shí)例方法下方增添新方法
func spawnObstacle(){
//1
let bottomObstacle = createObstacle() //實(shí)例化一個(gè)精靈
let startX = size.width + bottomObstacle.size.width/2//x軸位置為屏幕最右側(cè)
//2
let bottomObstacleMin = (playableStart - bottomObstacle.size.height/2) + playableHeight * kBottomObstacleMinFraction //計(jì)算障礙物超出地表的最小距離
let bottomObstacleMax = (playableStart - bottomObstacle.size.height/2) + playableHeight * kBottomObstacleMaxFraction //計(jì)算障礙物超出地表的最大距離
bottomObstacle.position = CGPointMake(startX, CGFloat.random(min: bottomObstacleMin, max: bottomObstacleMax)) // 隨機(jī)生成10%~60%的一個(gè)距離賦值給position
worldNode.addChild(bottomObstacle) //添加到世界節(jié)點(diǎn)中
//3
let topObstacle = createObstacle() //實(shí)例化一個(gè)精靈
topObstacle.zRotation = CGFloat(180).degreesToRadians()//翻轉(zhuǎn)180°
topObstacle.position = CGPoint(x: startX, y: bottomObstacle.position.y + bottomObstacle.size.height/2 + topObstacle.size.height/2 + player.size.height * kGapMultiplier)//設(shè)置y位置 相距3.5倍的Player尺寸距離
worldNode.addChild(topObstacle)//添加至世界節(jié)點(diǎn)中
//4 給障礙物添加動(dòng)作
let moveX = size.width + topObstacle.size.width
let moveDuration = moveX / kGroundSpeed
let sequence = SKAction.sequence([
SKAction.moveByX(-moveX, y: 0, duration: NSTimeInterval(moveDuration)),
SKAction.removeFromParent()
])
topObstacle.runAction(sequence)
bottomObstacle.runAction(sequence)
}
倘若你迫不及待想看看成果馍迄,將spawnObstacle
方法添加至didMoveToView()
最下方,點(diǎn)擊運(yùn)行局骤。一對障礙物“呼嘯而過”攀圈,然后就沒有然后了...確實(shí)目前這個(gè)方法僅僅只是產(chǎn)生一對罷了,為此我們還需要新增一個(gè)方法用于源源不斷的產(chǎn)生障礙物峦甩。請?zhí)砑尤缦聝?nèi)容到spawnObstacle()
方法下方
func startSpawning(){
//1
let firstDelay = SKAction.waitForDuration(1.75)
//2
let spawn = SKAction.runBlock(spawnObstacle)
//3
let everyDelay = SKAction.waitForDuration(1.5)
//4
let spawnSequence = SKAction.sequence([
spawn,everyDelay
])
//5
let foreverSpawn = SKAction.repeatActionForever(spawnSequence)
//6
let overallSequence = SKAction.sequence([firstDelay,foreverSpawn])
runAction(overallSequence)
}
- 第一個(gè)障礙物生成延遲1.75秒
- 生成障礙物的動(dòng)作赘来,用到了先前的實(shí)例方法
spawnObstacle
. - 之后生成障礙物的間隔時(shí)間為1.5秒
- 之后障礙物的生成順序是:產(chǎn)生障礙物,延遲1.5秒;產(chǎn)生障礙物凯傲,延遲1.5秒;產(chǎn)生障礙物犬辰,延遲1.5秒...可以看出[產(chǎn)生障礙物,延遲1.5秒]為一組重復(fù)動(dòng)作冰单。
- 使用
SKAction.repeatActionForever
重復(fù)4中的動(dòng)作幌缝。 - 將延遲1.75秒和重復(fù)動(dòng)作整合成一個(gè)SKAction的數(shù)組,然后讓場景來執(zhí)行該動(dòng)作組诫欠。
請將didMoveToView()
方法中的spawnObstacle
替換成startSpawning()
,點(diǎn)擊運(yùn)行涵卵。
倘若覺得不錯(cuò)浴栽,請點(diǎn)擊喜歡并關(guān)注我吧..