GameplayKit的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用法与实例的更多相关文章
- HTML常用标签用法及实例
HTML常用标签用法及实例1.<!--1.注释-->2.<!--2.DOCTPYE 声明文档类型-->3.<!--3.a--> <a href="h ...
- C# Timer用法及实例讲解
摘自:http://www.cnblogs.com/xcsn/archive/2013/05/10/3070485.html 1.C# Timer用法及实例详解 http://developer.51 ...
- C# Timer用法及实例详解
C# Timer用法有哪些呢?我们在使用C# Timer时都会有自己的一些总结,那么这里向你介绍3种方法,希望对你了解和学习C# Timer使用的方法有所帮助. 关于C# Timer类 在C#里关于 ...
- 【Java学习笔记之二十二】解析接口在Java继承中的用法及实例分析
一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...
- shell脚本学习之case用法及实例
case语句和判断语句[if...elif...else]功能类似;当在逻辑判断比较简单的情况下,比后者的代码量要少许多.case用法,用变量来匹配某值,如果匹配成功则执行它下面的命令,直到 ;;为止 ...
- matlab sign函数用法及实例
在MATLAB科学计算过程当中,我们经常需要对我们的计算公式或者计算结果检验其符号,,sign函数就给我们提供了这种方便,下面就通过实例介绍一下matlab sign函数 的用法,希望能够给您带来帮助 ...
- java中static、this、super、final用途、用法及实例
一.static 请先看下面这段程序: public class Hello { public static void main(String[] args){ //(1) System.out.pr ...
- crontab用法与实例
导读 在Linux系统的实际使用中,可能会经常碰到让系统在某个特定时间执行某些任务的情况,比如定时采集服务器的状态信息.负载状况:定时执行某些任务/脚本来对远端进行数据采集等.这里将介绍下cronta ...
- mysql事务处理用法与实例详解
来源:转载 MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB:支持ACID事务.行级锁.并发 3.Berke ...
随机推荐
- CVPR 2016 paper reading (6)
1. Neuroaesthetics in fashion: modeling the perception of fashionability, Edgar Simo-Serra, Sanja Fi ...
- CVPR 2016 paper reading (3)
DeepFashion: Powering Robust Clothes Recognition and Retrieval with Rich Annotations, Ziwei Liu, Pin ...
- 两种方式(xml+代码)构建SqlSessionFactory+完整实现
首先创建类.接口.数据库: entity包下Admin类: package com.wbg.springJavaConfig.entity; public class Admin { private ...
- Windows中杀死某个端口对应的进程
netstat -ano | findstr 3000 //列出进程极其占用的端口,且包含 3000 tasklist | findstr 17692 // 查看是什么程序占用的 taskkill - ...
- 『ACM C++』 PTA 天梯赛练习集L1 | 048-49
今日刷题048-049 ------------------------------------------------L1-048---------------------------------- ...
- ;(function($,window,document,undefined){})(jQuery,window,document)
;(function($,window,document,undefined){})(jQuery,window,doucment) 1.自调函数(function(){})() 2.好处是不会产生任 ...
- md5加密+盐方式一
这种方法是采用随机生成盐值加入password中组合成的新密码,下面是md5+盐的一个工具类,直接导入使用即可! 工具类 package com.oracle.utils; import java.s ...
- TypeScript 运算符
应用场景(待完善) 位运算符 运算符 描述 例子 类似于 结果 十进制 & AND,按位与处理两个长度相同的二进制数,两个相应的二进位都为 1,该位的结果值才为 1,否则为 0. x = 5 ...
- xshell安装教程
Xshell安装使用教程 Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议.Xshell 通过互联网到远程主机 ...
- 入口文件 index.php 隐藏
入口文件 index.php 隐藏 在PHP的web项目中,问了隐藏项目的开发语言,我们首先会选择把项目的入口文件index.php(如果做了特殊配置,特殊处理)在URL中隐藏掉. 当然部署中还需要隐 ...