第2章 钢琴师(上)

劲松重新搭好了开发环境,问文彪道:“环境搭好了,你要做个什么呢?”

文彪胸有成竹的说道:“你看我的名字,一文一武。追妹子当然不能用武啦,虽然我算不上一个文艺青年,不过弹个小曲子还是没问题的。不如你就帮我做个钢琴的应用吧。”

“钢琴应用不是有现成的么,干嘛还要麻烦我做?”劲松疑惑地看着他。

“这就不懂了吧。现在都讲究定制,网上是能下载到,不过追妹子还欠火候。我找了一圈,没找到适合的。”

“所以你其实是没找到顺手的?”

“也不全是。好比说你要买书,找了一圈,只发现有两本,一本用人民币买,一本用美元买。虽然折算过来价钱一样,不过美元那本就显得更有价值。”

“但是我还是会买通过人民币卖的那本。”

“你没抓住重点啊,核心在感觉,谈情说爱不就是谈感觉么?”,文彪继续说道:“感觉怎么产生的?与众不同。我们的生活太乏味了,需要点新鲜空气,而我要成为那片空气,就像……”。

“好好”,劲松赶忙打断他,文彪一旦胡扯起来,就没完没了,“做呗,那就它了!另外,你追的还是上次看到那个妹子吗?”

“必须啊,这两天我都调查好了。她跟咱们同岁,学师范专业的,毕业后直接在北京找的工作。”文彪一口气说了这妹子的信息。

“我们给行动起个名字吧”,文彪接着说道,“她是教语文的,就叫文心雕龙怎么样,挺有意境吧?”

“那跟你也没关系啊。不如叫‘文心彪拢’如何?”劲松笑着问。

“绝了。劲松,你太给力啦,就它了。哈哈”,文彪大笑,“文心彪拢成功与否,就看劲松大神做的神器啦。”

“好说好说”,劲松笑着摆摆手“劲松的名字是白叫的吗?”

2.1 解析Cocos2D-X

搭建一个游戏很像拍电影,要把主角放到正确的位置,并能控制他的行为。游戏开发的过程更像是一个调配所需元素的过程。这节将从第1章新建的项目入手,分析Cocos2D-X的基本元素和架构,了解一下所需要的“道具”。

2.1.1 元素

在玩游戏时,我们能看见的、能操纵的都是元素。以先前的HelloWorld为例,其中就有三个元素,分别是图片、文字和菜单。元素这个概念有个对应的类:Node。因此我们说,图片是一个元素,它一定是继承自Node。

打开在第1章中创建的项目:HelloWorld。打开HelloWorldScene.cpp文件,我们来看一下元素究竟是怎么创建出来的。

(1)图片

场景和人物大多是通过图片来表现的,所以图片是最常用的元素。通常会使用精灵(Sprite)来对图片进行操作。我们可以看到在init函数中如何创建一个精灵,相应代码如下:

        auto sprite = Sprite::create("HelloWorld.png");

提示

创建这个Sprite的图片资源保存在程序根目录的Resources目录下,这个目录是Cocos2D-X读取文件的默认目录。项目中使用到的资源都应该放置在这个目录中。

上面的代码创建了一个精灵,它显示的图片是“HelloWorld.png”。auto是自动类型推导,可以根据需要将变量声明为对应类型。它是C++ 11的新特性,具体可以参考第9章的介绍。另外,我们来看一下Sprite的类定义,它有很多的构造函数,如代码清单2-1所示。

代码清单2-1 Sprite的构造函数

        static Sprite* create();
        static Sprite* create(const std::string& filename);
        static Sprite* create(const std::string& filename, const Rect& rect);
        static Sprite* createWithTexture(Texture2D *texture);
        static Sprite* createWithTexture(Texture2D *texture, const Rect& rect, bool rotated=false);
        static Sprite* createWithSpriteFrame(SpriteFrame *spriteFrame);
        static Sprite* createWithSpriteFrameName(const std::string& spriteFrameName);

我们可以根据实际的需求进行选择。

(2)文字

此处的文字包含数字和文本两部分。它也是常用的元素,可以实现标记状态、显示完成度、记录结果等功能。同图片元素一样,它也有很多种创建方式。在这个例子中使用的是下面这个创建函数:

        auto label = LabelTTF::create("Hello World", "Arial", 24);

这行语句创建了一个显示“Hello World”的文字,字体是“Arial”,字号是24。

(3)菜单

菜单最初专门用于处理点击。随着Cocos2D-X的发展,发现这种形式不太容易使用。在我们使用的Cocos2D-X 3.0中,点击部分已经重新设计了,我们会在后面详细讲解。但是,对于菜单的使用方法,在这里应该有所了解,创建一个菜单如代码清单2-2所示。

代码清单2-2创建一个菜单

        auto closeItem = MenuItemImage::create(
                                "CloseNormal.png",
                                "CloseSelected.png",
                                CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
        auto menu = Menu::create(closeItem, NULL);

注意

真正创建出菜单的是最后一行,而之前创建的closeItem是一个菜单项。一个菜单是一个容器,可以含有很多菜单项。

从代码清单2-2中我们看到,前两个参数是图片资源,它们是正常状态和点击状态所使用的显示图片,第三个参数是一个回调函数,当点击按钮时调用这个函数。

注意

CC_CALLBACK_1是Cocos2D-X 3.0中新加入的回调定义,它是基于C++11中的std::bind的一种回调方式,最后一位数字代表这个绑定函数有一个参数。

2.1.2 层

看过了对元素的介绍,我们再来了解一下,在Cocos2D-X的程序中如何使用层来处理元素间的关系。正如PhotoShop一样,将不同元素放置到不同的层上,不同层上的元素之间就不会受到影响。采用这样的方式,可以实现对元素的灵活管理。

注意

在同一层中,也可以分出更小的“层”,通常使用“ZOrder”来标记。“ZOrder”只是逻辑意义上的层,并不像这里的层是一个数据结构。有些时候,需要通过更改“ZOrder”来手动调整元素间的遮挡关系。

在HelloWorld中,将所有的元素都加入到了一个层中。这个层的创建位置在HelloWorldScene.cpp中的createScene函数中,创建方法如下:

        auto layer = HelloWorld::create();

2.1.3 场景

我们可以认为场景是在一定的时间、空间内发生的一系列事件的集合,因此场景是一个比层更大的概念,是一个层的集合。创建场景的方式依旧可以在createScene函数中看到,代码如下:

        auto scene = Scene::create();

2.1.4 导演

既然是拍“微电影”,总要有导演。我们的程序中也有这么一个“导演”,当“他”喊“Cut”时,场景就要停止。它是一个单例,在AppDelegate.cpp文件的applicationDid-FinishLaunching函数中初始化,并且可以载入一个默认的场景,如代码清单2-3所示。

代码清单2-3初始化导演并载入场景

        //初始化
        auto director = Director::getInstance();
        //创建场景
        auto scene = HelloWorld::createScene();
        //载入场景
        director->runWithScene(scene);

提示

单例模式是一种常用的软件设计模式。通过单例模式可以保证系统中的某个类只有一个实例。单例在对实例个数进行控制的同时,也节约了系统资源。在Cocos2D-X中大量使用了单例。简单点说,单例就是一个全局的实例。

2.1.5 组合

经过上面的介绍,我们已经知道了元素、层、场景等,那么如何把它们组织起来呢?

仔细看HelloWorldScene.cpp中的init函数,我们会发现有一个addChild函数,它就是把所有东西组合起来的关键。当我们使用addChild函数时,就可以为当前对象添加一个子对象,这样我们就可以建立一个树型结构,进而构建出整个游戏。在绘制每个元素时,也会绘制它的子节点。反过来说,如果未画出某个元素,很有可能是我们忘记使用addChild函数了。

2.2 使用UI编辑器

像上一节说过的那样,我们可以使用addChild函数在代码中组合层和元素。有了这些知识,我们就可以着手构思一下我们要做的钢琴游戏了。

钢琴的琴键很多,手机屏幕肯定放不下,必须有一个能够拖动的琴键组。另外琴键的位置怎么确定?总不能硬想吧?这就要用到图形化的编辑工具。在这节中我们将使用编辑器编辑一个可拖动的琴键。

2.2.1 创建UI工程

UI Editor是CocoStudio的一部分,它的主要功能是编辑游戏中的UI。接下来我们就了解一下它的使用。

首先,我们运行CocoStudio,在主界面中点选UI Editor。在弹出的UI编辑器菜单中点选“文件”→“新建项目”,(或使用快捷键“Ctrl+N”),会弹出如图2-1的新建项目对话框,在其中更改项目名和路径后,点击确定。

图2-1 创建新UI工程

创建成功后会弹出如图2-2的工程界面,这就是我们的工作区。

图2-2 UI编辑器的工作区

接下来我们做些基本的更改,使工程配置符合我们的要求。

❑更改画布列表中的名字,选中画布列表中的画布名,按下“F2”,将其更改为Piano,这将是我们项目导出后的文件名。

❑在工具栏中点选画布,更改画布大小,这里我们选择960*640,如图2-3所示。

图2-3 更改画布大小

技巧

在编辑器的右下角有缩放的滚动条,可以用来调整工作区的大小。另外,按住空格键可以拖动工作区。

2.2.2 创建元素

在配置好基本环境后,我们着手创建一个滚动层。

在左侧的工具栏中找到滚动层,点选拖动到工作区中,如图2-4所示。

图2-4 创建滚动层

完成上述操作后,我们可以看见一个新建的红色的区域,即滚动区域。接下来,我们更改它的属性值,使其符合我们的要求。

❑在“属性”→“尺寸和模式”中,将控件宽改为960,将控件高改为640,移动控件使它贴合在工作区上。

❑在“属性”→“常规”中,更改名字为“Main”。

❑在“属性”→“控件布局”中将坐标更改为X=0,Y=0。

❑在“属性”→“特性”中,更改滚动区域宽度为1800,更改滑动方向为“Horizontal”。

注意

滚动区域在滚动方向上没有增加,是无法产生滚动效果的。

接下来我们要将资源添加进工程中。在右侧“资源”选项卡中点击“添加文件”图标可以添加单个资源文件,点击“添加文件夹”可以添加一个文件夹。找到琴键的图片资源,将其添加进资源中。

提示

CocoStudio项目文件默认的资源目录是项目根目录下的“Resource”。这里我们需要把随书光盘文件中的“chapter2/picture”中的图片复制到“Resource”目录下。

添加好资源后,我们来创建一个琴键。

1)在左侧工具栏中拖动“按钮”到工作区中,如图2-5所示。

图2-5 创建按钮

注意

此处实际上是将按钮添加到了滚动层Main中,将它添加成了滚动层的子元素。

2)在对象结构列表中选择刚刚创建好的按钮。

3)确保“属性”→“常规”中的交互复选框被选中。

注意

选中交互表示接收点击消息。因此如果不选中此项,点击时将不会有响应。

4) 找到“属性”→“特性”。将“Resource”中“left.png”拖动到“正常状态”后面的输入框中,将“left_down.png”分别拖动到“按下状态”和“禁用状态”中,这样就完成了显示皮肤的更改。

技巧

可以在Windows的资源管理器中选中图片文件,将其拖动到右侧资源选项卡中。

5)拖动按钮将其调整到合适的位置,调整好后如图2-6所示。

图2-6 调整后的按钮

注意

在图2-6中,正方形边框的四个角点是缩放点,右侧边的中点是旋转点,红色的十字星是锚点,也是旋转轴。

2.2.3 导出

编辑好琴键后我们要将其保存并导出。

点击“文件”→“导出项目”,在弹出的对话框中,我们可以看到导出路径和一些导出的选项,这里我们不做更改。点击确定,会弹出一个导出成功的对话框,这样我们的编辑工作就正式完成了。

2.3 载入到程序

在上节我们编辑出了一个琴键,但只有界面是不行的,要将它关联加载到程序才算完整。在这节我们将看到如何将CocoStudio导出的文件载入到程序中,运行效果如图2-7所示。

图2-7 加载运行效果

2.3.1 创建加载环境

按照第1章介绍的方法,我们创建一个名为Piano的工程。创建成功后,我们先编译运行一下,防止原始工程创建出现问题。

运行成功后,我们将CocoStudio导出的资源复制到Piano工程的Resources目录下。

接下来要配置项目属性。在Cocos2D-X3.0中将功能进行分类并封装到不同的库中,因此要使用相应功能就要配置相应的包含目录和库依赖。

我们要使用CocoStudio导出文件,因此要按以下方法配置。

1)添加附加包含目录。右击“项目”→“属性”,在弹出的对话框中选择“C/C++”→“常规”→“附加包含目录”,在“附加包含目录”行末点击下箭头,在下拉菜单中选择编辑。在其中添加两个目录: $(EngineRoot)cocos\和$(EngineRoot)cocos\editor-support,如图2-8所示。

图2-8 添加包含目录

2)添加附加库目录。在“解决方案”上右击,选择“添加”→“现有项目”,如图2-9所示,然后选择“项目根目录\cocos2d\cocos\editor-support\cocostudio\proj.win32”中的“libCocostudio”项目文件。

图2-9 添加库目录

3)添加库引用。右击项目“Piano”,之后点击“引用”,在弹出的对话框下方,点击“添加新引用…”,最后在子对话框中勾选“libCocostudio”,如图2-10所示。

图2-10 添加附加依赖项

4)用同样的方法添加“cocos2d\cocos\ui\proj.win32”目录中的项目“libGUI”。

5)用同样方法添加“cocos2d\extensions\proj.win32”目录下的项目“libExtensions”。

完成这些操作后,我们就完成项目环境的配置。

2.3.2 加载导出文件

打开HelloWorldScene.cpp,在最上面添加如代码清单2-4所示代码,以包含文件和命名空间。

代码清单2-4添加包含文件和命名空间

        #include "HelloWorldScene.h"
        #include "cocostudio/CocoStudio.h"
        #include "ui/CocosGUI.h"
        using namespace cocos2d;
        using namespace cocostudio;
        using namespace ui;

然后找到init()函数,对其进行更改,如代码清单2-5所示,实现导出文件的加载。

代码清单2-5加载导出文件

        bool HelloWorld::init()
        {
            //////////////////////////////
            // 1. super init first
            if ( !Layer::init() )
            {
              return false;
            }
            auto widget = cocostudio::GUIReader::getInstance()->widgetFromJsonFile
              ("Piano.json");
            addChild(widget);
            return true;
        }

在代码清单2-5中,我们通过CocoStudio编辑导出的文件,再通过widgetFrom-JsonFile将这个文件导入到项目中。这里实际上创建了一个元素,我们取到它的指针,将其赋值给“widget”变量。还记得在2.1节中介绍如何将元素组合起来吗?使用的是addChild函数。所以此处我们调用addChild函数将创建好的元素插入到场景中。

编译运行代码清单2-5,即可出现我们编辑的程序了。

大家细看,会发现右下角显示着程序当前运行的信息,从中找到AppDelegate.cpp文件中的applicationDidFinishLaunching函数,在其中去掉如代码清单2-6所示的代码。

代码清单2-6设置适配模式,并关闭FPS

            // turn on display FPS
            //director->setDisplayStats(true);
            // set FPS. the default value is 1.0/60 if you don't call this
            //director->setAnimationInterval(1.0 / 60);

我们注释掉这两个函数,就可以把FPS显示关掉。这两个函数是用来检测游戏运行流畅度的,通常在开发的过程中保留,在发布游戏时隐藏。

2.4 完善功能

通过前面的学习我们已经能够将利用编辑器制作的界面导入到程序中,在这一节我们将处理点击响应,并制作一个完整的钢琴游戏,完成效果如图2-11所示。

图2-11 钢琴游戏运行效果

2.4.1 点击响应

我们使用编辑器编辑出的元素,都是以控件(Widget)的形式读入到程序中。Widget是新加入的类型,用来封装UI控件的一些基本功能,其中就封装了点击响应。我们编辑出的所有元素都应该是Widget或它的子类型。

注意

Widget类被封装在ui库中。使用它需要包含头文件CocosGUI.h,同时需要使用命名空间ui: using namespace cocos2d::ui;。

控件中的点击响应是以TouchEventListener的形式实现的。每一个Widget都可以注册一个TouchEventListener,当有与点击相关的事件发生时,就会调用注册的TouchEventListener。简单说来,就是在点击的时候调用某个函数,然后在这个函数中实现自己想要的处理。

我们可以使用Widget中的addTouchEventListener函数来添加点击响应。在使用此函数时我们注意到它的第二个参数是SEL_TouchEvent类型,按F12跳转到它的定义,可以看到如下代码:

        typedef void (Ref::*SEL_TouchEvent)(Ref*,TouchEventType);
        #define toucheventselector(_SELECTOR) (SEL_TouchEvent)(&_SELECTOR)

SEL_TouchEvent被定义成一个函数类型,函数的参数和返回值在typedef中已做出说明,因此我们需要声明一个类型相同的函数类型。使用toucheventselector宏,可以将我们的函数转化为SEL_TouchEvent类型。

知道了原理,接下来我们动手创建自己的响应。

首先在HelloWorldScene.h的HelloWorld类中添加一个函数,代码如下:

        void touchButton(cocos2d::Ref* object,cocos2d::ui::TouchEventType type);

然后在HelloWorldScene.cpp中实现它,代码如下:

        #include "SimpleAudioEngine.h"
        void HelloWorld::touchButton(Ref* object,ui::TouchEventType type)
        {
            CCLOG("Touch Button");
          CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/Do.wav");
        }

在这段实现代码中,我们播放一个声效。CocosDenshion是Cocos2D-X的声音播放模块,它是一个单件类,要播放声效只要通过getInstance函数取到它的实例,然后再调用playEffect函数就可以。现在我们还没有声音。在随书光盘的本章资源文件的Resources中,找到声音文件夹sound将其复制到项目的Resources目录下。

技巧

CCLOG的作用是在终端中输出一行日志。灵活运用日志可以极大提高调试的效率。

最后我们要在HelloWorld::init函数中为按钮增加TouchEventListener,代码如下:

        auto buttonWidget =dynamic_cast<ui::Button*>(widget->getChildByName("Main")
                              ->getChildByTag(11));
        buttonWidget->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));

提示

在Cocos2D-X 3.2版本中,也可以通过调用buttonWidget->addTouchEventListener (CC_CALLBACK_2(HelloWorld::touchButton,this)); 来绑定点击。使用这种方式需要将touchButton函数的第二个参数类型更改为Widget::TouchEventType。

在上面的代码中,可以看到如何找到特定的按钮。widget是刚才我们通过Json文件创建的元素,也是控件载入到程序中的根节点,就是我们在编辑器中“对象结构”中的根节点。通常可以采用名字和数字标记(Tag)来标识控件,如图2-12所示。这里我们使用getChildByName取到我们的拖动区域,然后再通过getChildByTag取到按钮。

图2-12 更改名字与Tag

注意

此处名字和Tag必须与编辑器中“常规”项的“名字”和“Tag”配置对应,否则无法找到所要的控件。

编译运行,点击按钮就能听见声音了。

2.4.2 补齐整套琴键

目前为止,我们已经成功编辑了一个按键,并且实现了点击按键发出声音。接下来我们把缺少的按键补齐,做一个套完整的琴键。

首先分析一下要实现哪些:白键7个,黑键5个,每一个按键需要有一个对应的声音文件。将声音文件与对应按键建立关系是目前面临的问题。

这里我们采用这样一个策略:通过Tag来找到对应的琴键,通过琴键的名字来找到声音文件。每一个八度在Tag中的编号占20个。例如:白键分别是1~7,黑键是11~15。然后下一个八度再从21~27,以此类推。而它们的名字就叫:Do,Ri,Mi等。我们取到按键后,再去找它的名字,根据名字来对应如“Do.wav“之类的声音文件。

分析清楚了思路,接下来我们打开UI编辑器中的项目,在其中添加多个琴键。

1)调整好所有琴键的位置。

2)确保“属性”→“常规”中勾选“交互”,然后编辑每个琴键的名字和Tag。其中,黑键用#来表示,如Do#,高八度用H来表示,如DoH。

注意

在完成编辑后记得在对象结构树中将黑键调整到白键的下面,这样才能在点击黑键时优先捕获点击消息。

这里编辑了三组按键,完成后大概如图2-13所示。

图2-13 琴键编辑完成示意图

编辑完成后,将其导出并复制到工程中。

编辑好了琴键,我们再来关联响应。像2.4.1节中介绍的,将TouchEventListener注册到按钮上,更改init函数如代码清单2-7所示。

代码清单2-7为添加Listener

        bool HelloWorld::init()
        {
            //////////////////////////////
            // 1. super init first
            if ( !Layer::init() )
            {
                return false;
            }
            auto widget = cocostudio::GUIReader::getInstance()->widgetFromJsonFile("Piano.
            json");
            addChild(widget);
            //auto buttonWidget =dynamic_cast<ui::Button*>(widget->getChildByName
            ("Main") ->getChildByTag(11));
            //buttonWidget->addTouchEventListener(this,toucheventselector(HelloWor
            ld::touchButton));
            auto main = widget->getChildByName("Main");
            for(int i = 10;i<70;++i)
            {
                auto buttonWidget = dynamic_cast<ui::Button*>(main->getChildByTag(i));
                if(buttonWidget)
                {
                          buttonWidget->addTouchEventListener
                                      (this,toucheventselector(HelloWorld::touchButton));
                    }
              }
              return true;
        }

我们参考先前挂载点击的方式,先调用getChildByName函数取到组件的根节点,然后对Tag从10到70进行遍历,如果有对应的按钮对象,就绑定点击响应。

最后更改Listener函数,如代码清单2-8所示。

代码清单2-8修改响应函数

        void HelloWorld::touchButton(Ref* object,ui::TouchEventType type)
        {
          //CCLOG("Touch Button");
          //CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/Do.wav");
          auto button  =dynamic_cast<Button*>(object);
          if(button && type == TouchEventType::TOUCH_EVENT_BEGAN)
          {
              char buf[32]={0};
              std::string name = button->getName();
              sprintf(buf,"sound/%s.wav",name.c_str());
              CCLOG("Sound Name is:%s",buf);
              CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(buf);
          }
        }

在响应函数中,被点击的对象作为Ref传入到函数中。对传入的对象进行类型转换,就可以取出名字,然后我们拼出一个声音文件的路径名。当目标对象被按下、点击移动、点击结束、点击取消时都会调用这个函数。这里我们需要在点击开始时进行逻辑处理。

编译运行,点击琴键就可以演奏了。

2.5 安装到手机中

我们编写的是移动程序,所以一切都得以安装到手机中为准。在这一节中我们来看看如何把钢琴游戏安装到手机中。

2.5.1 安装Java环境

由于Andoroid是由Java语言开发出来的,因此我们首先要安装Java的运行基础:JDK。找到JDK的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html,打开后的下载界面如图2-14所示。

图2-14 JDK下载界面

笔者使用的是Windows 7的64位系统,因此选择最后一项下载。下载后运行安装,将路径保存到C:\Java\JDK\目录下。在安装过程中会提示安装jre,将其安装到C:\Java\Jre文件夹下。

安装完Java后,再来安装Android SDK。进入Android开发者官网(http://developer. android.com/sdk/index.html)下载开发Android程序使用的ADT包。它是一个集成了Android SDK组件的Eclipse,使用它可以直接开发Android程序,而省去了在原版Eclipse中安装插件的烦恼。下载后解压,将其重命名为ADT,并放置在C:\Tools文件夹下,这个文件路径可以根据自己的需要更改。如果需要运行Eclipse,打开ADT文件夹,运行Eclipse.exe即可。

安装好Android SDK后,还需要安装编译C++的NDK。到NDK官方网站(http://developer.android.com/tools/sdk/ndk/index.html)下载最新的NDK。下载完成后解压到C:\Tools目录下,将其重命名为ndk-r9d。

最后安装ANT。打开ANT官网(http://ant.apache.org/bindownload.cgi)下载ANT。下载后解压到C:\Tools目录下,将其重命名为ant。

2.5.2 配置Cocos2D-X编译环境

打开“命令与提示符”,运行Cocos2D-X根目录下的setup.py文件,设置编译环境,代码如下:

        C:\Users\Fansy>cd C:\OutFile\cocos2d-x-3.2
        C:\OutFile\cocos2d-x-3.2>setup.py
        Setting up cocos2d-x...
        -> Adding COCOS2D_CONSOLE_ROOT environment variable... ALREADY ADDED
        -> Looking for NDK_ROOT envrironment variable... NOT FOUND
              Please enter its path (or press Enter to skip): C:\Tools\ndk-r9d
        ADDED
          -- Added: NDK_ROOT = C:\Tools\ndk-r9d
        -> Looking for ANDROID_SDK_ROOT envrironment variable... NOT FOUND
              Please enter its path (or press Enter to skip): C:\Tools\ADT\sdk
        ADDED
          -> Added: ANDROID_SDK_ROOT = C:\Tools\ADT\sdk
        -> Looking for ANT_ROOT envrironment variable... NOT FOUND
              Please enter its path (or press Enter to skip): C:\Tools\ant\bin
        ADDED
          -> Added: ANT_ROOT = C:/Tools/ant/bin
        Set up successfull:
              NDK_ROOT was added into registry
              ANDROID_SDK_ROOT was added into registry
              ANT_ROOT was added into registry
        Please restart the terminal or restart computer to make added system variables t
        ake effect

运行完成后,即完成了环境变量的设置。

注意

配置完环境变量需要重新启动机器。

2.5.3 编译项目

在运行编译之前,我们需要更改Android对应的make文件。找到程序根目录/proj. android/jni/Android.mk文件,将其内容更改为如下:

        LOCAL_PATH := $(call my-dir)
        include $(CLEAR_VARS)
        LOCAL_MODULE := cocos2dcpp_shared
        LOCAL_MODULE_FILENAME := libcocos2dcpp
        LOCAL_SRC_FILES := hellocpp/main.cpp \
                        ../../Classes/AppDelegate.cpp \
                        ../../Classes/HelloWorldScene.cpp
        LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes  \
                            ../../cocos2d/cocos \
                            ../../cocos2d/cocos/editor-support
        LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
        LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
        LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
        LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static
        include $(BUILD_SHARED_LIBRARY)
        $(call import-module,2d)
        $(call import-module,audio/android)
        $(call import-module,Box2D)
        $(call import-module,editor-support/cocostudio)

完成这样的更改后,在编译时会编译CocoStudio库。更改这个文件后,即可编译程序了。打开“命令与提示符”,进入到C:\Code\HelloWorld目录中,运行如下命令:

        cocos run -p android -j 4

编译运行后即可将程序编译出Android包。编译好的文件会放置在“根目录\bin\debug\android”中。使用数据线将文件复制到手机上安装,即可在手机上运行游戏。

2.6 小结

通过这章我们认识了Cocos2D-X程序的基本层次结构,并学习了如何通过编辑器编辑一个界面。在导出编辑好的界面后,我们可以通过接口将其加载到程序中。随后学习了如何制作点击响应的回调函数,构成一个完整的程序。最后还学会了如何打包并安装到Android手机上。在下一章中,我们将看到,如何使钢琴程序的元素更加丰富。