cocos2d-x: 死磕"HelloWorld"(1)——入口函数及其带来的疑问

麻雀虽小,五脏俱全。HelloWorld就是一只小麻雀,但是涵盖了游戏制作的基本流程,以及基本的渲染框架。我们的目标就是要通过解剖这只小麻雀,一窥cocos2d-x游戏制作全貌。

由于篇幅较长,我们将整个学习过程分为七篇博文,一篇一个主题。第一个主题就是入口函数,通过观察入口函数来获取一点初步的感受,并提出一些问题,以便带着问题进一步学习。第二个主题是游戏应用实例的创建,以及它和游戏运行主函数run()之间的关系。第三个主题是详解游戏运行主函数run(),着重分析其中的应用初始化函数applicationDidFinishLaunching()和渲染主循环函数mainLoop(),但是为了掌握结构,避免混乱,我们会将这两个函数中所引用的更为细节的函数放在后续章节中讲解,这些细节函数包括HelloWorld场景的创建,渲染的准备和具体实施。因此,第四个主题就是HelloWorld场景的创建,它通过applicationDidFinishLaunching()中调用的HelloWorld::scene()来实现,所以我们将在该篇中详解HelloWorld::scene()函数。有了场景之后,下一步就是渲染该场景,因此第五个主题是渲染的准备工作,它通过applicationDidFinishLaunching()中调用的runWithScene()实现,功能是把场景入栈,等待渲染。第六个主题就是渲染的具体实施,它通过mainLoop()里的drawScene()实现,其中涉及一些“底层”的openGL函数调用。最后在第七篇中作一总结。对于一个单纯的游戏制作者而言,只需了解前面四篇内容,而后面的渲染部分可以留给引擎开发者们去操心。

本文针对Cocos2d-x 2.2.3版而写。希望能够做到两点:一是结构清晰,二是细节详尽。但是由于水平有限,必有许多谬误,欢迎批评指正。

闲话少叙,进入正题。HelloWorld的C++版项目名为HelloCPP,其结构如下图所示:

一个入口函数,main.cpp/h, 两个类,AppDelegate.cpp/h和HelloWorld.cpp/h, 还有一个定义宏的头文件,AppMacros.h。看起来so easy,有木有。其实还有很多其他的类,比如application类,导演类,场景类等,都没有显示出来。之所以只显示两个类其实是有深意的。因为对于单纯的游戏制作者(而非引擎开发者)而言,只需显示出来的这两个类,而那些隐藏的类是封装好的,无需改动。我们将在后面逐渐认识到这一点。

我们现在就来看一下入口函数的头文件:

main.h

#ifndef __MAIN_H__
#define __MAIN_H__

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
//定义了一个空宏WIN32_LEAN_AND_MEAN,可以做为宏开关使用。例如在后面就可以调用#ifdef WIN32_LEAN_AND_MEAN,进行选择性编译。从原有的英文注释中可以看出,该宏开关是用于剔除不必要的Windows头文件,这样可以加速生成解决方案。
// Windows Header Files:
#include <windows.h>
//和windows编程相关头文件。
#include <tchar.h>
//和字符串编码有关头文件,方便处理中文。

// C RunTime Header Files
#include "CCStdC.h"
//和运行时间有关头文件。
#endif    // __MAIN_H__

该头文件并无特别之处,无非就是包含了三个相关头文件。至于这几个头文件里的具体内容,已经超越本文主题,暂且搁下。下面就来看看入口函数的源文件:

main.cpp

#include "CCEGLView.h"

USING_NS_CC;//宏开关,用于选择使用或者不使用cocos2d名空间。默认状态是使用。它的具体定义在下一代码片段中展示。

int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);//从该宏定义来看,和直接放置hPrevInstance等效。目的是说明该参数未在程序中其他地方引用,只在此处象征性引用一下,避免编译警告。
    UNREFERENCED_PARAMETER(lpCmdLine);//同上。
    //以上三行代码,如果试过在VS里创建win32项目的童鞋会发现它们是自动生成的,和cocos2d-x没啥关系。基本上意思就是建立一个带四个参数的入口函数,但是第二个和第三个参数并未在程序里引用。这里就不再赘述了。

    // create the application instance
    AppDelegate app;//声明了一个AppDelegate实例对象app。AppDelegate是应用代理类,一个应用有且仅有一个代理,它继承了CCApplication类。其具体内容将在第二篇中分解。
    CCEGLView* eglView = CCEGLView::sharedOpenGLView();// 创建了一个CCEGLView类的指针,eglview,顾名思义,跟视窗有关。并且用一静态成员函数(必须是静态的,否则无法直接调用)来初始化该指针。
    eglView->setViewName("HelloCpp");//给窗口命名。
    eglView->setFrameSize(2048, 1536);//设置窗口大小。
    // The resolution of ipad3 is very large. In general, PC's resolution is smaller than it.
    // So we need to invoke 'setFrameZoomFactor'(only valid on desktop(win32, mac, linux)) to make the window smaller.
    eglView->setFrameZoomFactor(0.4f);//调整分辨率。
    return CCApplication::sharedApplication()->run();//整个游戏的运行就靠这一句。它的具体内容将在第三篇中详解。在此,我们能看出的是sharedApplication()必须是CCApplication的一个静态成员函数,否则无法直接调用,而且返回值是一指针,因为它后面跟了一个指针御用箭头操作符,而run()就是该指针所指对象的成员函数。

}

最前面的宏开关的定义如下

CCPlatformMacros.h(顾名思义,定义了各种平台相关的宏)

// namespace cocos2d {}
#ifdef __cplusplus
    #define NS_CC_BEGIN                     namespace cocos2d {
    #define NS_CC_END                       }
    #define USING_NS_CC                     using namespace cocos2d
#else
    #define NS_CC_BEGIN 
    #define NS_CC_END 
    #define USING_NS_CC 
#endif

可见,如果__cplusplus已经被定义,则用cocos2d为名空间,否则不用。


至此,我们囫囵吞枣将入口函数过了一遍。在阅读代码过程中,我们注意到对标识符的命名规则的掌握可以帮助理解。这里先小结两处:

经验小结1,一般全大写代码,不是宏名,就是类型别名。

经验小结2,以shared开头的函数都是静态的实例获取函数,常用于单例模式(在下一篇还会遇到)。

面对如此简练的入口函数,相信童鞋们心里一定会有很多疑问,比如, Q1, app对象建立之后去哪了?Q2, 最后是什么对象在run?Q3, run的内容是什么?Q3, HelloWorld类去哪了?咋没露个脸呢?Q4, HelloWorld图片到底是从哪里进来的呢?老师经常教导我们要带着疑问来学习,所以有疑问是件好事。在接下来的篇章中我们将一步步解答这些问题。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值