代码改变世界

`cocos2dx非完整` 游戏架构缩影 添加启动流程

2015-05-29 13:05  respawn  阅读(1020)  评论(0编辑  收藏  举报

这期的话题可能不是很好, 我没有想到很好的词句去更好的表达. 我一直都是很固执的认为, 同一类型的游戏,在开发做的前期工作上面其实都是可以复用的,也就是大同小异的。从游戏启动,启动日志,启动检查,检查更新,到进入游戏.这些都是那一套东西,我想把这些东西抽象一下,概括出一个叫做"流程"的概念.

我的想法就是流程是顺序执行的, 就像我喜欢画图,先做什么,然后做什么,做完什么做什么.其实从一款app启动到进入游戏,这之间的过程都是流程化进行的.还有一个很经典的例子,新手引导,其实新手引导就是一堆流程集.无论是等级引导还是顺序引导还是任务引导其实都是有顺序的.或者换一个出发点,策划在做游戏的时候,他对游戏玩家在某个时间段出于一个什么样的状态会想的很清楚,因为他就是游戏的制作者.新手引导确实很难处理,谁做过谁知道.

好吧.既然说到流程这个概念,那么为了实现这个东西,也就需要响应的引入事件调度的概念,这个用lua很容易实现.我就不费力气了,从quick直接把事件机制拿过来,稍微改了一下(请原谅我是个偏执抑郁症患者).预示就诞生了下面这个东西:

 1 --小岩<757011285@qq.com>
 2 --2015-5-27 17:05
 3 local mm = require "fw.oop.measure_mgr"
 4 local m = class("measure")
 5 
 6 function m:ctor(dispatcher, next_m)
 7     self.dispatcher_ = dispatcher
 8     self.next_m_ = next_m
 9 end
10 
11 function m:get_name()
12     return self.__cname
13 end
14 
15 function m:get_next_name()
16     return self.next_m_
17 end
18 
19 function m:launch()
20     self.dispatcher_:dispatch({
21             name   = mm.LAUNCH_M,
22             launch = self:get_name(),
23         })
24 end
25 
26 function m:finish()
27     self.dispatcher_:dispatch({
28             name   = mm.FINISH_M,
29             finish = self:get_name(),
30             forward= self:get_next_name(),
31         })
32 end
33 
34 function m:remove()
35     self.dispatcher_:dispatch({
36             name  = mm.REMOVE_M,
37             remove = self:get_name(),        
38         })
39 end
40 
41 function m:onlaunch()
42 end
43 
44 function m:onfinish()
45 end
46 
47 function m:onremove()
48 end
49 
50 return m

 

 1 --小岩<757011285@qq.com>
 2 --2015-5-27 17:05
 3 local proxy = require "fw.framework.proxy"
 4 local mm = class("measure_mgr")
 5 
 6 mm.LAUNCH_M = "LAUNCH_MEASURE"
 7 mm.FINISH_M = "FINISH_MEASURE"
 8 mm.REMOVE_M = "REMOVE_MEASURE"
 9 mm.TAG      = "MEASUREMGR_TAG"
10 
11 function mm:ctor(dispatcher)
12     self.proxy_ = proxy.new(dispatcher)
13     self.measures_ = {}
14     self.proxy_:add_listener(mm.LAUNCH_M, 
15                     function(e)
16                         self:onlaunch_m(e) 
17                     end, mm.TAG)
18                :add_listener(mm.FINISH_M, 
19                        function(e)
20                            self:onfinish_m(e)
21                        end, mm.TAG)
22                :add_listener(mm.REMOVE_M, 
23                        function(e)
24                            self:onremove_m(e)
25                        end, mm.TAG)
26 end
27 
28 function mm:register_measure(m)
29     local m_name = string.upper(m:get_name())
30     if not self.measures_[m_name] then
31         self.measures_[m_name] = m
32     end
33 end
34 
35 function mm:remove_measure_by_name(name)
36     name = string.upper(tostring(name))
37     if self.measures_[name] then
38         self.measures_[name]:onremove()
39         self.measures_[name] = nil
40     end
41 end
42 
43 function mm:launch_measure_by_name(name)
44     name = string.upper(tostring(name))
45     if self.measures_[name] then
46         self.measures_[name]:onlaunch()
47     end
48 end
49 
50 function mm:finish_measure_by_name(name)
51     name = string.upper(tostring(name))
52     if self.measures_[name] then
53         self.measures_[name]:onfinish()
54     end
55 end
56 
57 function mm:onlaunch_m(e)
58     self:launch_measure_by_name(e.launch)
59 end
60 
61 function mm:onfinish_m(e)
62     self:finish_measure_by_name(e.finish)
63     local next_m = e.forward
64     if next_m then
65         self:launch_measure_by_name(next_m)
66     end
67 end
68 
69 function mm:onremove_m(e)
70     self:remove_measure_by_name(e.remove)
71 end
72 
73 function mm:destroy()
74     self.proxy_:remove_all_listeners()
75     self.measures_ = {}
76 end
77 
78 return mm

 

上面也是看到了我给流程封装了finish(), remove(), launch()方法. 为了更彻底的贯彻流程的概念, 我索性也将启动部分的代码做了一点简单的封装.

 1 --小岩<757011285@qq.com>
 2 --2015-5-27 17:27
 3 local ij = require "fw.framework.inject"
 4 local mm = require "fw.oop.measure_mgr"
 5 local app = class("app")
 6 
 7 function app:ctor()
 8     self.dispatcher_ = ij.inject({}):add_component("fw.framework.dispatch")
 9     self.m_mgr_ = mm.new(self.dispatcher_)
10     self.entrance_m_ = nil
11 end
12 
13 function app:get_dispatcher()
14     return self.dispatcher_
15 end
16 
17 function app:start()
18     if not self.entrance_m_ then
19         error("pls set entrance measure before start()!")
20     end
21 
22     self.entrance_m_:launch()
23 end
24 
25 function app:register_game_measure(m)
26     if not self.entrance_m_ then
27         self.entrance_m_ = m
28     end
29     self.m_mgr_:register_measure(m)
30 end
31 
32 function app:destroy()
33     self.m_mgr_:destroy()
34 end
35 
36 function app:exit()
37     cc.Director:getInstance():endToLua()
38 end
39 
40 return app

 

默认会从第一个开始启动进入, 然后依次执行注册的流程.具体的例子我可以给一个.

 1 --小岩<757011285@qq.com>
 2 --2015-5-27 17:39
 3 local clm = require "game.measure.check_log"
 4 local cem = require "game.measure.check_env"
 5 local cum = require "game.measure.check_update"
 6 
 7 local application = class("application", fw.app)
 8 
 9 function application:ctor()
10     application.super.ctor(self)
11 end
12 
13 function application:run()
14     self:register_game_measure(clm.new(self:get_dispatcher(), cem.__cname))
15     self:register_game_measure(cem.new(self:get_dispatcher(), cum.__cname))
16     self:register_game_measure(cum.new(self:get_dispatcher()))
17     self:start()
18 end
19 
20 return application

 

目前的代码, 我只是写到了增量更新,所以我注册了三条流程.

 -- check_log_measure 启动app运行日志.

 -- check_env_measure 启动检查环境设置 

--  check_update_measure 启动增量更新.

下面如果再添加流程应该就是进入游戏的流程了.

这样做再某些方面显得很呆板, 将一些简单的事情做的有点复杂了. 但是是有一个好处的, 那就是我们的架构设计开始出现模式化的代码了. 模式化很重要, 模式化是统一的前提. 在没有做到模式化之前, 一味的强调各种统一风格的事情就是扯淡,很难做得到.就像以前我遇到过一位主程, 每天就只会强调代码格式, 注释格式的问题, 基础的功能代码并不能提供. 我不知道这么做的意义何在. 这里只是突然想到了, 顺手吐槽一下.

 

这里说一句抱歉, 原本计划这一篇写增量更新的. 现在看来要延后了, 这里绝对不是因为技术问题. 我昨天就写好了, 今早起床也是将android包打出来测试通过了.是因为直接跳到更新那边忽略了中间太多的东西了,我想穿插一些文章来说明一下这些问题. 懂的人不需要多说,对于那些渴望学习的人, 我啰嗦一点就罗嗦一点了, 但是能解答他们的问题或者是有一点启示, 就是最好的事情了.