前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >玩家状态机-使用GameplayKit管理不同的状态和动画

玩家状态机-使用GameplayKit管理不同的状态和动画

作者头像
iOSDevLog
发布2019-03-11 14:29:52
1.8K0
发布2019-03-11 14:29:52
举报
文章被收录于专栏:iOSDevLogiOSDevLog

在本节中,我们将了解GameplayKit状态机,然后我们将让我们的玩家跳转并给他一些其他动画,所以扣紧并为这一知识的骑行做好准备。

下载PlayerState Machine 玩家状态机

要学习本教程,您将需要Xcode 9,您可以下载最终项目,以帮助您与自己的进度进行比较。

GameplayKit状态机

首先,我们需要了解玩家的所有不同状态,因为我们将把它们应用到我们的游戏中。

playerStateMachine

LandingState

LandingState是玩家接触地面的时间。

IdleState

IdleState是玩家静止时的动画。

WalkingState

WalkingState是玩家走路时的动画。

JumpingState

JumpingState是玩家跳跃和动作的动画。

StunnedState

最后,StunnedState是玩家被陷阱或敌人触碰时的动画。

状态

正如您在上图中所注意到的那样,所有状态都是相互连接的,这意味着所有状态都以不同的方式相关。

建立

让我们创建一个新的Swift文件,你可以按Command和N来创建新文件。将出现一个新窗口,确保您在iOS平台上并选择Swift File模板并单击Next。然后,我们将被要求命名该文件。我们将其称为“playerStateMachine”,我们将其保存在我们的初始文件夹ElonGame中并点击Create。

GameplayKit

现在,我们需要研究游戏的逻辑,所以我们需要调用GameplayKit框架。GameplayKit与游戏的逻辑更相关,因为SpriteKit用于游戏的视觉部分。让我们将GameplayKit导入我们的新文档。

为玩家状态导入玩家动画和类

接下来,我们将调用所有玩家动画,稍后,我们将为PlayerState创建一个类。在能够接收状态之前必须初始化玩家。我们将添加的所有代码将在导入GameplayKit后立即生效

我们正在使用名称characterAnimationKey重新组合所有动画。在PlayerState类中,我们将playerNode初始化为SKNode,并使他能够接收动画和动作状态。这些状态仅适用于playerNode。

跳跃状态 Jumping State 类

我们将添加一个跳跃状态类JumpingState来管理跳跃动作。在这个类中,我们需要创建两个函数。第一个isValidNextState是一个指示器,它将告诉我们当前状态是否允许转换到下一个状态。我们现在将默认返回值设置为true。第二个函数didEnter将帮助我们在玩家进入跳跃状态时执行一些动作。当他这么做的时候,我们正在给他施加75牛顿的重力,持续时间为0.1秒。此持续时间决定了玩家跳跃的速度。显然,在跳转期间,hasFinishedJumping的值设置为false。最后,我们将添加一个Timer这将有助于我们限制跳跃动作,主要是阻止玩家同时跳跃多次,试图像Flappy Bird一样在空中飞行。这将确保初始跳跃已完成,然后再次重复。一旦玩家登陆,hasFinishedJumping就变为真实。

游戏场景设置

我们需要为Player State定义一些变量,让我们在Sprite Engine之后添加声明。

didMove设置

didMove方法内部,在joystickKnob = joystick?.childNode(withName:“knob”)之后,让我们添加将保持玩家不同状态的playerStateMachine数组。

touchesBegan

让我们去touchesBegan并在的大括号内!如果!(操纵杆?.contains(位置))!,让我们开始跳跃动作。

现在,让我们运行模拟器。除了使用操纵杆左右控制玩家之外,如果点击屏幕,玩家会通过跳跃进行响应。

玩家状态

让我们回到playerStateMachine.swift和文档的底部,让我们创建更多班的其余State我们的玩家

着陆状态类

让我们为着陆状态创建一个新类。在这个类中,我们将添加相同的** isValidNextState 函数作为跳转类。但是,我们将使用Switch**语句作为控制流。它类似于if语句,除了它运行某个代码块,具体取决于匹配的多个值而不是true或false。我们在跳转状态类中选择了Switch语句而不是if语句,因为稍后我们会添加更多的情况。在这个课程中,我们正在检查玩家是处于着陆状态还是处于跳跃状态。如果任一条件为假,则不要进入空闲状态。

代码语言:javascript
复制
class LandingState : PlayerState {
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {

        switch stateClass {
        case is LandingState.Type, is JumpingState.Type: return false
        default: return true
        }
    }

    override func didEnter(from previousState: GKState?) {

        stateMachine?.enter(IdleState.self)
    }
}

空闲状态类

LandingState类一样,我们需要为IdleState创建一个类,并再次验证我们是否可以使用** isValidNextState 函数进入下一个状态。然后,我们将使用表示可应用于节点的图像的SKTexture对象声明变量纹理。作为参数,我们将应用图像玩家/ 0以使玩家在空闲状态期间保持静止。最后,我们将声明一个操作,将图像附加到我们之前选择的玩家。的动作变量被存储为懒惰避免被RAN直到必要被称为首次这是在当didEnter**功能,以及删除任何以前的动画后的功能。使用惰性属性进行声明的目的是节省处理时间并优化内存。

代码语言:javascript
复制
class IdleState : PlayerState {
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {

        switch stateClass {
        case is LandingState.Type, is IdleState.Type: return false
        default: return true
        }
    }

    let textures = SKTexture(imageNamed: "player/0")
    lazy var action = { SKAction.animate(with: [textures], timePerFrame: 0.1)} ()

    override func didEnter(from previousState: GKState?) {

        playerNode.removeAction(forKey: characterAnimationKey)
        playerNode.run(action, withKey: characterAnimationKey)
    }
}

行走状态类

现在,让我们定义walkingState类。其中的代码与IdleState非常相似。然而,纹理变量是一个数组,其中包含我们玩家的不同帧,因此当他走路时,他的动画就好像他的腿和手臂在现实生活中一样移动。这个动作一直在运行,直到我们另一个状态中断行走。

代码语言:javascript
复制
class WalkingState : PlayerState {
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {

        switch stateClass {
        case is LandingState.Type, is WalkingState.Type : return false
        default: return true
        }
    }

    let textures : Array<SKTexture> = (0..<6).map({ return "player/\($0)"}).map(SKTexture.init)
    lazy var action = { SKAction.repeatForever(.animate(with: textures, timePerFrame: 0.1))} ()

    override func didEnter(from previousState: GKState?) {

        playerNode.removeAction(forKey: characterAnimationKey)
        playerNode.run(action, withKey: characterAnimationKey)
    }
}

眩晕状态类

我们将首先声明** StunnedState**类,但暂时将其留空。我们将在后面的部分完成。

代码语言:javascript
复制
class StunnedState : PlayerState {

}

约束跳跃

让我们回到JumpingState类来限制跳跃,这样当我们的玩家完成跳跃并降落在地面上时,他才能再次跳跃。在函数isValidNextState内部和返回true之前,添加以下条件。此外,让我们改变返回true,以返回false**。

代码语言:javascript
复制
if hasFinishedJumping && stateClass is LandingState.Type { return true }

return false

跳跃动画

isValidNextState函数的正下方,让我们将变量纹理声明为数组类型,用于存储跳跃动画的图像。同样,我们将运行一个动作来使用这些图像为玩家设置动画,就像在行走动画中一样。

代码语言:javascript
复制
let textures : Array<SKTexture> = (0..<2).map({ return "jump/\($0)"}).map(SKTexture.init)
lazy var action = { SKAction.animate(with: textures, timePerFrame: 0.1)} ()

删除并运行操作

在下面的didEnter函数中,让我们在** hasFinishedJumping = false **上方添加remove和run操作。

代码语言:javascript
复制
playerNode.removeAction(forKey: characterAnimationKey)
playerNode.run(action, withKey: characterAnimationKey)

完成State

让我们回到GameScene.swift文档,然后查找didMove函数。在JumpingState(playerNode:player!),之后,让我们在数组** playerStateMachine中添加其余的玩家状态**。

代码语言:javascript
复制
WalkingState(playerNode: player!),
IdleState(playerNode: player!),
LandingState(playerNode: player!),
StunnedState(playerNode: player!),

默认玩家为空闲状态

现在,我们需要在游戏开始时将玩家默认为处于空闲状态。在playerStateMachine = GKStateMachine之后,添加这行代码。

代码语言:javascript
复制
playerStateMachine.enter(IdleState.self)

positivePosition

现在我们已经设置了所有玩家状态,让玩家在用户移动旋钮时进入行走状态。为此,请转到Game Loop标记下的更新功能,并在声明xPosition 之后,让我们创建一个名为 positivePosition的新变量。这将为旋钮的x位置存储正值。

代码语言:javascript
复制
let positivePosition = xPosition < 0 ? -xPosition : xPosition

if floor(positivePosition) != 0 {
    playerStateMachine.enter(WalkingState.self)
} else {
    playerStateMachine.enter(IdleState.self)
}

当我们声明positivePosition时,我们正在测试xPosition是否为负数。如果这是真的,那就让它变得积极。然后,我们使用floor函数将该值四舍五入为最接近的整数。如果最终结果不为0,表示旋钮不在操纵杆的中心,请让玩家走动动画。否则,让他进入空闲状态。

设置行走状态

如果您运行应用程序并点击屏幕,您将看到当我们的玩家跳跃时,他会进入跳跃动画。然而,即使他登陆后,他仍然处于跳跃状态。为了解决这个问题,我们需要修改行走状态,原因是我们还没有应用与地面的碰撞。让我们回到playerStateMachine.swift文件,并在JumpingState类,注释掉这种情况下 ,如果hasFinishedJumping && stateClass是LandingState.Type {返回true} 。同样,让我们​​改变返回false返回true。由于我们尚未应用碰撞,因此行走和跳跃状态现在发生冲突。

代码语言:javascript
复制
// if hasFinishedJumping && stateClass is LandingState.Type { return true }

return true

现在再次运行模拟器并执行跳转。这次,当我们左右移动操纵杆时,我们的玩家实际上正在行走。此外,由于我们刚刚删除约束,他可以连续跳转我们垃圾邮件的次数。如果我们放开旋钮,玩家将停止所有的行走和跳跃。

https://dl.dropboxusercontent.com/s/32b6nqb40lkiqft/2.playerStateMachine-SettingUptheWalking%20state.mp4?dl=0

结论

在本节中,我们了解了GKStateMachine,为我们的玩家分配了不同的状态,并对何时进入和退出这些状态应用了某些条件。最重要的是,我们为它们添加了动画并应用它们。

原文: https://designcode.io/playerstate-machine

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.02.28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 下载PlayerState Machine 玩家状态机
  • GameplayKit状态机
    • LandingState
      • IdleState
        • WalkingState
          • JumpingState
            • StunnedState
              • 状态
              • 建立
              • GameplayKit
              • 为玩家状态导入玩家动画和类
              • 跳跃状态 Jumping State 类
              • 游戏场景设置
                • didMove设置
                  • touchesBegan
                  • 玩家状态
                    • 着陆状态类
                      • 空闲状态类
                        • 行走状态类
                          • 眩晕状态类
                            • 约束跳跃
                              • 跳跃动画
                                • 删除并运行操作
                                  • 完成State
                                    • 默认玩家为空闲状态
                                    • positivePosition
                                    • 设置行走状态
                                    • 结论
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档