GameplayKit的GKStateMachine用法與實例
阿新 • • 發佈:2018-10-11
通過 實例 location width state com ren original function
GKStateMachine
玩家進入GameScene場景中 -> 通過GKStateMachine進入到指定的遊戲狀態GKState
在GameScene場景中 -> 根據不同的邏輯調用GKStateMachine -> 在各個不同的遊戲狀態GKState之間進行切換
源碼如下:
一、GameScene.swft
import SpriteKit
import GameplayKit
class GameScene: SKScene,SKPhysicsContactDelegate {
//MARK: - StateMachine 場景中各個舞臺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) // 進入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 直接進入遊戲狀態;
newScene.stateMachine.enter(PlayState.self)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
// 當 physicsWorld.body(at: touchLocation)為nil時
// 采用atPoint 取得場景中的的精靈
let touchLocation = touch.location(in: self) ///獲得點擊的位置
let nodeAtPoint = self.atPoint(touchLocation) //返回SKNode
/// 判斷目前的GameScene場景舞臺是哪個state
switch stateMachine.currentState {
case is WaitingState:
/// 判斷是否是點擊了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:
//挑戰:判斷是否是點擊了暫停按鈕 PauseButton
// if nodeAtPoint.name == "pauseButton" {
// stateMachine.enter(PauseState.self)
// }
break;
case is GameOverState:
if nodeAtPoint.name == "tapToPlay" {
restartGame()
}
default:
break;
}
}
//MARK: - 時時更新
override func update(_ currentTime: TimeInterval) {
/// 獲取時間差
if lastUpdateTimeInterval == 0 {
lastUpdateTimeInterval = currentTime
}
dt = currentTime - lastUpdateTimeInterval
lastUpdateTimeInterval = currentTime
stateMachine.update(deltaTime: dt) // 調用所有State內的update方法
}
}
二、MenuState.swft
//
// MenuState.swift
// Copyright © 2018 iFiero. All rights reserved.
//
import SpriteKit
import GameplayKit
class MenuState:GKState {
// 必須引入場景(如:GameScene)
unowned let scene:GameScene
// 執行didEnter前,可在init()初始化代碼
init(scene:SKScene){
self.scene = scene as! GameScene
super.init()
print("Menu State")
}
// 進入當前狀態時觸發
override func didEnter(from previousState: GKState?) {
}
// 離開當前狀態時觸發
override func willExit(to nextState: GKState) {
}
/* 返回一個布爾值
* 該值指示當前處於該狀態的狀態機是否允許轉換到指定狀態
* 通俗點講就是:如果stateMachine(狀態機)的狀態是PlayState,那麽就從MenuState狀態轉到PlayState狀態
*/
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is PlayState.Type
}
// Execute Update Per Frame,遊戲運行過程中的每一幀都會執行
// 但須在GameScene update內調用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?) {
}
// 挑戰:創建遊戲暫停GKState狀態 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 用於判斷球的速度是否過快,如果太快了則設置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 遊戲結束")
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is PlayState.Type
// return (stateClass == PlayState.self) || (stateClass == MenuState.self)
}
}
更多遊戲教學:http://www.iFIERO.com -- 為遊戲開發深感自豪
源碼傳送門:https://github.com/apiapia/BreakOutGameVansVTutorial
GameplayKit的GKStateMachine用法與實例