状态机在quick中是一个亮点,如果我们做一款RPG游戏,一个角色一般会拥有idle,attack,walk,run,death这些状态,如果游戏角色的状态采用分支条件判断的话,会造成非常庞大而难以维护,但一旦使用了状态机这种模式,就会显得简单方便。

对于quick中的状态机是如何实现的咱们先不去了解,首先看看如何去使用它。

总结起来,如果让一个类拥有状态机,主要有两步:

1.创建状态机对象

2.初始化状态机,主要包括事件和回调函数

1.创建状态机组件

self.fsm = {}
cc.GameObject.extend(self.fsm):addComponent("components.behavior.StateMachine"):exportMethods()

这样就创建了一个状态机对象,接下来我们要对其初始化,其实也就是设置各个状态的逻辑。

2.初始化状态机(设置状态逻辑)

设置状态逻辑是重写setupState方法,这其中有这么几个字段参数,

  • initial:状态机的初始状态
  • terminal (final):结束状态
  • events:状态发生转变时对应的事件
  • callbacks:发生转变时的回调函数

一般我们会设置initial,events和callbacks这三个。

先看events,在events中需要分清楚“事件”和“状态”,events采用table结构,例如我们来写一个

events = {{name = "move", from = {"idle", "jump"}, to = "walk"},
}

这其中move是事件,就像触摸事件event.name那样,name表示事件名称,而from和to后面跟的idle,jump,walk表示状态。所以上面的意思就是,当执行move事件时,如果状态是idle或者jump,那么都会跳转到walk状态上。

from的状态可以是单一状态,也可以使集合状态,就是几个状态,但to的状态只能唯一,不然程序还给你来个随机状态?肯定不行的。

所以这里需要想好我们的主角有哪些状态,当什么事件发生时,他会从什么状态变到什么状态上去。例如我简单这么写,

events = {{name = "move", from = {"idle", "jump"}, to = "walk"},{name = "attack", from = {"idle", "walk"}, to = "jump"},{name = "normal", from = {"walk", "jump"}, to = "idle"},
},

解释一下,如果是normal事件,不管主角在走路walk还是跳跃jump,都会变成闲置idle状态。其他同理。

接下来一个重点是callbacks参数,

即所谓回调了,就是事件触发,会执行一系列的函数。

  • onbeforeEVNET: 在事件EVENT开始前被激活
  • onleaveSTATE: 在离开旧状态STATE时被激活
  • onenterSTATE 或 onSTATE:在进入新状态STATE时被激活
  • onafterEVENT 或 onEVENT:在事件EVENT结束后被激活

例如

callbacks = {onenteridle = function ()  --或者 onidleprint("idle")end,
},

此外还有5种通用型的回调来捕获所有事件和状态的变化:

  • onbeforeevent: 在任何事件开始前被激活
  • onleavestate: 在离开任何状态时被激活
  • onenterstate:在进入任何状态时被激活
  • onafterevent :在任何事件结束后被激活
  • onchangestate :当状态发生改变的时候被激活
这里面的名称是不可以修改的,它是针对于任何事件和任何状态的。
所以大家可以想象一下这其中有多少事件回调和多少状态回调,它们的先后顺序,咱们可以自己分别print一下就知道调用的先后了,这里就不演示了。
最后,就是调用这些事件了,通过self.fsm:doEvent(event)就可以了,参数event对应events参数名称。此外还有这些,
  • fsm:isReady() :返回状态机是否就绪
  • fsm:getState() :返回当前状态
  • fsm:isState(state) :判断当前状态是否是参数state状态
  • fsm:canDoEvent(eventName) :当前状态如果能完成eventName对应的event的状态转换,则返回true
  • fsm:cannotDoEvent(eventName) :当前状态如果不能完成eventName对应的event的状态转换,则返回true
  • fsm:isFinishedState() :当前状态如果是最终状态,则返回true
  • fsm:doEventForce(name, ...) :强制对当前状态进行转换
接下来在实际运用一下,我们创建一个Player类,为其添加一个状态机,
local Player = class("Player", function ()return display.newSprite("icon.png")
end)function Player:ctor()self:addStateMachine()
endfunction Player:doEvent(event)self.fsm:doEvent(event)
endfunction Player:addStateMachine()self.fsm = {}cc.GameObject.extend(self.fsm):addComponent("components.behavior.StateMachine"):exportMethods()self.fsm:setupState({initial = "idle",events = {{name = "move", from = {"idle", "jump"}, to = "walk"},{name = "attack", from = {"idle", "walk"}, to = "jump"},{name = "normal", from = {"walk", "jump"}, to = "idle"},},callbacks = {onenteridle = function ()local scale = CCScaleBy:create(0.2, 1.2)self:runAction(CCRepeat:create(transition.sequence({scale, scale:reverse()}), 2))end,onenterwalk = function ()local move = CCMoveBy:create(0.2, ccp(100, 0))self:runAction(CCRepeat:create(transition.sequence({move, move:reverse()}), 2))end,onenterjump = function ()local jump = CCJumpBy:create(0.5, ccp(0, 0), 100, 2)self:runAction(jump)end,},})
endreturn Player

比较简单,回调函数只是写了进入三个状态的回调,然后为Player添加一个doEvent函数,调用状态机中doEvent。

回到我们的MyScene.lua中,
local Player = import("..views.Player")local MyScene = class("MyScene", function ()return display.newScene("MyScene")
end)function MyScene:ctor() local player = Player.new()player:setPosition(display.cx, display.cy)self:addChild(player)local function menuCallback(tag)if tag == 1 then player:doEvent("normal")elseif tag == 2 thenplayer:doEvent("move")elseif tag == 3 thenplayer:doEvent("attack")endendlocal mormalItem = ui.newTTFLabelMenuItem({text = "normal", x = display.width*0.3, y = display.height*0.2, listener = menuCallback, tag = 1})local moveItem =  ui.newTTFLabelMenuItem({text = "move", x = display.width*0.5, y = display.height*0.2, listener = menuCallback, tag = 2})local attackItem =  ui.newTTFLabelMenuItem({text = "attack", x = display.width*0.7, y = display.height*0.2, listener = menuCallback, tag = 3})local menu = ui.newMenu({mormalItem, moveItem, attackItem})self:addChild(menu)endreturn MyScene

添加我们刚才的Player,记得import或者require,这里为了方便我就通过菜单按钮的形式来分别doEvent了。

quick-cocos2d-x游戏开发【14】——StateMachine状态机相关推荐

  1. iOS cocos2d 2游戏开发实战(第3版)

    <iOS cocos2d 2游戏开发实战(第3版)> 基本信息 原书名:Learn cocos2d 2: Game Development for iOS 作者: (美)Steffen I ...

  2. 《Cocos2d 跨平台游戏开发指南(第2版)》一1.9 添加动作到精灵

    本节书摘来异步社区<Cocos2d 跨平台游戏开发指南(第2版)>一书中的第1章,第1.9节,作者: [印度]Siddharth Shekar(谢卡)译者: 武传海 责编: 胡俊英,更多章 ...

  3. iOS cocos2d 2游戏开发实战(第3版)---你的第一个游戏!

    2019独角兽企业重金招聘Python工程师标准>>> 随着苹果公司不断地创新与发展,新的iPhone 5.iPad 4以及iPad mini产品相继问世,包括iOS与Xcode在内 ...

  4. 【通知】▁▂▃ Himi 最新著作《iOS游戏编程之从零开始—Cocos2d-x与cocos2d引擎游戏开发》★书籍源码+第4/5/6样章★-免费下载★ ▃▂▁

    2013年新年,Himi的第二本著作:<iOS游戏编程之从零开始-Cocos2d-x与cocos2d引擎游戏开发>一书正式发售: (大家可以到新华书店.淘宝.拍拍.当当.亚马逊等进行购买) ...

  5. Cocos2D手机游戏开发之优化篇

    Cocos2D手机游戏开发之优化篇 在这个手机游戏盛行已久的年代,一款产品想要博得更多用户的喜爱就要在细节上做得更加到位.而游戏的优化在这里面起到了非常关键的作用.试想下,一款画面和玩法都深受用户喜欢 ...

  6. 添加类iOS cocos2d 2游戏开发实战(第3版)

    这两天一直在学习添加类之类的问题,现在正好有机会和大家讨论一下. 第1章 简介 1 1.1 第3版中的新增内容 2 1.2 选择ios版cocos2d的来由 3 1.2.1 收费 3 1.2.2 开源 ...

  7. unity游戏开发-简易的状态机

    本篇主要分享一个简易状态机的实现. 目录 状态机 应用例子 业务需求 普通实现 缺点分析 状态机实现 优点分析 状态机 简单点讲状态机其实就是将一个具体的业务拆分为几个小的状态,状态之间由一定的条件来 ...

  8. Cocos2d手机游戏开发-黄金矿工梦西游手机游戏

    开发环境: Cocos2d-X v2.2.x 下载地址: http://www.taomadao.com/thread-46-1-1.html 转载于:https://my.oschina.net/u ...

  9. cocos2d x游戏开发系列教程 中国象棋01 工程文件概述

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 上一篇博 ...

  10. 趣说游戏AI开发:对状态机的褒扬和批判

    0x00 前言 因为临近年关工作繁忙,已经有一段时间没有更新博客了.到了元旦终于有时间来写点东西,既是积累也是分享.如题目所示,本文要来聊一聊在游戏开发中经常会涉及到的话题--游戏AI.设计游戏AI的 ...

最新文章

  1. 深度学习必懂的13种概率分布
  2. SQL逻辑查询语句执行顺序
  3. faster-rcnn移植过程中出现错误
  4. spark2.0.1 安装配置
  5. ironpython3发布时间_.NET 基金会项目介绍-DLR/IronPython2/IronPython3
  6. 新疆特岗计算机考试题,2020新疆特岗教师笔试资料领取(小学信息技术)
  7. 3.1 神经网络概览
  8. 隔离存取空间IsolatedStorage【WP7学习札记之十】
  9. Javascript ES6 Promise同步读取文件(使用async、await)
  10. 16进制 dat matlab_MATLAB中的常量与变量
  11. 多View统一Camera v1.2
  12. [SUCTF 2019]EasyWeb
  13. Qt Creator编辑3D场景
  14. 检验样本是否服从泊松分布
  15. tl r4238 虚拟服务器,TL-R4238快速安装设置指南图文教程
  16. 邮件个性签名html,iphone发邮件添加个性签名方法
  17. preHandle执行多次问题
  18. 【MFC】基于OpenCV的魔镜
  19. manifest.json
  20. 常用JS效果 需要时更新。。。

热门文章

  1. 【重读经典】《Python核心编程(第3版)》
  2. 剑侠情缘(网络版)---开发回顾(一篇老文章,看看也不错)
  3. vue run build 错误 CssSyntaxError错误
  4. SVN本地目录创建及使用
  5. LeetCode算法 删除有序数组中的重复项 删除有序数组中的重复项|| C++
  6. USB HID读卡器 M1卡读卡器 Mifare 读写器 NFC方案 NFC读写器方案 usb 接口NFC读写器 ISO14444 TypeA 协议读写器 S50/S70 usb读写器 提供Demo
  7. 懒人精灵(一款类似按键精灵的工具)制作和使用C/C++编写的插件
  8. 如何利用 Blender GIS 制作三维地形
  9. Proteus软件下载安装(包含win10安装proteus8.0+报错问题解决)
  10. mysql workbench8.0关键词大写_Mysql从入门到精通全文整理