cpp11:
- 支持了auto标识符, 这样可以大大简化了声明变量的类型
- auto标识符: 泛类定义
- nullptr 代替 NULL, NULL只代表内存地址位为0, 这样做有时会出问题, cpp11后尽量用nullptr
- static_cast< Class >obj相当于c语言的(Class)obj, dynamic_cast更智能, 无法转换会返回nullptr
- 设置指针型布尔
std::shared_ptr<bool> enable(new bool(true));
- 获取和赋值
(*enable) = false;
- 获取和赋值
- 7.
创建工程
- 下载最新的cocos2dx 3.x版本, 解压缩
- 打开terminal, cd 找到3.x解压缩的路径位置/tools/cocos2d-console/bin
- 执行 ./cocos new ProjectName -l cpp -p PackageName -d ~/Desktop
- 自行替换上面的ProjectName和PackageName内容, 以及对应语言, 我使用c++语言, 保存到桌面上
- std::nothrow
在内存不足时,new (std::nothrow)并不抛出异常,而是将指针置NULL
[相对cocos2dx2.x来看待]
基础
- 设置z层级
setLocalZOrder(0);
- 获得z层级
getGlobalZOrder();
- 层级参考链接
- globalZOrder 是用于 渲染器 中用来给“绘制命令”排序的
- localZOrder 是用于父节点的子节点数组中给 节点 对象排序的
- 设置颜色
setColor(Color3B::RED);
- 清空颜色
setColor(Color3B::WHITE);
- 获取锚点对应坐标
Vec2::ANCHOR_BOTTOM_LEFT
- 菜单按钮绑定
CC_CALLBACK_1(MyClass::func, this)
- 获取屏幕大小
Director::getInstance()->getWinSize()
- 获取屏幕可视区域
Director::getInstance()->getOpenGLView()->getVisibleRect()
- 获得触碰点的世界坐标系
- convertToWorldSpace(convertToNodeSpace(pTouch->getLocation()))
- convertToWorldSpace(convertTouchToNodeSpace(pTouch))
- 触控点还取决于glview->setDesignResolutionSize和director->setContentScaleFactor
ActionManager:
- VisibleRect 屏幕可以获得屏幕的指定位置点, 可以获得屏幕的大小
- 同时可并行执行多条 action
- CC_CALLBACK_0 调用函数指针, 执行参数为0的函数
- CC_CALLBACK_1 执行参数为1的函数
- removeChild 可以remove 自身
- Director::getInstance()->getActionManager()->addAction(action, target, true); 另外一种添加动作的方式, 第三个参数为不自动执行
- Director::getInstance()->getActionManager()->resumeTarget(target); 回复执行对象动作
- Director::getInstance()->getActionManager()->pauseTarget(target); 设置后对象即使添加新的动作也无法执行
- schedule(CC_SCHEDULE_SELECTOR(MyClass::funct), 3); 每三秒执行一次
8.unschedule(CC_SCHEDULE_SELECTOR(MyClass::funct)); 停止循环执行函数 - 在执行动作的过程中调用函数, 并终止动作, 不会导致crash
- action的tag可以重复, 可通过sprite->stopAllActionsByTag(kTag); 删除多个动作, 而且可以保留其他动作继续执行
Action
- actionBy->reverse() 可以创建相对运动的逆运动
- target->setPosition3D(Vec3(40, 40, 0)); 伪3d, z负责缩放, moveBy moveTo 同样支持
- SkewTo可以创造3d翻转
- target->ignoreAnchorPointForPosition(false); 不忽略锚点
- JumpBy::create(time, targetPosition, high, jumpTimes);
- PointArray->addControlPoint(Vec2(0, 0)); 点数组存储点
- DrawNode->drawCardinalSpline(pointArray,0,100,Color4F(1.0, 0.0, 1.0, 1.0));
- CardinalSplineBy::create(3, array, 1); 按照点以及点的张力运动
- CatmullRomBy::create(3, array); 非封闭点运动
- CallFunc::create(std::bind(&TargetClass::funct,this, param) ) 绑定函数, 这样可以传递参数, 也支持数值类型
CallFuncN::create( CC_CALLBACK_1(ActionCallFuncN::callback, this))
CallFunc::create( std::bind(&ActionCallFunction::callback1, this) )
CallFunc::create( std::bind(&ActionCallFunction::callback2, this, _tamara) )
CallFunc::create( std::bind(&ActionCallFunction::callback3, this, _kathia, 42) ) - CallFuncND 不再需要, 已经被std::bind()替代
- sequence 序列 可以支持reverse翻转
- OrbitCamera 轨道动作
- this->runAction(Follow::create(target, Rect(0, 0, s.width * 2 - 100, s.height))); 舞台镜头跟踪对象
- TargetedAction::create(target, jump2) 混合其他对象动作到当前动作中, 支持reverse
- this->schedule([&](float dt) { log(“dealing”);},5 ,false ,0, “key”); 延迟函数(函数内容, 周期间距, 重复次数, 延迟, key)
- scheduleOnce([&](float dt) { log(“dealing”);},2 ,”key”);
- auto actionFloat = ActionFloat::create(2.f, 0, 3, [this](float value) { target->setScale(value); }); 无需自定义变量, 设置临时数值变化
- action->clone() 再也不需要去写autorelease, 已经被包含在clone内部, 非常方便
- Scheduler 的 timeScale 可以正倒放动作
ProgressBar
- 已支持SpriteFrame方式进度条
auto s = Director::getInstance()->getWinSize();
auto to = Sequence::createWithTwoActions(ProgressTo::create(6, 100), ProgressTo::create(0, 0));
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("zwoptex/grossini.plist");
auto left = ProgressTimer::create(Sprite::createWithSpriteFrameName("grossini_dance_01.png"));
//ProgressTimer::Type::RADIAL/BAR
left->setType(ProgressTimer::Type::BAR);
//radial模式设置为逆时针旋转
//left->setReverseProgress(true);
left->setMidpoint(Vec2(0.5f, 0.5f));
left->setBarChangeRate(Vec2(1, 0));
addChild(left);
left->setPosition(100, s.height/2);
left->runAction(RepeatForever::create(to->clone()));
sound & music
- 我能了解到的是v2.x版本的苦恼, 原因是2.x版本的sfx在loop的时候100%无法回收停止音效, 应该在v3.x版本里面有所修正, 待证实
camera
- 创建camera:
auto camera = Camera::create();
camera->setCameraFlag(CameraFlag::USER1);
addChild(camera); - 默认当前场景会有一个defaultCamera
- camera对象虽然也是被添加在node环节中, 但是他的层级关系只跟设置的CameraFlag有关系, 数值越大越在前端显示
- 在设置一个node节点整体为一个camera的内容时, 如果想把子节点都设置为此camera的内容, 则最好在所有addchild完成后再设置setCameraMask((unsigned short)CameraFlag::USER1)
- 参考链接
cocos2d 信息
- 读取plist信息
Configuration::getInstance()->loadConfigFile("configs/config-test-ok.plist")
- 获取信息
Configuration::getInstance()->getInfo()
- cocos2dx版本
Configuration::getInstance()->getValue("cocos2d.x.version") //cocos2d-x-3.7
- openGL版本
Configuration::getInstance()->getValue("gl.version") //OpenGL ES 2.0 IMGSGX543-113.3.1
- 获取无效值后会得到默认值
Configuration::getInstance()->getValue("invalid.key", Value("defaultStrValue"))
- 获取国家
Application::getInstance()->getCurrentLanguage() //LanguageType::CHINESE
- 获取国家码
Application::getInstance()->getCurrentLanguageCode() //zh
Touch 触摸绑定
- EventListenerTouch 触摸事件侦听
- EventListenerKeyboard 键盘事件侦听
- EventListenerAcceleration 加速器事件侦听
- EventListenMouse 鼠标事件侦听
- EventListenerCustom 自定义事件侦听
- 回调函数
- lambda方式cpp11
[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; } // 没有return语句 -> lambda 函数的返回类型是'void'
[]() { ++global_x; } // 没有参数,仅访问某个全局变量
[]{ ++global_x; } // 与上一个相同,省略了()
[] //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y] //x 按值捕获, y 按引用捕获.
[&] //用到的任何外部变量都隐式按引用捕获
[=] //用到的任何外部变量都隐式按值捕获
[&, x] //x显式地按值捕获. 其它变量按引用捕获
[=, &z] //z按引用捕获. 其它变量按值捕获
- 以上参考链接
listener->onTouchBegan = [=](Touch* touch, Event* event){
return true;
};
listener->onTouchEnded = [=](Touch* touch, Event* event){
};
- CC_CALLBACK_N宏回调方式
- 10.
- lambda方式cpp11
- 事件侦听器派发
- _eventDispatcher是Node的一个属性,使用它来管理当前节点(Scene, Layer和Sprite)不同事件的分配
- 使用clone()方法是因为每一个事件监听器只能被添加一次
- 如果是固定优先值的监听器添加到一个节点(addEventListenerWithFixedPriority),那当这个节点被移除时必须同时手动移除这个监听器,但是添加场景图优先监听器到节点(addEventListenerWithSceneGraphPriority)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);- FixedPriority和SceneGraphPriority
- FixedPriority 整形值。低权值的事件监听器将优于高权值的事件监听器
- SceneGraphPriority Node的指针。Node的z顺序高的(绘制于顶部的)节点将优于z顺序低的节点。这将保证了诸如触碰事件的自顶向下传播
键盘
- `auto listener = EventListenerKeyboard::create();
listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this);
listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
// Implementation of the keyboard event callback function prototype
void KeyboardTest::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event)
{
log(“Key with keycode %d pressed”, keyCode);
}void KeyboardTest::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event)
{
log(“Key with keycode %d released”, keyCode);
} `- `auto listener = EventListenerKeyboard::create();
加速计事件
- `auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(AccelerometerTest::onAcceleration, this));
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
// Implementation of the accelerometer callback function prototype
void AccelerometerTest::onAcceleration(Acceleration* acc, Event* event)
{
// Processing logic here
}`- `auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(AccelerometerTest::onAcceleration, this));
鼠标事件(v3新增)
- `_mouseListener = EventListenerMouse::create();
_mouseListener->onMouseMove = CC_CALLBACK_1(MouseTest::onMouseMove, this);
_mouseListener->onMouseUp = CC_CALLBACK_1(MouseTest::onMouseUp, this);
_mouseListener->onMouseDown = CC_CALLBACK_1(MouseTest::onMouseDown, this);
_mouseListener->onMouseScroll = CC_CALLBACK_1(MouseTest::onMouseScroll, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);`
- `_mouseListener = EventListenerMouse::create();
- 自定义事件
_listener = EventListenerCustom::create("game_custom_event1", [=](EventCustom* event){
std::string str("Custom event 1 received, ");
char* buf = static_cast<char*>(event->getUserData());
str += buf;
str += " times";
statusLabel->setString(str.c_str());
});
_eventDispatcher->addEventListenerWithFixedPriority(_listener, 1);- 事件触发
static int count = 0;
++count;
char* buf = new char[10];
sprintf(buf, "%d", count);
EventCustom event("game_custom_event1");
event.setUserData(buf);
_eventDispatcher->dispatchEvent(&event);
CC_SAFE_DELETE_ARRAY(buf);
- 事件移除
- 移除单独侦听器
_eventDispatcher->removeEventListener(listener);
- 移除所有侦听起, 如果在同一语句下新增了新的事件, 那么全部删除语句并不会影响到下一步操作
_eventDispatcher->removeAllEventListeners();
- 移除单独侦听器
- 创建单一事件侦听器
EventListenerTouchOneByOne::create()
- 其他
- 触碰点转换为位置点
Vec2 locationInNode = this->convertToNodeSpace(touch->getLocation());
- 检测是否点击区域
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
if (rect.containsPoint(locationInNode))- 拖动物体跟随移动
auto target = static_cast<Sprite*>(event->getCurrentTarget());
target->setPosition(target->getPosition() + touch->getDelta());
- 事件优先级
- 如果设置了优先级, 那么这个触碰就和addchild层级没关系了, 不设置是默认随层级走的, 层级越高, 越靠近camera越容易被触碰, 而如果设置了优先级, 不管你child层级如何, 都按照指定优先级来, 优先级priority是按照从小到大数字来排列先后点击的
- 使用优先级调用的是addEventListenerWithFixedPriority方法, 所以必须手动回收
//使用优先级
_eventDispatcher->addEventListenerWithFixedPriority(listener, _fixedPriority);
//不使用优先级
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
- 移除和添加事件
- 移除
_eventDispatcher->removeEventListener(listener1);
- 移除指定类型
_eventDispatcher->removeEventListenersForType(EventListener::Type::TOUCH_ONE_BY_ONE);
- 添加
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
- 移除
- 在添加事件后, 对象retain并移除, 再次出现时是可以继续执行触碰操作的. 给的例子来看, 在隐藏后显示, 未松开手指拖动, 还是会直接触碰touchmove事件, 这点需要注意
- direct事件
- 更新 Director::EVENT_AFTER_UPDATE
- 访问 Director::EVENT_AFTER_VISIT
- 绘制 Director::EVENT_AFTER_DRAW
- 投影 Director::EVENT_PROJECTION_CHANGED
- 通过 Director::getInstance()->getEventDispatcher() 的 addCustomEventListener 方式来添加事件
- 绑定函数 std::bind(&DirectorEventTest::onEvent1, this, std::placeholders::_1)
- 绑定匿名函数 [&](EventCustom *event) {}
- 多点触摸
- EventListenerTouchAllAtOnce
- 获得第一个点击的点
touches[0]
- 暂停和恢复事件
- 暂停
_eventDispatcher->pauseEventListenersForTarget(this, true); //参数2为是否递归
- 恢复
_eventDispatcher->resumeEventListenersForTarget(this, true); //参数2为是否递归
- 一次性事件
removeListenerOnTouchEnded(true); //触摸结束不再接收触摸
引擎扩展
- 动态下载 参照 AssetsManagerExTest 事例
- 滑动条 参照 CCControlSliderTest 事例
- 取色器 参照 ControlColourPickerTest 事例
- 开关 参照 ControlSwitchTest 事例
- 色彩文字按钮 参照 ControlButtonTest 事例
- 音量旋钮 参照 ControlPotentiometerTest 事例
- 加减按钮 参照 CCControlStepperTest 事例
- ccbi界面 参照 CocosBuilderTest 事例
- 滚动界面 参照 TableViewTest 事例
- 图片加密 参照 Texure Atlas Encryption 事例
材质特效
- 创建滤镜
auto properties = Properties::createNonRefCounted("Materials/2d_effects.material#sample");
Material *mat1 = Material::createWithProperties(properties);
- 模糊特效
spriteBlur->setNormalizedPosition(Vec2(0.2f, 0.5f));
spriteBlur->setGLProgramState(mat1->getTechniqueByName("blur")->getPassByIndex(0)->getGLProgramState());
- 外发光
spriteOutline->setNormalizedPosition(Vec2(0.4f, 0.5f));
spriteOutline->setGLProgramState(mat1->getTechniqueByName("outline")->getPassByIndex(0)->getGLProgramState());
- 噪点
spriteNoise->setNormalizedPosition(Vec2(0.6f, 0.5f));
spriteNoise->setGLProgramState(mat1->getTechniqueByName("noise")->getPassByIndex(0)->getGLProgramState());
- 边缘检测
7.spriteEdgeDetect->setNormalizedPosition(Vec2(0.8f, 0.5f));
spriteEdgeDetect->setGLProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getGLProgramState()); - 效果拖尾
- 参考 Node: MotionStreak 支持色彩和贴图拖尾
- 物理引擎 参考 Node: Physics / 3D
- 屋里引擎 关节 参考 Joints
- action和物理引擎的互相影响 Actions
- 只处理单面碰撞 One Way Platform
- 切割 Slice
数据存储
向量等
参考链接:
ps: v4都出了泪奔了~~~
cocos2dx v3的一些特色功能:
Auto-batching
在3.0版本实现了引擎的逻辑代码与渲染代码的分离,实现了Auto Batch与Auto Culling功能。不再推荐使用SpriteBatchNode提高精灵的绘制效率。
Auto-culling的支持,Sprite在绘制时会进行检查,超出屏幕的不会发给渲染。
Auto-batching拥有更好的性能提升。Auto-batching的渲染流程
- drawScene开始绘制场景
- 遍历场景的子节点,调用visit函数,递归遍历子节点的子节点,以及子节点的子节点的子节点,以及…
- 对每一个子节点调用draw函数
- 初始化QuadCommand对象,这就是渲染命令,会丢到渲染队列里
- 丢完QuadCommand就完事了,接着就交给渲染逻辑处理了。
- 是时候轮到渲染逻辑干活干活,遍历渲染命令队列,这时候会有一个变量,用来保存渲染命令里的材质ID,遍历过程中就拿当前渲染命令的材质ID和上一个的材质ID对比,如果发现是一样的,那就不进行渲染,保存一下所需的信息,继续下一个遍历。好,如果这时候发现当前材质ID和上一个材质ID不一样,那就开始渲染,这就算是一个渲染批次了。
- 因此,如果我们创建了10个材质相同的对象,但是中间夹杂了一个不同材质的对象,假设它们的渲染命令在队列里的顺序是这样的:2个A,3个A,1个B,1个A,2个A,2个A。那么前面5个相同材质的对象A会进行一次渲染,中间的一个不同材质对象B进行一次渲染,后面的5个相同材质的对象A又进行一次渲染。一共会进行三次批渲染。