GKStateMachine
玩家進(jìn)入GameScene場景中 -> 通過GKStateMachine進(jìn)入到指定的游戲狀態(tài)GKState
在GameScene場景中 -> 根據(jù)不同的邏輯調(diào)用GKStateMachine -> 在各個(gè)不同的游戲狀態(tài)GKState之間進(jìn)行切換
源碼如下:
一、GameScene.swft
import SpriteKit
import GameplayKit
class GameScene: SKScene,SKPhysicsContactDelegate {
//MARK: - StateMachine 場景中各個(gè)舞臺State
lazy var stateMachine:GKStateMachine = GKStateMachine(states: [
WaitingState(scene: self),
PlayState(scene: self),
GameOverState(scene: self)])
override func didMove(to view: SKView) {
stateMachine.enter(MenuState.self) // 進(jìn)入MenuState
}
func restartGame(){
let newScene = GameScene(fileNamed: "GameScene")!
newScene.size = CGSize(width: SCENE_WIDTH, height: SCENE_HEIGHT)
newScene.anchorPoint = CGPoint(x: 0, y: 0)
newScene.scaleMode = .aspectFill
let transition = SKTransition.crossFade(withDuration: TimeInterval(0.5))
view?.presentScene(newScene, transition:transition)
//reload GameScene 直接進(jìn)入游戲狀態(tài);
newScene.stateMachine.enter(PlayState.self)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
// 當(dāng) physicsWorld.body(at: touchLocation)為nil時(shí)
// 采用atPoint 取得場景中的的精靈
let touchLocation = touch.location(in: self) ///獲得點(diǎn)擊的位置
let nodeAtPoint = self.atPoint(touchLocation) //返回SKNode
/// 判斷目前的GameScene場景舞臺是哪個(gè)state
switch stateMachine.currentState {
case is WaitingState:
/// 判斷是否是點(diǎn)擊了PlayButton
if nodeAtPoint.name == "playButton" {
stateMachine.enter(PlayState.self)
}
if nodeAtPoint.name == "learnTemp" {
print("weird")
UIApplication.shared.open(URL(string: "http://www.iFIERO.com")!, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: { (error) in
print("jump to http://www.iFiero.com")
})
}
case is PlayState:
//挑戰(zhàn):判斷是否是點(diǎn)擊了暫停按鈕 PauseButton
// if nodeAtPoint.name == "pauseButton" {
// stateMachine.enter(PauseState.self)
// }
break;
case is GameOverState:
if nodeAtPoint.name == "tapToPlay" {
restartGame()
}
default:
break;
}
}
//MARK: - 時(shí)時(shí)更新
override func update(_ currentTime: TimeInterval) {
/// 獲取時(shí)間差
if lastUpdateTimeInterval == 0 {
lastUpdateTimeInterval = currentTime
}
dt = currentTime - lastUpdateTimeInterval
lastUpdateTimeInterval = currentTime
stateMachine.update(deltaTime: dt) // 調(diào)用所有State內(nèi)的update方法
}
}
二石抡、MenuState.swft
//
// MenuState.swift
// Copyright ? 2018 iFiero. All rights reserved.
//
import SpriteKit
import GameplayKit
class MenuState:GKState {
// 必須引入場景(如:GameScene)
unowned let scene:GameScene
// 執(zhí)行didEnter前,可在init()初始化代碼
init(scene:SKScene){
self.scene = scene as! GameScene
super.init()
print("Menu State")
}
// 進(jìn)入當(dāng)前狀態(tài)時(shí)觸發(fā)
override func didEnter(from previousState: GKState?) {
}
// 離開當(dāng)前狀態(tài)時(shí)觸發(fā)
override func willExit(to nextState: GKState) {
}
/* 返回一個(gè)布爾值
* 該值指示當(dāng)前處于該狀態(tài)的狀態(tài)機(jī)是否允許轉(zhuǎn)換到指定狀態(tài)
* 通俗點(diǎn)講就是:如果stateMachine(狀態(tài)機(jī))的狀態(tài)是PlayState,那么就從MenuState狀態(tài)轉(zhuǎn)到PlayState狀態(tài)
*/
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is PlayState.Type
}
// Execute Update Per Frame,游戲運(yùn)行過程中的每一幀都會執(zhí)行
// 但須在GameScene update內(nèi)調(diào)用stateMachine.update()
override func update(deltaTime seconds: TimeInterval) {
}
}
三秤掌、PlayingState.swft
import SpriteKit
import GameplayKit
class PlayState:GKState {
unowned let scene:GameScene
init(scene:SKScene){
self.scene = scene as! GameScene
super.init()
print("Play State")
}
override func didEnter(from previousState: GKState?) {
}
// 挑戰(zhàn):創(chuàng)建游戲暫停GKState狀態(tài) PauseState.swift
// return (stateClass == PauseState.self) || (stateClass == GameOverState.self)
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is GameOverState.Type
}
// Excute Update Per Frame
override func update(deltaTime seconds: TimeInterval) {
// update 用于判斷球的速度是否過快,如果太快了則設(shè)置linearDamping的阻力
}
}
四默穴、GameOverState.swft
import SpriteKit
import GameplayKit
class GameOverState:GKState {
unowned let scene:GameScene
init(scene:SKScene){
self.scene = scene as! GameScene
super.init()
}
override func didEnter(from previousState: GKState?) {
print("GameOver State 游戲結(jié)束")
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is PlayState.Type
// return (stateClass == PlayState.self) || (stateClass == MenuState.self)
}
}
更多游戲教學(xué):http://www.iFIERO.com -- 為游戲開發(fā)深感自豪