您的位置:首页 > 编程语言 > Lua

【游戏_忍者六道】状态机设计与应用之lua篇

2016-09-04 12:39 239 查看

一 前言

上一篇图文描述了C++实现游戏中应用的状态机,C++中的三大特性:封装,继承,多态得以应用,封装数据引擎访问的增,删,查,改,状态机基类以及多种状态子类实现私有private或者公共public继承它,但是发挥更大的作用是多态的使用,子类继承实现基类的virtual虚函数,在不同的事件机制触发下,迁移变换执行不同的状态,虽然毫无标准顺序可言,却是按照指定规则轨道正确行使,这是状态机设计的正确使用的最妙之处,起码是当前使用是这样,不同的需求会设计出不同高效的状态机。

那么,lua在状态机方面是如何应用的呢?

众所周知,lua是游戏开发中效率颇高的脚本语言,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua脚本可以很容易的被C/C++代码调用,也可以反过来调用C/C++的函数。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,ini等文件格式,并且更容易理解和维护。在目前所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。现在很多游戏(无论手游,还是端游),都为它的强大所折服,ps和魔兽都有使用lua,不得不承认,lua这方面做得确实很不错,虽然lua是面向过程和函数式编程,但是它的闭包和table特性使得它像C++一样,很完美的实现OO——面向对象。

二 状态机实现

这里简单的说下一个游戏中,lua脚本实现一个功能的场景:



举个栗子,这是十一的活动,很多游戏会选择在传统佳节,做一些活动,引起玩家的关注和参与,从而赢得访问和流量,十一活动流程很简单,玩家登陆游戏客户端之后,如果当前时间不到十月一日,那么就不会有一些玩法的Npc或者图标之类,会选择玩其他的一些活动或者打怪,即使如此,此时已经处在设计的状态机中了,只是当前为“检查活动开启状态”,这就有点像,不知不觉就进来套路一样;当时间到来时,一般活动开始事件会设置为:2016年10月1日00:00:00,不得有丝毫时间的马虎,那么自然可以想到,结束时间为:2016年年10月5日24点了。

lua语法中,使用table存储数据,我们在StateManagerByLua在活动开始时,事先new调用构造函数,使用tCurrentState的一个table将EDoing_Sate(进行状态)和ECheckStart_Start(检查是否开始状态)作为Key,存储AstateByLua,BstateByLua…状态的对象。

在此活动自然会在“进行状态”,发布活动开始的一些广播抑或一些邮件通知User知道,BginTime=< NowTime

tCurrentState[EDoing_Sate] = AstateByLua:new{ p_Object = self}


两种状态被存储下来之后,时间的检查需要使用timer定时器,可以自己封装相关的定时器和相关回调,当时间到达10.1,那么活动开始了,此时开始的状态可以参看如下用例:



品尝到十一活动的乐趣之后,可不曾晓得,事件过得会如此之快,升级的也升了,高级装备也拿了,钱也赚了,活动时间>10.5到0点就End了,npc或者活动图标就会随之消失。

三 lua源码实现状态机

状态机类图先睹为快:



下面简单写一些此次活动的代码结构:

----------------------------------------
--- Title: 管理器相关   StateManagerByLua
--- desc: 负责 管理各种状态
---------------------------------------
//管理器属性
StateManagerByLua = new{
m_CurrentState = nil,// 当前状态
tCurrentState = {},  //存储所有状态的table
}

// 管理器 构造
// dest: 将所有状态都存储起来
function StateManagerByLua:ManagerConstructor()
tCurrentState[EA_Sate] = AstateByLua:new{ p_Object = self}
tCurrentState[EB_Sate] = BstateByLua:new{ p_Object = self}
...
end

// 状态切换
function StateManagerByLua:GotoState(nState)
// 离开当前状态
...
self.m_CurrentState:LeaveState()
...
// 进入其他状态
self.m_CurrentState = tCurrentState[nState]
self.m_CurrentState:EnterState()
end

// 检测活动是否开启
function StateManagerByLua:CheckState()
if 10.1 =< time and time < 10.5 then
self:GotoState(EBeginState)// 进入开始状态
else
self:GotoState(ECheckActivityState) // 进入检测状态
end
end


由此,可清晰的解构出,活动管理其实并没有那么复杂,manager耦合各个状态对象和自身属性,发挥着重要作用。

接下来看看开始状态的代码结构:

---------------------------------------
-- Title:活动开始状态
-- desc:活动开启 - 事件xxx- 做法xxx-
----------------------------------------
BeginState = new{
m_pobj = nil, // 访问管理器属性
...
}

// 进入活动开始状态
function BeginState:EnterState()
...
//打怪
//领取奖励
// 自定义活动逻辑
...
end

//离开状态
function  BeginState:LeaveState()
...
end


so, 结束状态也是同理,自己可以合理安排各个状态所需的逻辑和玩法,异曲同工。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  游戏 设计 lua