cocos2d-x 4.0 安装教程(Windows + VS) + cocosui入门知识储备

(一)前期准备

  • Windows 10操作系统
  • VS 2019 或 VS 2017
  • Python 2.7.18:记得勾选将python添加到环境变量的复选框,不然自己手动添加也行。
  • CMake 3.19.0:记得勾选将cmake添加到环境变量的复选框,不然自己手动添加也行。
  • cocos2d-x 4.0:手动将cocos2d-x-4.0\tools\cocos2d-console\bin目录添加到环境变量。

以上全都下载最新版本应该也没问题,至此就可以使用VS来编译cocos2d-x工程了。

(二)VS编译cocos2d-x工程

  1. 新建项目
    打开命令行执行cocos new PROJECT-NAME -p com.coco2dx.org -l cpp -d PROJECT-PATH。其中PROJECT-NAME是实际的项目名,PROJECT-PATH是具体的项目路径。以Test作为项目名为例,命令执行之后可以生成以下目录:
    在这里插入图片描述
  2. 在该目录下新建build文件夹并打开。(其实文件夹命名随意,这里只是以build为例)
  3. build目录下打开命令行执行cmake .. -G"Visual Studio 16 2019" -Tv142 -A win32 ..(vs2017则是cmake .. -G"Visual Studio 15 2017" -Tv141 -A win32 ..)这里以Test作为项目名。
  4. 执行完毕后就会在build目录下生成VS工程,双击sln文件打开工程。
    在这里插入图片描述
  5. 直接运行就可以生成可执行文件,在build\bin\Test\Debug目录下。双击运行Test.exe就可以看到hello world啦。
    在这里插入图片描述
    在这里插入图片描述
    运行时可能会遇到一个无法启动ALL_BUILD的问题,这里将Test(你的项目)设定为启动项目即可。
    在这里插入图片描述
    在这里插入图片描述
    还有的情况下使用了log会运行失败,报错信息如下所示,错误指向文件CCConsloe.hvoid CC_DLL log(const char * format, ...) CC_FORMAT_PRINTF(1, 2);。这个错误实在是太刁钻了,查了很多论坛才发现,只要把错误列表的“生成 + IntelliSense”改成“仅生成”即可。
    在这里插入图片描述

(三)CocosStudio

cocos引擎的UI编辑器,由于已经停止维护了(下载官网也找不到了),所以这里可以提供个人的下载链接,提取码为etki

CocosStudio发布资源有两种方式:

  • 发布成csb文件,将xml格式的csd文件转换成二进制文件,便于解析。

  • 发布为VS工程,但是在VS2019上运行会存在诸如"function": 不是 "std" 的成员之类的一堆错误。幸好在github上找到解决方法,只需要在cocos2d\cocos\audio\win32\AudioCache.h文件中加上#include <functional>即可。

    实际上在VS工程中也是通过加载csb文件来进行渲染的。

    bool HelloWorld::init()
    {
    	if ( !Layer::init() )
        {
            return false;
        }
        
        auto rootNode = CSLoader::createNode("MainScene.csb");
    
        addChild(rootNode);
    
        return true;
    }
    

    运行结果为:
    在这里插入图片描述


(四)新手文档

Hello World

从HelloWorld的demo也可以看出,资源文件存放在Resources目录下。
在这里插入图片描述
运行过程:

  1. main.cpp中的入口函数做了两件事情:初始化Application对象和运行其单例的run方法。
    // main.cpp
    int WINAPI _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // create the application instance
        AppDelegate app;	// 继承自Application
        return Application::getInstance()->run();
    }
    
  2. AppDelegate的构造方法看似什么事都没做,其实是隐式调用了其父类Application的构造方法。
    // AppDelegate.cpp
    AppDelegate::AppDelegate()
    {
    }
    
    // CCApplication-win32.cpp
    Application::Application()
    : _instance(nullptr)
    , _accelTable(nullptr)
    {
        _instance    = GetModuleHandle(nullptr);
        _animationInterval.QuadPart = 0;
        CC_ASSERT(! sm_pSharedApplication);
        sm_pSharedApplication = this;	// 将静态的sm_pSharedApplication指针指向当前对象
    }
    
  3. Application的静态方法getInstance直接返回单例,即静态的sm_pSharedApplication指针。
    // CCApplication-win32.cpp
    Application* Application::getInstance()
    {
        CC_ASSERT(sm_pSharedApplication);
        return sm_pSharedApplication;
    }
    
  4. Application的实例方法run中调用了applicationDidFinishLaunching方法,该方法在其子类AppDelegate中已经被重写,在其中调用了HelloWorld场景的静态createScene方法,以及设置场景窗口、屏幕适配方案、FPS等一系列方法。
    // CCApplication-win32.cpp
    int Application::run()
    {
    	...
    	if (!applicationDidFinishLaunching())
        {
            return 1;
        }
        ...
    }
    
    // AppDelegate.cpp
    bool AppDelegate::applicationDidFinishLaunching() {
    	...
    	// create a scene. it's an autorelease object
        auto scene = HelloWorld::createScene();
        // run
        director->runWithScene(scene);
    
        return true;
    }
    
  5. HelloWorld::createScene实际上是调用其父类Scene的静态create方法,在其中新创建一个Scene对象,调用初始化方法init并返回。
    // HelloWorldScene.cpp
    Scene* HelloWorld::createScene()
    {
        return HelloWorld::create();
    }
    
    // CCScene.cpp
    Scene* Scene::create()
    {
        Scene *ret = new (std::nothrow) Scene();
        if (ret && ret->init())
        {
            ret->autorelease();
            return ret;
        }
        else
        {
            CC_SAFE_DELETE(ret);
            return nullptr;
        }
    }
    
  6. 所以我们可以在HelloWorld场景的init方法里面做自定义的初始化工作了。e.g.
    // HelloWorldScene.cpp
    bool HelloWorld::init(){
    	if ( !Scene::init() )
        {
            return false;
        }
    	...
    }
    

常用API

推荐Cocos2d-x 用户手册,里面有对一些基本概念和进阶内容的介绍。

  • 打印
    log("");
    

    log函数的参数类型为const char*,对字符串string实例要先调用c_str方法转换成const char*类型。不过更建议使用格式化日志。e.g.

    auto listener = EventListenerKeyboard::create();
    listener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event) {
        log("Key with keycode %d pressed", keyCode);
        return true;
    };
    
  • 回调

    回调函数有两种写法:

    • CALL_BACK_N(__selector__, __target__):N可选择1, 2, 3, 4,表示__selector__方法的参数个数。__selector__参数是指类的成员函数,即类名::方法名的形式,__target__是该类的对象,可以是指针或对象,一般使用this
    • Lambda表达式:[捕获值列表](参数列表){函数体}。捕获值的意义可以参看C++11中的Lambda表达式构成之——捕获值列表

    e.g.

    void HelloWorld::init(){
    	// 关闭按键的两种回调方式:
    	auto closeItem = MenuItemImage::create(
                                           	   "CloseNormal.png",
                                           	   "CloseSelected.png",
                                           	   CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
        auto closeItem2 = MenuItemImage::create(
        	"CloseNormal.png",
        	"CloseSelected.png",
        	[&](Ref* pSender) {
        	Director::getInstance()->end();
    	});
    }
    
    void HelloWorld::menuCloseCallback(Ref* pSender)
    {
        Director::getInstance()->end();
    }
    
  • Ref

    cocos2d-x - Ref 引用计数

  • Node

    cocos2d-x - Node 节点

  • 渲染

    cocos2d-x - Render 渲染

  • cocosui

    除了LabelMenu,其余UI组件都需要使用到头文件"ui/CocosGUI.h"以及命名空间ui.

    • Label:标签
      auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);	// 参数:文字,字体,字号
      
    • Menu:菜单
      auto menuItem = MenuItemImage::create("normal.png", "selected.png", 回调函数);	
      // 用法一:直接使用MenuItem创建菜单
      auto menu = Menu::create(closeItem, NULL);
      // 用法二:使用vector组织多个MenuItem来创建菜单
      Vector<MenuItem*> menuItems;
      menuItems.pushBack(closeItem);
      auto menu = Menu::createWithArray(menuItems);
      
    • Button:按键
      auto button = ui::Button::create("ButtonNormal.png", "ButtonSelected.png", "ButtonDisable.png");	// 参数:未选中图片,选中图片,不可用图片
      button->addTouchEventListener([&](Ref* sender, ui::Widget::TouchEventType type) {
          switch (type) { }
      });
      
      TouchEventType枚举常量一共有四种类型:BEGAN, MOVED, ENDED, CANCELED
      enum class TouchEventType
      {
          BEGAN,
          MOVED,
          ENDED,
          CANCELED
      };
      
    • CheckBox:复选框
      auto checkbox = ui::CheckBox::create("normal.png", "normal_press.png", "active.png", "normal_disable.png", "active_disable.png");
      checkbox->addTouchEventListener([&](Ref* sender, ui::Widget::TouchEventType type){
      	switch (type) { }
      });	
      
    • LoadingBar:进度条
      auto loadingBar = ui::LoadingBar::create("LoadingBarFile.png");
      loadingBar->setDirection(LoadingBar::Direction::RIGHT);	// 参数:方向
      loadingBar->setPercent(25);	// 参数:进度
      
    • Slider:滑动条
      auto slider = ui::Slider::create();
      slider->loadBarTexture("SliderBar.png"); 	// 参数:滑动框背景图
      slider->loadSlidBallTextures("SliderNodeNormal.png", "SliderNodePress.png", "SliderNodeDisable.png");	// 参数:未选中图片,选中图片,不可用图片
      slider->loadProgressBarTexture("SliderProgressBar.png");	// 参数:进度条图片
      slider->addTouchEventListener([&](Ref* sender, ui::Widget::TouchEventType type){
      	switch (type) { }
      });
      
    • TextFiled:文本框
      auto textField = ui::TextField::create("","Arial",30);
      textField->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type){  });
      
  • 事件分发机制
    • 事件监听器:负责接收事件,并执行预定义的事件处理函数。事件监听器可以直接对各种回调函数进行直接赋值,只有一个回调的监听器往往可以其create方法会以回调作为参数(e.g. 加速度事件监听器等)。
      • EventListenerTouch:响应触摸事件。触摸事件的回调包括(只有onTouchBegan方法是具有bool返回值的,可以设置触摸吞噬):
        std::function<bool(Touch *touch, Event *event)> onTouchBegan;
        std::function<void(Touch *touch, Event *event)> onTouchMoved;
        std::function<void(Touch *touch, Event *event)> onTouchEnded;
        std::function<void(Touch *touch, Event *event)> onTouchCancelled;
        
        关于单点触摸(EventListenerTouchOneByOne)和多点触摸(EventListenerTouchAllAtOnce)的区别可以查看:Cocos2d-X之触摸事件
      • EventListenerMouse:响应鼠标事件。鼠标事件的回调包括:
        std::function<void(EventMouse* event)> onMouseDown;
        std::function<void(EventMouse* event)> onMouseUp;
        std::function<void(EventMouse* event)> onMouseMove;
        std::function<void(EventMouse* event)> onMouseScroll;
        
      • EventListenerKeyboard:响应键盘事件。键盘事件的回调包括:
        std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed;
        std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased;
        
        EventListener基类的回调其实是只有一个参数的,而EventListenerKeyboard其实是对基类的回调进行了扩充(其实就是对event进行强转并获取其_keyCode属性),增加了额外的参数。其他监听器扩充参数的思路也可由此类推。
        bool EventListenerKeyboard::init()
        {
            auto listener = [this](Event* event){
                auto keyboardEvent = static_cast<EventKeyboard*>(event);
                if (keyboardEvent->_isPressed)
                {
                    if (onKeyPressed != nullptr)
                        onKeyPressed(keyboardEvent->_keyCode, event);
                }
                else
                {
                    if (onKeyReleased != nullptr)
                        onKeyReleased(keyboardEvent->_keyCode, event);
                }
            };
            
            if (EventListener::init(Type::KEYBOARD, LISTENER_ID, listener))
            {
                return true;
            }
            
            return false;
        }
        
      • EventListenerAcceleration:响应加速度事件。加速度事件监听器只有一个回调。
        static EventListenerAcceleration* create(const std::function<void(Acceleration*, Event*)>& callback);
        std::function<void(Acceleration*, Event*)> onAccelerationEvent;
        
      • EventListenerCustom:响应自定义事件。自定义事件监听器也只有一个回调。
        static EventListenerCustom* create(const std::string& eventName, const std::function<void(EventCustom*)>& callback);
        std::function<void(EventCustom*)> _onCustomEvent;
        
      • 每个监听器都有对应的回调函数,可以直接使用前面所说的CC_CALLBACK或者Lambda表达式来赋值。
      • 事件分派是具有一定优先级的,优先级越高,就越先接收到事件。事件分派优先级可以分为FixedPriority和SceneGraphPriority,两者只能使用一种作为标准。
        • FixedPriority:事件监听器自身设定的优先级,监听器通过addEventListenerWithFixedPriority方法注册。
          void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
          {
              CCASSERT(listener, "Invalid parameters.");
              CCASSERT(!listener->isRegistered(), "The listener has been registered.");
              CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
              
              if (!listener->checkAvailable())
                  return;
              
              listener->setAssociatedNode(nullptr);
              listener->setFixedPriority(fixedPriority);
              listener->setRegistered(true);
              listener->setPaused(false);
          
              addEventListener(listener);
          }
          
        • SceneGraphPriority:使用节点的层级作为事件分派的优先级,监听器通过addEventListenerWithSceneGraphPriority方法注册。
          void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
          {
              CCASSERT(listener && node, "Invalid parameters.");
              CCASSERT(!listener->isRegistered(), "The listener has been registered.");
              
              if (!listener->checkAvailable())
                  return;
              
              listener->setAssociatedNode(node);
              listener->setFixedPriority(0);
              listener->setRegistered(true);
              
              addEventListener(listener);
          }
          
      • 如果要在当前节点消费(吞没)事件,不再往更低优先级的节点传递,可以在回调的最后直接return true。这一点常用于Touch事件。注意:ui::Button的触摸事件以及监听器其实是自定义实现的(EventFocus, EventFocusListener),默认是在捕获时直接消费,不会再继续分派。
      • 事件监听器只能注册一次(从CCASSERT(!listener->isRegistered(), "The listener has been registered.");可以看出)。如果需要多次注册同一个监听器对象,只能使用其clone副本。e.g.
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, sprite1);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(), sprite2);
        
    • 事件分发器:负责注册监听器以及发起通知。前面四种事件一般由系统分派,自定义事件可以手动分派。以下为增删监听器和分派事件的常用方法:
      class CC_DLL EventDispatcher : public Ref
      {
      public:
          void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
      	void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
          void removeEventListener(EventListener* listener);
          void removeEventListenersForType(EventListener::Type listenerType);
          void removeEventListenersForTarget(Node* target, bool recursive = false);
          void removeCustomEventListeners(const std::string& customEventName);
          void removeAllEventListeners();
          void dispatchEvent(Event* event);
          void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
          
      protected:
          void dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent);
          void dispatchTouchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent);
      }
      
      事件分发最终是会按顺序调用到监听器的回调函数std::function<void(Event*)> _onEvent
    • 事件对象:记录事件的相关信息。事件基类为Event,事件和事件监听器是一一对应的关系。
      • EventTouch:触摸事件。
      • EventMouse:鼠标事件。
      • EventKeyboard:键盘事件。
      • EventAcceleration:加速度事件。
      • EventCustom:自定义事件。自定义事件使用一个void指针指向需要传递的数据,在自定义事件初始化之后可以调用setUserData方法设置数据,而在EventListenerCustom监听器的回调中可以调用getUserData方法获取数据。自定义事件提供一个事件名_eventName便于事件分派器定向分派事件和删除监听器。
        class CC_DLL EventCustom : public Event
        {
        public:
            EventCustom(const std::string& eventName);
            void setUserData(void* data) { _userData = data; }
            void* getUserData() const { return _userData; }
            const std::string& getEventName() const { return _eventName; }
        protected:
            void* _userData;       ///< User data
            std::string _eventName;
        }
        
  • 动作

    cocos2d-x - Action动作

【参考资料】
[1] Cocos2d-x Windows 环境搭建 - zhxmdefj - 博客园
[2] cocos2dx4.0 - 简书
[3] Cocos2dx-v4.0学习-使用CMake编译Cocos2d-4.0 (For Visual Studio)_hunter_wyh-CSDN博客
[4] 无法启动 build/x64/debug/ALL_BUILD_weixin_42279610的博客-CSDN博客
[5] Cocos2d-x 用户手册
[6] 理解CC_CALLBACK_0, CC_CALLBACK_1, CC_CALLBACK_2, CC_CALLBACK_3
[7] C++11中的Lambda表达式构成之——捕获值列表
[8] “ccconsole.h, ccutf8.h error, expected a {” - cocos2d-x / C++ - Cocos Forums

  • 13
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: cocos2d-x 4. 学习之路 cocos2d-x是一款开源的跨平台游戏引擎,支持多种平台,包括iOS、Android、Windows、Mac OS X等。cocos2d-x 4.是最新版本,相比之前版本,它有很多新特性和改进,如增强的渲染性能、更好的3D支持、更好的物理引擎等。 如果你想学习cocos2d-x 4.,可以从以下几个方面入手: 1. 学习基础知识:了解cocos2d-x的基本概念、架构和工作原理,掌握cocos2d-x的编程语言和开发环境。 2. 学习API:熟悉cocos2d-x的API,包括场景管理、精灵、动画、音频、物理引擎等。 3. 学习示例代码:通过阅读和分析cocos2d-x的示例代码,了解如何使用cocos2d-x开发游戏。 4. 学习实践:通过实践开发小游戏,掌握cocos2d-x的开发流程和技巧,提高自己的编程能力。 总之,学习cocos2d-x 4.需要一定的时间和耐心,但只要你有兴趣和热情,相信你一定能够掌握它。 ### 回答2: cocos2d-x是一个强大的游戏引擎,可用于开发移动和桌面游戏。随着cocos2d-x更新至4.0版本,它的功能得到了大幅升级。如果你想学习cocos2d-x 4.0,以下是一些重要的步骤和建议。 1. 更改代码结构 cocos2d-x 4.0中启用了新的代码结构,旨在更好地实现模块化和解耦。新代码结构包括Core、Renderer、2d等模块,使代码更易于维护和升级。要理解新代码结构,请先阅读cocos2d-x官方文档,并针对各个模块学习和熟悉其API。 2. 学习新功能 cocos2d-x 4.0中引入了许多新功能,例如Shader、Render Queue等。学习新功能是非常必要的,因为它们将改变以前的游戏开发模式。了解这些新功能的实现原理,并在自己的项目中应用它们,有助于提高游戏性能和质量。 3. 学习C++11 cocos2d-x 4.0开始支持C++11标准,这意味着你可以使用C++11的新特性来编写更好的代码。要理解C++11的特性,建议通读一遍C++11的官方标准,并尝试在cocos2d-x项目中使用这些新特性。 4. 实战练习 最后,实战练习是学习任何技能的关键。为了更好地学习cocos2d-x 4.0,建议你尝试开发自己的游戏项目。通过尝试解决实际问题,你能更好地理解cocos2d-x的API,并在实践中掌握游戏开发的技术。 总而言之,学习cocos2d-x 4.0需要掌握新的代码结构、新的功能和C++11标准,并通过实际项目实战练习来加深理解。这需要一定的时间和耐心,但只要你认真学习、实践和不断尝试,必定能够取得成功。 ### 回答3: cocos2d-x 4.0是目前市面上非常流行的开源游戏开发引擎,在游戏开发领域有着较为广泛的应用。然而,学习cocos2d-x 4.0需要付出一定的努力和时间。以下是我对cocos2d-x 4.0学习之路的一些经验和建议。 1. 学习基础知识 在开始学习cocos2d-x 4.0之前,我们需要了解一些基础知识,比如C++语言、OpenGL ES等,这些都是cocos2d-x 4.0的底层实现技术。掌握这些基础知识会让我们从事游戏开发时更加得心应手。 2. 学习文档 学习cocos2d-x 4.0需要阅读官方文档,这些文档详细介绍了引擎的各个方面,而且是学习的最佳资料。文档里包括了引擎的安装、使用、开发以及调试等。建议大家先从官网下载文档,并且仔细阅读。 3. 实践和开发 掌握了基础知识以及学习了文档之后,最好的方式就是通过实践和开发来加深对cocos2d-x 4.0的理解。通过实际开发游戏来体验引擎的使用,这样能够更深刻的理解引擎的机制以及遇到的各种问题该如何解决。同时,通过找到一些相近的问题,并通过查阅文档、代码实现等方式来解决问题,可以增强自己的技术水平。 4. 参与社区 cocos2d-x 4.0的官方论坛以及社区非常活跃,里面的开发者也有着丰富的经验和技术,在学习中可以多向论坛、社区里的大牛请教,获得更多的技术指导,同时也可以参与讨论,提出自己的问题和思考来获得反馈,这样可以更快地提高自己的技术。 总之,学习cocos2d-x 4.0需要耐心和对游戏开发的热情。只有通过不断的学习与实践,我们才能最终掌握这个优秀的游戏开发引擎,从而创建属于自己的游戏作品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值