cocos2d-x初探

自己挖的坑,含着泪也要填上——Eidosper
 
很多年前就听大牛们说,cocos2d这个引擎写的有点乱,现在有点体会了。
 
首先上官网——没有什么卵用,教程给的都是比较弱鸡。
 
先不吐槽了。
 
1 安装
 
先去官网下载:http://www.cocos2d-x.org/download
最左边那个,或者:
 $ git clone https://github.com/cocos2d/cocos2d-x.git
用terminal或者cmd(win下推荐powershell貌似那玩意儿才带git)切换到一个目录,然后键入上面的命令。
 
然后win下需要装python,mac自带。
python download-deps.py
python setup.py
最后输入cocos,回车,装好的话就有反应了
 
2 使用
 
cocos new [一堆参数,有些是必须的]
换到你方便的目录,直接cocos new -l=cpp,就能用默认的名字来创建了。当然你也可以补全参数。
 
点进去有很多proj.****的文件夹,点进去就有对应的visual studio或者xcode工程,也有android studio的工程。选你的版本,就可以编译出来helloworld了。
 
3 入门
 
在你cocos new的目录里面有两个文件夹: Classes和Resources,前者是你用来写cpp和hpp的地方,后者是放png和mp3的地方。
 
打开appdelegate.cpp,就两句话你要看
    // create a scene. it's an autorelease object
auto scene = HelloWorld::createScene();

// run
director->runWithScene(scene);
这个你可把括号里面的改成你的,当然这个文件可以改一些初始化的东西,例如背景色可以改成默认白色。
 
新建一个hpp文件,加入到你的ide中。
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

using namespace cocos2d;

class HelloWorld : public Layer//这里也可以是Scene,cocos2d的类
{
public:
HelloWorld();
~HelloWorld();//名义上的构造函数和析构函数,不用鸟

virtual bool init();//实际上的构造函数

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);//cocos2d的真实构造函数
};

#endif // __HELLOWORLD_SCENE_H__
一般来说我们在cpp用 auto a = new HelloWorld;这样的写法,不过高大上的cocos当然不会用默认的语法。
要创建一个类,cocos2d一般都是auto a = HelloWorld::create(参数可能有可能没有,通常没有);
各种类都是这样的创建——其实构造函数有没有就没啥意义了。
哦,给的代码是改了的,你需要在对应的cpp文件里写三个函数,实现一个函数,构造析构函数内容都直接空着就行,反正用不上。
 
Layer和Scene几乎没啥区别,你先当成同义词。除此之外还有sprite。
 
HelloWorld::HelloWorld(){}
HelloWorld::~HelloWorld(){}

bool HelloWorld::init()
{
auto a = Sprite::create("图片路径和名称");//这里你得把资源文件拖到你的ide中
a->setposition(x,y);

this->addChild(a);
}
这就创建了a这个精灵。
 
4 动作
a->runAction(FadeIn::create(1.0));//续1秒
a->runAction(MoveTo::create(1.0,Vec2(500,500)));
显然,上面两个动作是同时进行的。
 
如果你想实现先淡入,再移动,那就:
auto seq = Sequence::create(FadeIn(),MoveTo(),NULL);//记得最后是NULL
a->runAction(seq);
如果你有a b c d四个精灵,想依次出现?那就用sequence加delaytime动作吧,别的方式我试过了还没一个能多重嵌套的。
也就是所有的动作,都是从同一时间开始的,不管你什么时候runAction的,当然回调函数例外。
 
5 事件
鼠标按键或者ipad之类的触控怎么搞?
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);


listener->onTouchBegan = [](Touch* touch, Event* event)
{
// event->getCurrentTarget() 返回 *listener's* sceneGraphPriority 节点.
auto target = static_cast<Sprite*>(event->getCurrentTarget());

// 获取当前触控点相对与按钮的位置
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);

// 检测点击区域
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
//target->setOpacity(180);
return true;
}
return false;
};

// 当移动触控的时候
listener->onTouchMoved = [](Touch* touch, Event* event)
{
//auto target = static_cast<Sprite*>(event->getCurrentTarget());

//target->runAction(MoveTo::create(0, target->getPosition() + touch->getDelta()));
};

// 结束
listener->onTouchEnded = [=](Touch* touch, Event* event)
{
auto target = static_cast<Sprite*>(event->getCurrentTarget());
log("sprite onTouchesEnded.. ");
//target->setOpacity(255);

if (target == spriteStartButton)
{
//spriteStartButton->runAction(MoveTo::create(5, Vec2(1024,-200)));

auto quitSeq = Sequence::create(DelayTime::create(1),FadeOut::create(1), NULL);
spriteBackground->runAction(quitSeq->clone());
spriteStartButton->runAction(quitSeq->clone());
spriteTitle->runAction(quitSeq->clone());
spriteCharacter->runAction(quitSeq->clone());
spriteStartButton->runAction(quitSeq->clone());
spriteMuseumButton->runAction(quitSeq->clone());
spriteConfigButton->runAction(quitSeq->clone());
spriteHelpButton->runAction(quitSeq->clone());

auto quitSeq2 = Sequence::create(DelayTime::create(1),FadeIn::create(1), NULL);
spriteLoading->runAction(quitSeq2);

auto quitSeq3 = Sequence::create(DelayTime::create(4),CallFunc::create([]{Director::getInstance()->replaceScene(MapScene::create());}), NULL);
this->runAction(quitSeq3);



}
else if (target == spriteMuseumButton)
{

}
};
其中用到的是lambda表达式,也就是个匿名函数
auto a = [函数捕捉参数](函数参数){函数实体};
比函数指针多了一个好,就是支持捕捉。
int x = 3;
auto a = [&](){x=4};
你要是用函数指针,那你要在函数的里面用函数外面的x,就得传参数,参数多了就蛋疼。但是直接[&]就可以以引用方式使用匿名函数外面的数值了,省事儿。
 
6 callfunc
你要是在sequence里面有这样的需求:先需要动作a,然后需要动作b和动作c同时进行,怎么办?用callfunc。
auto seq = Sequence::create(DelayTime::create(4),CallFunc::create([](){Director::getInstance()->replaceScene(MapScene::create());}), NULL);
a->runAction(seq);
直接用callfunc这个类,create个函数,里面填lambda表达式再好不过。
 
就这样,有需要讨论的可以留言。
 

0 个评论

要评论文章请先登录注册