美文网首页
生命系统-在临死前多次受伤

生命系统-在临死前多次受伤

作者: iOSDevLog | 来源:发表于2019-02-28 18:42 被阅读4次

在本节中,我们将了解生命系统。游戏中生命系统的实现为玩家提供了多次在死亡或重置游戏之前清除等级的机会。有很多方法可以代表这个系统。您可以申请生活酒吧,或者像塞尔达的游戏一样,拥有心形。

下载生命系统

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

心形容器和心形

这个系统的布局基本上是你场景中一个不可见的矩形容器,我们将在其中插入心形。在Score分区下方,让我们声明心形容器和心形的变量。

// Hearts
var heartsArray = [SKSpriteNode]()
let heartContainer = SKSpriteNode()

heartsArray的括号表示我们正在创建一个空数组。

设置心形容器

didMove方法中,创建一个新的部门并将其命名为:Hearts。设置位置,zPosition并将心形容器添加到cameraNode。

// Hearts
heartContainer.position = CGPoint(x: -300, y: 140)
heartContainer.zPosition = 5
cameraNode?.addChild(heartContainer)

设置心形

容器已设置好。我们需要一个将心形放在容器中的功能。在Action Mark中,添加一个新函数并将其命名为:fillHearts。为心形声明一个变量并设置其位置。然后,将心形添加到心形容器中。

func fillHearts(count: Int) {
    for index in 1...count {
        let heart = SKSpriteNode(imageNamed: "heart")
        let xPosition = heart.size.width * CGFloat(index - 1)
        heart.position = CGPoint(x: xPosition, y: 0)
        heartsArray.append(heart)
        heartContainer.addChild(heart)
    }
}

didMove方法中,将心形容器添加到相机后,调用fillHearts函数并将计数值设置为3。运行模拟器,您将在屏幕的左上角看到三个美丽的心。

心形约束

让失去三颗心的玩家死亡。首先,在布尔分区中声明一个新的布尔值,并将其命名为:isHit。将其值设置为false。与接触陷阱的玩家类似,玩家一次会失去一个以上的心形,我们需要将接触限制为一个。

var isHit = false

失去了一颗心

Action Mark中,添加一个新函数并将其命名为:loseHeart。如果玩家被击中,我们将删除数组中的最后一个元素。两秒钟后,玩家不再被击中。

func loseHeart() {
    if isHit == true {
        let lastElementIndex = heartsArray.count - 1
        if heartsArray.indices.contains(lastElementIndex - 1) {
            let lastHeart = heartsArray[lastElementIndex]
            lastHeart.removeFromParent()
            heartsArray.remove(at: lastElementIndex)
            Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in
                self.isHit = false
            }
        }
    }
}

杀戮碰撞

我们需要更新玩家和杀戮对象之间的碰撞,因为我们实现了生命系统。在碰撞标记中,删除玩家与杀戮之间的碰撞内容,因为我们不希望玩家立即死亡。然后,插入loseHeart函数并将isHit设置为true。

if collision.matches(.player, .killing) {
    loseHeart()
    isHit = true
}

运行模拟器,将玩家移动到陷阱,您将看到玩家一次失去多个心形,最小上限为1。

无敌

在大多数游戏中,受伤后,玩家有两秒钟不能再被击中。我们称之为无敌状态。有很多方法可以实现无敌状态,但是到目前为止我发现的最简单的方法是改变玩家的类别掩码。在lostHeart函数之后的Action Mark中,添加一个新函数并命名为:invincible。将玩家的类别掩码设置为0.然后,将计时器设置为两秒的时间间隔,并将玩家的类别掩码设置为2。

func invincible() {
    player?.physicsBody?.categoryBitMask = 0
    Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in
        self.player?.physicsBody?.categoryBitMask = 2
    }
}

loseHeart函数内部,调用无敌函数。运行模拟器!当玩家触摸陷阱时,您将看到一次只有一颗心会消失。

垂死

在失去所有三颗心之后让我们让玩家死去。在无敌功能之后,添加一个新功能并命名为:dying。在其中,设置我们之前删除的死亡动作。然后,删除玩家上的所有操作并将fillHeart函数添加到3。

func dying() {
    let dieAction = SKAction.move(to: CGPoint(x: -300, y: 0), duration: 0.1)
    player?.run(dieAction)
    self.removeAllActions()
    fillHearts(count: 3)
}

让玩家死亡

loseHeart功能中,如果我们不能再移除心形,玩家将会死亡。所以,在heartsArrayif语句之后,放一个else并调用垂死的函数。该loseHeart功能应该是这样的:

func loseHeart() {
    if isHit == true {
        let lastElementIndex = heartsArray.count - 1
        if heartsArray.indices.contains(lastElementIndex - 1) {
            let lastHeart = heartsArray[lastElementIndex]
            lastHeart.removeFromParent()
            heartsArray.remove(at: lastElementIndex)
            Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in
                self.isHit = false
            }
        }
        else {
            dying()
        }
        invincible()
    }
}

运行模拟器,所有功能都运行正常!

无敌状态

唯一的问题是我们需要一个信号来告诉我们玩家仍处于无敌状态。在玩游戏时很难计算两秒钟的无敌状态。许多游戏在玩家身上使用闪烁的视觉效果来告诉我们玩家是无敌的,就像马里奥一样。在playerStateMachine中,在Stunned State内,声明一个新变量,将其命名为isStunned并将值设置为false。声明isValidNextState方法。如果玩家已经无敌了,他就不能再无敌。然后,添加一个switch语句,如果玩家处于空闲状态,则将该值返回true。否则,返回false。

var isStunned : Bool = false

override func isValidNextState(_ stateClass: AnyClass) -> Bool {

    if isStunned { return false }

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

闪烁效果

有许多方法可以在游戏中应用闪烁效果,最常用的方法是更改​​相关对象的alpha。在isValidNextState方法之后,创建闪烁操作并重复操作5次。

let action = SKAction.repeat(.sequence([
    .fadeAlpha(to: 0.5, duration: 0.01),
    .wait(forDuration: 0.25),
    .fadeAlpha(to: 1.0, duration: 0.01),
    .wait(forDuration: 0.25),
    ]), count: 5)

didEnter方法

Stunned ****State中,调用didEnter方法。将isStunned设置为true并在玩家上应用闪烁。放一个计时器并将isStunned设置为false。这样,玩家就不能连续多次被击晕。

override func didEnter(from previousState: GKState?) {

    isStunned = true

    playerNode.run(action)
    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { (timer) in
        self.isStunned = false
        self.stateMachine?.enter(IdleState.self)
    }
}

修复JumpingState

JumpingState中,允许玩家在被击晕时跳跃。在isValidNextState内,将值返回true。

if stateClass is StunnedState.Type { return true }

让玩家闪烁

在玩家和碰撞之间的碰撞匹配中,添加StunnedState。碰撞匹配应如下所示。

if collision.matches(.player, .killing) {

    loseHeart()
    isHit = true

    playerStateMachine.enter(StunnedState.self)
}

运行模拟器,整个生命系统现在应该正常工作!

结论

在本节中,我们学习了生命系统的工作原理。我们在游戏中实现了心形,以及如何让玩家立于不败之地。这是一个非常重要的部分,我希望你到目前为止真的很喜欢这个课程。

原文: https://designcode.io/life-system

相关文章

  • 生命系统-在临死前多次受伤

    在本节中,我们将了解生命系统。游戏中生命系统的实现为玩家提供了多次在死亡或重置游戏之前清除等级的机会。有很多方法可...

  • 你从来不需要刻意讨好谁

    生命中能留下的,从来都不需要你刻意去讨好。 生活中总会有一群这样的人:在受伤很多次之后仍然拼尽全力地去挽留那份仅存...

  • 别让生命受伤

    今天,看到一则新闻,是一个父亲狠心的将自己幼小的孩子从高处抛下。原由就不去探讨了,但是,一个父亲做的如此狠心,真...

  • 真实感受

    我知道腿脚疼痛是因为身体循环系统有问题,生命长度就是由多次体内循环累计的,哪天无法循环了,生命也就结束了。陪...

  • 疫苗的妙用

    我的左臂上有一个点状的疤,从小就有。 我一直觉得奇怪,在我的印象里,虽然受伤过很多次,每次受伤的部位也...

  • 第二章 新世界与父母

    咕咕…咕… 胃在抗议。想到临死前就吃了早餐,复活后又饿了,果然生命还是在于进食的! 纤细的手臂离开了腮帮,捂住肚子...

  • ReactNative iOS多个Modal冲突问题

    RN的modal在iOS的系统中多次调用, 会导致RCTModalHostView不能正确的移除. 系统报错202...

  • 传说———琥珀

    琥珀色,是绚烂而悲怆的离人泪。 相传,琥珀是老虎临死前的目光,在没有月亮的夜晚,在老虎临死前凝视的地方...

  • 哎呀,受伤了

    受伤,就像成长的经历一样,你的受伤可大可小,但都得经历过。我受过许多次伤,但那一次受伤却让我到现在也没有忘...

  • 原创||生命本无意,奈何深情呵护

    作者 空谷幽兰 生命是什么?生命何以存在? 童年时期在林间玩耍带回来的受伤的小鸟,那么可爱灵动,精心...

网友评论

      本文标题:生命系统-在临死前多次受伤

      本文链接:https://www.haomeiwen.com/subject/ctekuqtx.html