我们的第二个游戏 Lulala 是采用我修改过的 quick 2.2.3 开发的,这个项目已经完成。
Lulala 完成后,我们立项了一个新的游戏 HHL,此时我转向了 cocos2d-x lua,具体原因我在 从 quick 转向 cocos2d-x 3.3 lua 一文中做过介绍。
在 HHL 中,我本想将以前在 quick 中修改的东西,全部移到到 cocos2d-x 3.x 中来,但仔细考虑后放弃了。我修改了太多的 C++ 代码,同样的工作我不可能在 cocos2d-x 3.x 中再来做一遍。
由于 从 quick 转向 cocos2d-x 3.3 lua 中提到的痛苦经历,我现在要保证 cocos2d-x 跟随官方一起更新。我不打算再大幅修改 cocos2d-x 3.4 的 C++ 代码,否则合并 cocos2d-x 官方库一定会出问题。
因此我把以前重写过的部分全部用 lua 来实现了,例如 SpriteFrameCache 不支持异步加载、AnimationCache 支持的 plist 格式定义文件采用 lua 等等。这能保证尽量不修改 C++ 代码。
另外,filter、dragonbones 这些支持,我就将其包含在项目库中,这样 cocos2d-x 的升级和项目模块升级可以完全解耦,互不相关。
同时,我还要保证 Lulala 项目中积累起来的一套 lua 库在 cocos2d-x 3.4 中也可以正常使用。但 quick 对 cocos2d-x 的修改也比较大,很多 lua 代码是依赖相关的 quick C++ 代码的。因此,我需要把部分 quick 中的 C++ 代码也移到我的项目库中。
同时我规范了 一套文档 ,希望统一开发者的开发行为。
现在 Lulala 准备发布。这就意味着,我需要马上做出选择,是基于 quick 继续开发和维护 Lulala 项目,还是将 Lulala 项目转到 cocos2d-x 3.4。
这是个艰难的决定。最终我选择后者。
因为负责接入 SDK 的同学说 cocos2d-x 3.4 提供的插件机制能够方便他接入 facebook,而其他同学也已经习惯了 HHL 项目的工作方式,再回到 Lulala 会比较痛苦。
而更重要的原因是,我不可能同时维护两个框架。
quick 开发组的 阳光七月 多次提醒我不要升级项目。我也知道工作量会非常大,但由于上面的两个原因,不得不升级。
所以,我花了2周多时间做了这件事,移植的内容包括 cocos2d-x 框架、lua 框架以及工具链。Lulala 项目中所有的 lua 文件,我基本上都改过了。因为不是一个人开发的,每个人的写码习惯不同,我经历了各种匪夷所思的错误和莫名其妙的调用,深刻感受到了码农和程序员之间的不同。
即使我非常爱折腾,我也依然觉得这件事确实是相当浪费精力浪费生命的事情。如果团队大一点,钱多一点,我也是不愿意移植的。最多 Lulala 和 HHL 两个项目分两个团队同时做就好了嘛。到时候 Lulala 项目不赚钱了就直接扔掉。但为了能活下来,这事儿不得不做,且只能我来做。
移植工作其实已经在农历新年之前完成了。这两天我会把移植中碰到的一些问题写出来。由于经过了一个春节假期,现在年纪大了记性不好,想起来多少就写多少吧。
在 移植 quick2.2.3 的项目到 cocos2d-x 3.4 lua 中提到,我已经开始使用 cocos2d-x 3.4 lua 来开发目前公司的两个项目。
在这两个项目中,我将 cocos 的 lua 框架、quick 的 lua 框架和我自己开发的 lua 代码,全部整合到了我的 lua 项目 中。
下面提到的 quick 框架,都是指的我整合的这个 lua 项目。 问题描述
使用 cocos2d-x 3.4 lua + quick 框架进行开发的时候,发现对于销毁再重建的按钮来说,有超过 30% 的几率无法响应触摸事件。
为了方便重现问题,我使用 quick 框架提供的 cc.ui.UIPushButton 做了测试。下面这段代码中 testUIButton() 方法会创建一个按钮,每次点击这个按钮时调用 newUIButton() 方法,这个方法销毁前面创建的按钮,然后再新建一个按钮。
这个新建的按钮,相当大的几率会出现无法响应触摸事件的情况。
function TestScene:ctor()
self:testUIButton()
end
function TestScene:testUIButton()
self._bi = 0
cc.ui.UIPushButton.new('normal.jpg')
:setButtonSize(240, 60)
:onButtonClicked(function(evt)
self:newUIButton()
end)
:align(display.LEFT_CENTER, display.cx, display.cy)
:addTo(self)
end
function TestScene:newUIButton()
if self._bi > 0 then
local name = 'btn'..self._bi
self[name]:removeSelf(true)
self[name] = nil
end
self._bi = self._bi + 1
name = 'btn'..self._bi
local x = math.random(200)
local y = math.random(200)
self[name] = cc.ui.UIPushButton.new('normal.jpg')
:setButtonSize(240, 60)
:addTo(self)
:align(display.CENTER,
display.cx - x, display.cy - y)
self[name]:onButtonClicked(function()
print('--------------- test '.. name)
end)
end 问题解决
用一个很简单的方法可以解决这个问题,修改 testUIButton() 方法,将 newUIButton() 进行延迟调用即可:
sheduler 的实现在 quick 框架中可以找到。
function TestScene:testUIButton()
self._bi = 0
cc.ui.UIPushButton.new('normal.jpg')
:setButtonSize(240, 60)
:onButtonClicked(function(evt)
scheduler.performWithDelayGlobal(function()
self:newUIButton()
end, 0.1)
end)
:align(display.LEFT_CENTER, display.cx, display.cy)
:addTo(self)
end 但这是个恶心的解决方案。若想知道真正的解决方案,就要知道这个 BUG 产生的原因。 原因分析
当然,上面测试代码的实现方式也是很恶心的。在一个按钮响应事件中创建一个按钮,在真实项目中应该不会这样使用。
不过,虽然这个代码有些极端,但能更方便地重现问题。在我们的实际项目中,只要是销毁之后再重建的按钮,都有可能出现这个 BUG 。而且,不仅仅是按钮,只要是继承 Node 的对象,销毁之后再重建,都会出现这个问题。
|