cocos 添加插件
下面将详细介绍 Cocos 添加插件相关内容,主要流程如下:
1、Cocos2d-x 项目的执行流程
Cocos2d-x 和 Python 的版本更迭速度快且兼容性不佳,这给开发者带来了一些不必要的麻烦。本文使用的是 Cocos2d-x 3.1 版本,创建好项目后,在 pro.win32
中打开 VS 工程。
任何 C++ 程序,无论项目规模大小,其与操作系统的接口都是通过 Main
函数实现的。需要注意的是,程序中调用的自定义函数和 main
函数不一定要放在同一个文件中。例如,可以在 main.c
文件中存放 main
函数,在另一个文件中编写要在 main
函数里调用的函数,最后在编译器将代码编译成可执行文件时,通过连接器连接这两个文件,形成最终的程序。
转到 run
函数可以看到,代码注释提示需要初始化一个应用实例,划红线处的函数应该就是初始化函数。若初始化失败,整个程序将立即退出。
转到该函数后,会发现其中包含一些初始化函数,划红线的代码用于创建一个场景,可理解为创建了一个大的框架。查看该函数的定义,执行的是 bool HelloWorld::init()
函数。这个函数内部包含插入图片、插入文字等代码,也就是说,执行 Cocos2d-x 程序时最初看到的内容,都是由该函数内的代码实现的。因此,重写这个方法,就能按照自己的想法初始化窗口。
2、如何使用 Sprite 控件
Sprite
控件与 2D 图像相关,可使用以下函数创建 Sprite
精灵对象,从而在场景中添加 2D 图像,之后需使用 addChild
方法将其添加到场景中。
static Sprite* create(const std::string &filename);
参数说明
filename
:包含路径的图像文件名,例如"scene1/monster.png"
。
返回值
返回自动释放的 Sprite
对象。创建后,Sprite
的尺寸大小与图像相同,且偏移被置为 (0, 0)
。
运行程序后,虽能看到图片显示,但位置可能不对,这就涉及到“锚点”的概念。锚点类似于定位点,每个通过 addChild
方法添加的节点都有一个锚点,默认情况下为 (0.5, 0.5)
。可以使用 s->setAnchorPoint(Point(0, 0));
方法设置锚点,具体用法可查阅官方 API:http://cn.cocos2d-x.org/doc/cocos2d-x-3.0/d8/de9/groupspritenodes.html#gac1be6ca229d92a1a145fda8a7eece771
3、Cocos2d-x 之 Director、Scene、Layer
从上面的分析可知,程序初始化时会初始化一些变量,第一行是初始化 Director
,它可类比为导演。在 Cocos2d-x - 3.0x 引擎中,采用节点树形结构管理游戏对象。一个游戏可划分为不同的场景,一个场景又可分为不同的层,一个层可拥有任意个可见的游戏节点。Director
是整个引擎的核心,负责管理游戏场景的转换、游戏的暂停等,就像真正的导演一样。整个项目只有一个 Director
对象,通过 getInstance
方法初始化创建。
Scene
是游戏的场景,通过初始化函数创建。在创建场景的函数 createScene
中,会包含创建一个层(Layer
)。这三个对象存在密切的逻辑关系。
开发游戏时,首先要创建 Director
对象,设置游戏的各种参数;然后为游戏创建不同的场景,即大的背景、平台等;在此基础上创建 Layer
对象,并将所需的游戏元素(通过 addChild
方法添加的节点)放在层上。
4、Cocos2d-x 是如何呈现图形的
由于 applicationDidFinishLaunching()
是程序的入口,项目会自动生成一些创建场景的代码。为了深入了解 Cocos2d-x 呈现图形的原理,我们可以注释掉自动生成的代码,自行编写。
bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLView::create("My Game");
director->setOpenGLView(glview);
}
// 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);
// create a scene. it's an autorelease object
Scene *scene = Scene::create(); // 创建一个场景
Layer *layer = Layer::create(); // 创建一个层
scene->addChild(layer); // 在场景中添加一个层
Sprite *s = Sprite::create("dota2.jpg"); // 创建一个 2D 图像元素
s->setAnchorPoint(Point(0, 0)); // 设置锚点
layer->addChild(s); // 将节点加入层中
// run
director->runWithScene(scene);
return true;
}
代码中的具体功能已添加注释。
5、LOG 控件
LOG
控件类似于 printf
函数,是一个用于输出信息的 API。
6、MessageBox 控件
MessageBox
控件的功能与 MFC 中的类似,都是用于显示弹窗信息,具体使用方法可查阅官网文档。
补充说明
Size size = Director::getInstance()->getVisibleSize(); // 获取屏幕可见区域的大小
这句话很实用,可用于获取当前屏幕可见区域的大小尺寸。
7、LabelTTF 文本标签控件
使用 LabelTTF
文本标签控件的步骤与使用其他标签基本相同,以下是示例代码:
bool HelloWorld::init() {
// 1. super init first
if ( !Layer::init() ) {
return false;
}
Size size = Director::getInstance()->getVisibleSize(); // 获取屏幕可见区域的大小
LabelTTF *label = LabelTTF::create();
label->setString("hello xuran"); // 设置文本标签内容
label->setFontSize(36); // 设置文字大小
label->setPosition(size.width/2, size.height/2); // 设置位置
addChild(label);
return true;
}
8、TextFieldTTF 控件的使用
TextFieldTTF
控件用于在场景中添加文本输入框,但添加后需要启动输入法才能使用键盘输入。
bool HelloWorld::init() {
// 1. super init first
if ( !Layer::init() ) {
return false;
}
Size size = Director::getInstance()->getVisibleSize(); // 获取屏幕可见区域的大小
TextFieldTTF *tf = TextFieldTTF::textFieldWithPlaceHolder("Please input words","宋体",36); // 根据各项参数创建一个文本编辑框
tf->setPosition(size.width/2, size.height/2); // 设定其位置在屏幕中间
addChild(tf);
auto listener = EventListenerTouchOneByOne::create(); // 设立一个事件监听器
listener->onTouchBegan = [tf](Touch *t, Event *event) {
if(tf->getBoundingBox().containsPoint(t->getLocation())) { // 获取触摸点并且判断触摸点是否包含在文本编辑框内
tf->attachWithIME(); // 为这个控件启用输入法
} else {
tf->detachWithIME();
}
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, tf); // 利用导演添加一个对事件的监听器
return true;
}
9、自定义一个类
如果想在界面中添加 2D 图像,且不想在 init
函数中使用 Sprite
的方式添加,而是实现一些自定义功能,就需要自定义一个类。由于要使用自己创建的类在场景中添加 2D 图像节点,因此需要继承 Sprite
类,因为该类提供了很多实用的功能。
以下是自定义 ball
类的示例代码:
ball.h
#pragma once
#include <iostream>
#include "cocos2d.h"
using namespace cocos2d;
class ball: public Sprite {
public:
virtual bool init();
static ball* create() {
ball* b = new ball();
b->init();
b->autorelease();
return b;
}
};
ball.cpp
#include "ball.h"
bool ball::init() {
initWithFile("ball.png");
return true;
}
在场景类的 init 函数中使用
auto b = ball::create();
b->setPosition(200, 200);
addChild(b);
通过自定义类,可以实现之前使用 Sprite
的功能,还能在此基础上进行扩展。
10、Menu 控件的使用
Menu
是菜单控件,MenuItem
是菜单项,菜单是多个菜单项的集合。可以创建文字版或图片版的菜单项,但 Menu
集合只接受 MenuItem
作为子元素。
auto menu = Menu::create(MenuItemImage::create("5.png", "6.png", [](Object *obj) {
log("menu item touched");
}), NULL);
addChild(menu);
上述代码创建了一个菜单控件,并使用 MenuItemImage::create
创建了一个图片菜单项,指定了选择菜单项前后的图片,以及选中菜单项后的回调函数。