cocos2d-x初探
自己挖的坑,含着泪也要填上——Eidosper
很多年前就听大牛们说,cocos2d这个引擎写的有点乱,现在有点体会了。
首先上官网——没有什么卵用,教程给的都是比较弱鸡。
先不吐槽了。
1 安装
先去官网下载:http://www.cocos2d-x.org/download
最左边那个,或者:
然后win下需要装python,mac自带。
2 使用
点进去有很多proj.****的文件夹,点进去就有对应的visual studio或者xcode工程,也有android studio的工程。选你的版本,就可以编译出来helloworld了。
3 入门
在你cocos new的目录里面有两个文件夹: Classes和Resources,前者是你用来写cpp和hpp的地方,后者是放png和mp3的地方。
打开appdelegate.cpp,就两句话你要看
新建一个hpp文件,加入到你的ide中。
要创建一个类,cocos2d一般都是auto a = HelloWorld::create(参数可能有可能没有,通常没有);
各种类都是这样的创建——其实构造函数有没有就没啥意义了。
哦,给的代码是改了的,你需要在对应的cpp文件里写三个函数,实现一个函数,构造析构函数内容都直接空着就行,反正用不上。
Layer和Scene几乎没啥区别,你先当成同义词。除此之外还有sprite。
4 动作
如果你想实现先淡入,再移动,那就:
也就是所有的动作,都是从同一时间开始的,不管你什么时候runAction的,当然回调函数例外。
5 事件
鼠标按键或者ipad之类的触控怎么搞?
6 callfunc
你要是在sequence里面有这样的需求:先需要动作a,然后需要动作b和动作c同时进行,怎么办?用callfunc。
就这样,有需要讨论的可以留言。
很多年前就听大牛们说,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最后输入cocos,回车,装好的话就有反应了
python setup.py
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__一般来说我们在cpp用 auto a = new HelloWorld;这样的写法,不过高大上的cocos当然不会用默认的语法。
#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__
要创建一个类,cocos2d一般都是auto a = HelloWorld::create(参数可能有可能没有,通常没有);
各种类都是这样的创建——其实构造函数有没有就没啥意义了。
哦,给的代码是改了的,你需要在对应的cpp文件里写三个函数,实现一个函数,构造析构函数内容都直接空着就行,反正用不上。
Layer和Scene几乎没啥区别,你先当成同义词。除此之外还有sprite。
HelloWorld::HelloWorld(){}这就创建了a这个精灵。
HelloWorld::~HelloWorld(){}
bool HelloWorld::init()
{
auto a = Sprite::create("图片路径和名称");//这里你得把资源文件拖到你的ide中
a->setposition(x,y);
this->addChild(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 b c d四个精灵,想依次出现?那就用sequence加delaytime动作吧,别的方式我试过了还没一个能多重嵌套的。
a->runAction(seq);
也就是所有的动作,都是从同一时间开始的,不管你什么时候runAction的,当然回调函数例外。
5 事件
鼠标按键或者ipad之类的触控怎么搞?
auto listener = EventListenerTouchOneByOne::create();其中用到的是lambda表达式,也就是个匿名函数
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)
{
}
};
auto a = [函数捕捉参数](函数参数){函数实体};
比函数指针多了一个好,就是支持捕捉。int x = 3;你要是用函数指针,那你要在函数的里面用函数外面的x,就得传参数,参数多了就蛋疼。但是直接[&]就可以以引用方式使用匿名函数外面的数值了,省事儿。
auto a = [&](){x=4};
6 callfunc
你要是在sequence里面有这样的需求:先需要动作a,然后需要动作b和动作c同时进行,怎么办?用callfunc。
auto seq = Sequence::create(DelayTime::create(4),CallFunc::create([](){Director::getInstance()->replaceScene(MapScene::create());}), NULL);直接用callfunc这个类,create个函数,里面填lambda表达式再好不过。
a->runAction(seq);
就这样,有需要讨论的可以留言。