从零开始的8-bit迷宫探险【Level 18】为什麽他们开始乱跑?捉摸不定的怪物移动模式

「诶,好累喔。」
「天气这麽好,要不要去玩水啊?」喜欢玩耍的 Snow 提议着。
忘记要赶走山姆的使命感,四个可爱的反派角色跑走了!?
黑森林的天气,又渐渐晴朗起来。

今日目标

  • 新增不同的移动模式:玩耍模式 (不再以主角为追踪目标)
  • 游戏开始後,取得一个随机时间,启动玩耍模式

PS. 这里是开发 iOS 手机游戏的系列文,如果还没看过之前 剧情 文章的朋友,欢迎先点这边回顾唷!


设定模式

  • 新增 setMode 方法:
    • 可让外部呼叫并带入 mode 参数,调整该怪物当前的移动模式
    • 呼叫 updateMode 方法,更新当前模式设定
    • 呼叫 playAnimation,设定当前模式下的图片序列图动画 (目前玩耍模式不会改变怪物样貌)
  • 调整 updateMode 方法:
    • 新增 .PLAY case,设定他的目标点为 gridMapping.lakeCorner.xgridMapping.lakeCorner.y
    • 移动速度:这边我们也可以让不同模式的移动速度有些差异,分别在 .ATTACK.PLAY case 中设定 moveInterval 的值,让攻击时的移动速度较快,而玩耍时的移动速度较慢
  • Weather.swift
class Weather: GameCharacter, Move {
    ...
    func setMode(mode: Mode) {
        self.mode = mode
        self.updateMode()
        self.playAnimation(imageName: "\(self.mode.getImage(role: self.role))_\(self.direction.rawValue)", num: 2)
    }
    func updateMode() {
        switch mode {
        case .ATTACK:
            ...
            self.moveInterval = 0.3
        case .PLAY:
            self.setTarget(targetX: gridMapping.lakeCorner.x, targetY: gridMapping.lakeCorner.y)
            self.moveInterval = 0.4
        default:
            break
        }
    }
}

Timer

设定在随机的一段时间後,让怪物们进入玩耍模式,玩耍模式维持 10 秒後,再让怪物回复到攻击模式

启动 Timer,进入玩耍模式

  • 使用 Int.random(in:) 随机取得 10 到 50 的整数
  • 使用 scheduledTimer 新增一个 Timer:
    • timeInterval:带入我们取得的随机秒数
    • selector:带入要执行的方法 attackToPlayModeAction,将会在 timeInterval 秒数後执行
    • repeats:false 不重复执行
  • 玩耍模式 attackToPlayModeAction
    • 将所有的怪物模式设定为玩耍模式 setMode(mode: .PLAY)

启动 Timer,回到攻击模式

  • attackToPlayModeAction
    • 设定另一个 Timer playModeTimer,让玩耍模式维持 10 秒後,执行回到攻击模式方法 palyToAttackModeAction
  • 回到攻击模式 palyToAttackModeAction
    • 将所有的怪物模式设定为攻击模式 setMode(mode: .ATTACK)

停止 Timer

启动了 Timer 後,为了避免 Timer 还没结束时就离开游戏画面,而 Timer 还在继续倒数的问题,我们在离开场景时要停止 Timer

  • 新增 stopTimer 方法,使用 invalidate() 停止 timer
  • 在场景将要被移除时 willMove(from: SKView),呼叫 stopTimer
  • GameScene.swift
class GameScene: SKScene {
    ...
    var randomTimer: Timer? = nil
    var playModeTimer: Timer? = nil
    
    override func didMove(to view: SKView) {
        ...
        let randomTime = Int.random(in: 10...50)
        self.randomTimer = Timer.scheduledTimer(timeInterval: TimeInterval(randomTime), target: self, selector: #selector(attackToPlayModeAction), userInfo: nil, repeats: false)
    }
    ...
    // 攻击->玩耍
    @objc func attackToPlayModeAction() {
        print("玩耍中")
        self.randomTimer = nil
        self.playModeTimer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(palyToAttackModeAction), userInfo: nil, repeats: false)
        for weather in self.weathers {
            if weather.mode == .ATTACK {
                weather.setMode(mode: .PLAY)
            }
        }
    }
    
    // 玩耍->攻击
    @objc func palyToAttackModeAction() {
        print("不玩了")
        self.playModeTimer = nil
        for weather in self.weathers {
            if weather.mode == .PLAY {
                weather.setMode(mode: .ATTACK)
            }
        }
    }
    
    func stopTimer() {
        if let randomTimer = self.randomTimer {
            randomTimer.invalidate()
            self.randomTimer = nil
        }
        if let playModeTimer = self.playModeTimer {
            playModeTimer.invalidate()
            self.playModeTimer = nil
        }
    }
    
    override func willMove(from: SKView) {
        self.stopTimer()
    }
}

执行结果

可以观察到,经过一段时间後,怪物突然移动变得较慢,且目标点变成湖边,并且渐渐移动过去,10秒後又回到攻击模式,蓝色的 Rain 又开始往主角追击

https://imgur.com/ut7WQf7.gif


今日小结

怪物追击主角的移动路径跟模式,到今天就会稍微告一个段落罗!
大家可以再自由发挥,加入其他有趣的模式让移动路径更难以捉摸。
之後会有专门讲解主角反击怪物的章节,请敬请期待~


参考来源:
random(in:)
scheduledTimer


<<:  Day11 Let's ODOO: Controller

>>:  #11 Pandas教学3

Day22-生命周期

前言 这几天我们已经学习了Props外来传递资料,还有State组件本身状态。 今天要来学习很重要的...

Windows Server IIS 如何安装 PHP 网页服务器

PHP 是众多网页开发者所使用的程序语言,想要快速学习网页程序语言的话,PHP 是值得推荐的选择。 ...

【Day28】Git 版本控制 - GitBook 简介

今天来介绍一个酷东西:GitBook 图片取自 GitBook 官网 GitBook GitBook...

[Day05] Tableau 轻松学 - Tableau 授权类型

前言 安全且有系统地使用一套软件的前提,是先了解其授权机制与权限范围,知道自己的角色可以做到什麽事与...

【额外分享】How To Test The Smart Contract Of iParking NFT With Foundry

tags: swfLAB ⚠️ Of course this is only my personal...