列举了一些 Cocos2d-x 框架的技术备忘录,基于 Cocos2d-x v3.16 和 Lua 5.1.5。
框架架构
导演 (Director)
单例类,负责创建并管理主窗口,场景切换,暂停恢复游戏运行,游戏主循环等。例如:
1 2 3 4 5 6 Director* director = Director::getInstance(); director->runWithScene(Scene::create()); director->pushScene(Scene::create()); director->popScene(); director->replaceScene(Scene::create()); Scene* scene = director->getRunningScene();
1 2 3 4 5 6 local director = cc.Director:getInstance()director:runWithScene(cc.Scene:create ()) director:pushScene(cc.Scene:create ()) director:popScene() director:replaceScene(cc.Scene:create ()) local scene = director:getRunningScene()
挂载一些全局变量,例如: TextureCache
、Scheduler
、EventDispatcher
和 Renderer
等。
1 2 3 4 5 Director* director = Director::getInstance(); TextureCache* textureCache = director->getTextureCache(); Scheduler* scheduler = director->getScheduler(); EventDispatcher* eventDispatcher = director->getEventDispatcher(); Renderer* renderer = director->getRenderer();
1 2 3 4 local director = cc.Director:getInstance()local textureCache = director:getTextureCache()local scheduler = director:getScheduler()local eventDispatcher = director:getEventDispatcher()
其他:
设置 OpenGLView
,投影模式,视窗大小等。
设置缩放系数 contentScaleFactor
。
设置帧率 FPS :setAnimationInterval(float interval)
。
场景 (Scene)
场景中所有节点 Node
以树形结构表示,Scene
为根节点。
过渡场景:TransitionScene
。
1 2 TransitionScene* scene = TransitionScene::create(1.0 , Scene:create()); Director::getInstance()->replaceScene(scene);
1 2 local scene = cc.Scene:create ()cc.Director:getInstance():pushScene( cc.TransitionScene:create (1 , scene) )
节点 (Node)
场景图中的基础类。所有元素以此为基类。
子节点以树形结构表示,存放在 Vector<Node*> _children;
属性:位置 position
,缩放 scale
,旋转 rotation
,锚点 anchorPoint
,大小 contentSize
,可见 visible
等。
管理子节点。
1 2 3 4 5 6 7 Node* parent = Node:create(); parent->addChild(Node:create(), 1 , "child1" ); parent->addChild(Node:create(), 2 , "child2" ); Node* child1 = parent->getChildByName("child1" ); parent->removeChild(child1, true ); Node* child2 = parent->getChildByName("child2" ); child2->removeFromParent();
1 2 3 4 5 6 7 local parent = cc.Node:create ()parent:addChild(cc.Node:create (), 1 , "child1" ) parent:addChild(cc.Node:create (), 2 , "child2" ) local child1 = parent:getChildByName("child1" )parent:removeChild(child1, true ) local child2 = parent:getChildByName("child2" )child2:removeFromParent(true )
1 2 3 4 Node* node = Node:create(); Action* action = node->runAction(MoveTo::create(1.0 , Vec2(100 , 50 ))); node->stopAction(action); node->stopAllActions();
1 2 3 4 local node = cc.Node:create ()local action = node:runAction(cc.MoveTo:create (1.0 , cc.p(100 , 50 )))node:stopAction(action); node:stopAllActions();
1 2 3 4 5 6 7 8 9 10 Node* node = Node:create(); node->schedule(CC_SCHEDULE_SELECTOR(Node::update), 1.0 ); node->unschedule(CC_SCHEDULE_SELECTOR(Node::update)); node->schedule(CC_CALLBACK_1(Node::update, node), 1.0 , "update1" ); node->unschedule("update1" ); node->schedule([](float dt) { }, 1.0 , "update2" ); node->unschedule("update2" ); node->unscheduleAllCallbacks();
定时器未在 Lua 中绑定,可以使用 Scheduler:scheduleScriptFunc
方法。
1 2 3 4 5 local scheduler = cc.Director:getInstance():getScheduler()local scheduleScriptEntryID = scheduler:scheduleScriptFunc(function (dt) end , 1.0 )scheduler:unscheduleScriptEntry(scheduleScriptEntryID)
1 2 3 4 5 6 7 8 9 function Node:schedule (callback, interval) local seq = cc.sequence:create ({ cc.DelayTime:create (interval), cc.CallFunc:create (callback), }) local action = cc.RepeatForever:create (seq) self:runAction(action) return action end
精灵 (Sprite)
渲染 2d 图片。
使用文件和 spriteFrame
创建图片。
1 2 3 4 5 6 Sprite* sprite1 = Sprite::create("example.png" ); Sprite* sprite2 = Sprite::createWithSpriteFrameName("frame.png" ); SpriteFrameCache* cache = SpriteFrameCache::getInstance(); SpriteFrame* frame = cache->getSpriteFrameByName("frame.png" ); Sprite* sprite3 = Sprite::createWithSpriteFrame(frame);
1 2 3 4 5 6 local sprite1 = cc.Sprite:create ("example.png" )local sprite2 = cc.Sprite:createWithSpriteFrameName("frame.png" )local cache = cc.SpriteFrameCache:getInstance()local frame = cache:getSpriteFrameByName("frame.png" )local sprite3 = cc.Sprite:createWithSpriteFrame(frame)
设置纹理 texture
、spriteFrame
、翻转 flipX
和 flipY
等。
常见优化方式:
将图片打包在同一图集 spritesheet
。
使用同样的混合方法 blend function
。
渲染器会自动进行批量渲染,在同一个 OpenGL call
中进行。
动作 (Action) ActionInterval
常用:MoveBy
、MoveTo
、RotateBy
、RotateTo
、FadeTo
、FadeIn
、FadeOut
等。
序列 Sequence
和同步 Spawn
。
1 2 3 4 5 6 7 8 9 10 Sequence* seq = Sequence::create(MoveTo::create(1.0 , Vec2(0 , 0 )), FadeTo::create(1.0 , 0 ), NULL ); Node* node = Node::create(); node->runAction(seq); Spawn* spawn = Spawn::create(Vector<FiniteTimeAction*>{ MoveTo::create(1.0 , Vec2(0 , 0 )), FadeTo::create(1.0 , 0 )}); node->runAction(spawn);
1 2 3 4 5 6 7 8 9 10 11 12 13 local seq = cc.Sequence:create ( cc.MoveTo:create (1.0 , cc.p(0 , 0 )), cc.FadeTo:create (1.0 , 0 ) ) local node = cc.Node:create ()node:runAction(seq) local spawn = cc.Spawn:create ( { cc.MoveTo:create (1.0 , cc.p(0 , 0 )), cc.FadeTo:create (1.0 , 0 ) }) node:runAction(spawn)
重复:Repeat
和 RepeatForever
。
1 2 3 4 5 6 7 8 9 10 Sequence* seq = Sequence::create( MoveBy::create(0.5 , Vec2(100 , 0 )), MoveBy::create(0.5 , Vec2(-100 , 0 )), NULL ); Repeat* repeat = Repeat::create(seq, 3 ); Node* node = Node::create(); node->runAction(repeat); RepeatForever* repeatForever = RepeatForever::create(seq->clone()); node->runAction(repeatForever);
1 2 3 4 5 6 7 8 9 10 11 local seq = cc.Sequence:create ( { cc.MoveTo:create (0.5 , cc.p(100 , 0 )), cc.MoveTo:create (0.5 , cc.p(-100 , 0 )), }) local actionRepeat = cc.Repeat:create (seq, 3 )local node = cc.Node:create ()node:runAction(actionRepeat) local repeatForever = cc.RepeatForever:create (seq:clone())node:runAction(repeatForever)
ActionInstant
常用:Show
、Hide
、RemoveSelf
等。
回调动作:CallFunc
和 CallFuncN
。
1 2 3 4 5 6 7 8 9 10 CallFunc* callFunc = CallFunc::create([]{ }); Node* node = Node::create(); node->runAction(callFunc); CallFuncN* callFuncN = CallFuncN::create([](Node* n){ }); node->runAction(CallFuncN);
Lua 中使用了 LuaCallFunc
实现 CallFunc
。
1 2 3 4 5 local callFunc = cc.CallFunc:create (function (node) end )local node = cc.Node:create ()node:runAction(callFunc)
其他
节点动作存储在 ActionManager
中,在每帧 Scheduler::update()
时遍历更新所有节点的所有动作。
动画 帧动画 (Animate)
通过每隔一个短暂时间进行图像替代。
Animate
是动作,Animation
是存储了一组 SpriteFrame
的对象。
1 2 3 4 5 6 7 8 9 10 Animation* animation = Animation::create(); for (int i = 0 ; i < 10 ; ++i) { char tmp[50 ]; sprintf (tmp, "frame_%02d.png" , i); std ::string file = tmp; animation->addSpriteFrameWithFile(file); } Animate* animate = Animate::create(animation); Sprite* sprite = Sprite::create("frame_01.png" ); sprite->runAction(animate);
1 2 3 4 5 6 7 local animation = cc.Animation:create ()for i = 1 , 10 do animation:addSpriteFrameWithFile(string .format ("frame_%02d.png" , i)) end local animate = cc.Animate:create (animation)local sprite = cc.Sprite:create ("frame_01.png" )sprite:runAction(animate)
龙骨动画 (DragonBone)
1 2 3 4 5 6 7 dragonBones::DBCCFactory* factory = dragonBones::DBCCFactory::getInstance(); factory->loadTextureAtlas("texture.xml" ); factory->loadDragonBonesData("skeleton.xml" ); dragonBones::DBCCArmatureNode* armatureNode = factory->buildArmatureNode("armature" ); dragonBones::Animation* animation = armatureNode->getAnimation(); animation->gotoAndPlay("animation1" ); animation->gotoAndStop("animation1" , 0 );
Spine 动画
1 2 spine::SkeletonAnimation* skeletonAnimation = spine::SkeletonAnimation::createWithFile("spine.json" , "spine.atlas" ); skeletonAnimation->setAnimation(0 , "actionName" , true );
粒子特效(Particle)
1 ParticleSystem* particle = ParticleSystem::create("particle.plist" );
1 local particle = cc.ParticleSystem:create ("particle.plist" )
事件
触摸事件、键盘事件、鼠标事件、加速度传感器事件和自定义事件等。
优先级:设置优先级,层级优先级。
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 EventListenerTouchOneByOne* touchListener = EventListenerTouchOneByOne::create(); touchListener->setSwallowTouches(true ); touchListener->onTouchBegan = [&](Touch* touch, Event* event){ return true ; }; touchListener->onTouchEnded = [&](Touch* touch, Event* event){ }; EventDispatcher* eventDispatcher = Director::getInstance()->getEventDispatcher(); eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this ); EventCustom event ("eventName" ) ;eventDispatcher->dispatchEvent(&event);
1 2 3 4 5 6 7 8 9 10 11 12 13 local touchListener = cc.EventListenerTouchOneByOne:create ()touchListener:setSwallowTouches(true ) touchListener:registerScriptHandler(function (event, eventTouch) return true end , cc.Handler.EVENT_TOUCH_BEGAN)touchListener:registerScriptHandler(function (event, eventTouch) return true end , cc.Handler.EVENT_TOUCH_ENDED)local eventDispatcher = cc.Director:getInstance():getEventDispatcher()eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, self) local event = cc.EventCustom:new("eventName" )eventDispatcher:dispatchEvent(event)
文件 IO
1 2 3 4 FileUtils* fileUtils = FileUtils::getInstance(); if (fileUtils->isFileExist("example.txt" )) { string str = fileUtils->getStringFromFile("example.txt" ); }
1 2 3 4 local fileUtils = cc.FileUtils:getInstance()if fileUtils:isFileExist("example.txt" ) then local str = fileUtils:getStringFromFile("example.txt" ) end
1 2 3 4 5 local file = io .open ("example.txt" , "r" )if file then local content = file:read ("*a" ) io .close (file) end
参考链接