我们作个比方,场景好比舞台的一幕,models下的类相当于剧本中的角色(注意只是剧本中的),是死的,并没有被演活,那么精灵就好比一个个地演员,把角色演活。
因此虫子类仅仅是类,虫子精灵负责按照虫子类描述的特性执行其动作。
但是这个demo项目在这方面处理得相当蹩脚,且容我整理后再梳理清楚。这一节主要是优化GameView和虫子类以及虫子精灵的分工。
逻辑层应当只负责宏观的逻辑执行,它最好不要去涉及到具体某些类或对象的初始化逻辑,特别是“角色”众多时应该用类来统一管理,然后派生类各自实现自己不同的地方,逻辑层只负责调用它们的公共接口或函数即可。
遵循这个原则,最后把虫子基类、蚂蚁类、蜘蛛类优化为如下(原始代码不再作分析,因为太混乱,难以梳理):
虫子基类:
local BugBase = class("BugBase")
function BugBase:ctor() self.name = nil imageFileName = position_ = cc.p(0,0) rotation_ = 0 dist_ = destination_ = speed_ = 1 touchRange_ = animationTimes_ = nil end
getName() if name==nil then printError('uninit name') return name getImageFileName() imageFileName=='uninit imageFileName') imageFileName getPosition() return position_ getRotation() rotation_ getDist() dist_ getAnimationTimes() animationTimes_=='uninit animationTimes_') animationTimes_ setDestination(destination) clone(dist_ = math.random(display.width / 2 + 100,200)
rotation = random(360) position_ = self:calcPosition(rotation,dist_,153)">rotation - 180 self fixedDeltaTime = 1.0 / 60.0 step(dt) dist_ = dist_ - speed_ * (dt / fixedDeltaTime) calcPosition(rotation_ + 180,43)">destination_) rotation,255)">dist,255)">destination) radians = rotation * pi / return cc.p(destination.x + math.cos(radians) * dist, destination.y - math.sin(radians) * dist) checkTouch(x,255)">y) dx,153)">dy = x - position_.x,255)">y - y offset = sqrt(dx * dx + dy * dy) return offset <= touchRange_ BugBase
优化之处:
去掉了虫子类型,有了派生类干嘛还用枚举来区分不同的类?神经病一样,典型的C语言思想,没有把类好好利用好。
增加了私有变量:name(虽然源码里面没有使用,但是看起来会舒服清晰很多),imageFileName(用于指示该类的图片资源),animationTimes_(动画延迟时间),并分别为它们设定了对应的get函数。
蚂蚁类:
import(".BugBase")
BugAnt = "BugAnt",153)">BugBase)
BugAnt:ctor() BugAnt.super.ctor(self) name = 'BugAnt' imageFileName = 'BugAnt.png' 1.0 70 animationTimes_ = 0.15 BugAnt
蜘蛛类:
BugSpider = "BugSpider",153)">BugSpider:ctor() BugSpider.'BugSpider' 'BugSpider.png' 1.5 50 0.1 BugSpider
派生类各自在自己的构造函数中初始化自己的数据,什么?担心会忘记设置?因此在基类的构造函数中把这几个私有变量初始化为nil,并在对应的get函数中进行判断,如果没有被初始化过则输出错误信息,基类的作用就是为派生类制造规范的行为准则,一切就这么简单方便!
接下来是虫子精灵和虫子死亡精灵:
虫子精灵: BugSprite = "BugSprite",128)">function(bugObj) imageFileName = bugObj:texture = getImage(imageFileName) if texture==loadImage( local frameWidth = texture:getPixelsWide() / 3 frameHeight = getPixelsHigh()
spriteFrame = newSpriteFrame(texture,43)">rect(frameWidth,153)">frameHeight)) sprite = newSprite(spriteFrame) sprite.animationName_ = imageFileName sprite.frameWidth_ = frameWidth frameHeight_ = frameHeight
--判断动画是否已经缓存,如果没有则创建 if getAnimationCache(animationName_)==-- create sprite frame based on image frames = {} for i = 1 do frame = frameWidth * i,153)">frames[#frames + 1] = frame -- create animation animation = newAnimation(frames,43)">getAnimationTimes()) -- caching animation setAnimationCache(animationName_,153)">animation) return sprite end)
BugSprite:bugObj) model_ = bugObj getModel() model_ start(model_:updatePosition() playAnimationForever(getAnimationCache(animationName_)) updatePosition() move(getPosition()) :rotate(getRotation()) BugSprite
虫子死亡精灵:
DeadBugSprite = "DeadBugSprite",43)">getImage(getImageFileName()) getPixelsHigh() 2,128)">return display.newSprite(spriteFrame) DeadBugSprite
这里一并分析说明,原始的逻辑是GameView里面告诉虫子精灵和死亡虫子精灵初始化的资源文件在哪里并如何初始化,神经病一样!正确的做法是:演员自己去看剧本,自行初始化自己的资源,因此这里优化后的虫子精灵只需通过虫子基类的get函数来获取对应的资源进行初始化即可。
这里需要注意的是:
end
一开始是getImage是为nil的,只需要调用loadImage加载一次即可,后面的精灵对象便可以使用getImage获取了。死亡虫子精灵获取资源时也应该这样,但是由于死亡虫子精灵和虫子精灵使用的资源是同一个图片,因此前面加载过了这里就可以直接使用了,这里对资源的操作暂时不做修改了。
死亡虫子精灵和虫子精灵的类初始化函数(暂时这么叫吧,以便于区分后面的构造函数)由原来的接受资源文件名改为直接接受虫子对象,然后通过get函数来获取它们具体的资源文件名,这样清晰多了。那么GameView的初始化就变得相当简单了,我们看看原来GameView是如何添加虫子和虫子精灵的:
GameView:addBug() bugType = BugBase.BUG_TYPE_ANT 1,255)">2) % 2 == 0 BUG_TYPE_SPIDER bugModel bugType == BUG_TYPE_ANT bugModel = BugAnt:create() else bugModel = BugSpider:bug = BugSprite:create(GameView.IMAGE_FILENAMES[bugType],153)">bugModel) :start(GameView.HOLE_POSITION) :addTo(bugsNode_,GameView.ZORDER_BUG)
bugs_[bug] = bug end 再看看优化后的:
bugClass = {BugAnt,BugSpider} index = bugClass) bugObj = bugClass[index]:create()
create(bugObj) :HOLE_POSITION) :end 打个比方,好比现在这一幕剧情需要一群群众演员,导演的要求是这些群众演员随机出现即可,只需要演员各自扮演好即可。这里,有多少虫子类就添加多少个,这里就是蚂蚁和蜘蛛,把它们放在一个数组里,然后随机选取一个让虫子精灵表演,虫子精灵由于已经被我们优化为了只接受一个虫子对象,它内部会调用虫子的get函数获取资源信息进行初始化,也就是演员各自表演好自己的角色。
优化去掉了GameView的onCreate函数中对资源的初始化过程:
-- create animation for bugs bugType,153)">filename in pairs(GameView.IMAGE_FILENAMES) -- load image filename) getPixelsHigh()
BUG_ANIMATION_TIMES[bugType]) filename,128)">end
上面一段代码直接删除,还可以删除的部分:
BugBase = "..models.BugBase")
GameView.IMAGE_FILENAMES = {} BugBase.BUG_TYPE_ANT] = "BugAnt.png" BUG_TYPE_SPIDER] = "BugSpider.png"
BUG_ANIMATION_TIMES = {} 0.15 0.1 经过以上梳理,现在的逻辑和流程清晰多了,下一节开始MOD成红警塔防游戏。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|