声 明
本教程仅用于初学cocos2dx同学使用,内容由本人(Code-Man)编写,此教程使用cocos2dx版本为3.4。本教程内容可以自由转载,但必须同时附带本声明,或注明出处。Cocos2d-CodeMonkey ,461679592。
【一】知己知彼
Hello,很高兴又跟Monkey们见面了。相信经过上一个教程大家已经打好了环境,并对C++有了一定的了解。在计算机语言里存在着这么一个
诅咒,任何一本计算机语言的教科书里都会有一句:Hello World 。哈哈哈!!
今天我也毫不例外的从HelloWorld讲起。
运行编译好的项目,如图:
头顶输出文字:HelloWorld ,中间是一张Cocos2dx的图片。是不是很像外星人?天真的傻孩子,很认真的告诉你,其实它是一个椰子,知道真相的我眼泪掉下来。
左下角的含义:
GL verts : 78 的意思是:当前场景传送给显卡的顶点数量。
GL calls:3 的意思:当前场景存在的节点数量,此处包括(文字、图片、按钮)
53.1 的意思:表示游戏当前的帧率,这经常能反映这个游戏对应这个设备来说是否存在卡顿。当帧率低于30帧以下时,是人无法接受的卡顿。市面上基本普及了60帧的设备。
0.013的意思:的意思是每一帧所处理的时间。
在看代码之前,先说以下cocos2dx的组成成分吧。
Cocos2dx的五脏六腑组成成分:
【二】寻根问底
都说戏如人生,人生如戏。其实游戏就像一场电影。当我第一次看到这张图的时候,在想这是不是要拍戏了。有导演,有场景,还有布局层,节点难道就是里面的演员吗?
其实你完全是可以这样理解啦。每一个演员都扮演着自己的角色,他们各自都有自己的特点。下面来看看他们都有什么用吧。
1.节点。
节点里面有一个比较好理解儿子(子类),就是Sprite(精灵)。这是游戏里最常见,也是最常用的元素。比如游戏的人物、武器、衣服...。当然节点下有很多的子类,节点本身并不承载任何显示在屏幕的内容(图片或者图像),但所有显示在屏幕上的内容元素都是节点的子类,可以说显示在屏幕上的元素皆为节点
2.布局层。
除精灵以为最多的元素。一个游戏离不开、背景层、暂停层、结束层。层是透明的因为有了精灵在层上,才丰富了它。把每一个层叠在一起,俯视来看,就是一个完整的游戏了。如果用过PS的可以直接理解为PS里的图层。
3.场景。
说白了就是一个箱子。里面可以装很多的层。一个游戏会有很多场景,如:首页、载入、登录、游戏界面。一个场景包括多个层,一个层包括多个精灵。
4.导演。
主导者,就像现实中的导演一样,场景的切换,开始、暂停、继续都是导演说的算。它控制着整个游戏的流程。
代码部分:
本人用的是Xcode,VS的Monkey们不用太过在意开发工具的不一样,其实内容都是一模一样的。
1.HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
//很明显HelloWorld继承了我们的布局层,所有HelloWorld也是一个层
class HelloWorld : public cocos2d::Layer
{
public:
//结合上面的所学的知识,聪明的Monkey可以,已经通过英文已经猜到这个方法的作用了吧。
//没错它就是创建一个场景。也就是创建一个箱子,里面装了我们的布局层
static cocos2d::Scene* createScene();
//virtual关键字: 如果C++不是学得特别多的暂可忽视。
//这个函数主要是初始化,这个类中所用到的变量等。
virtual bool init();
//结合第一张图片,我们可以看到右下角的那个按钮。这个方法也就是那个按钮,
//按下去之后所要调用的方法。按下去之后的事情都发生在这个方法里。
void menuCloseCallback(cocos2d::Ref* pSender);
//暂可不予理会,你只需要知道,没有它,HelloWorld就不能创建出来。
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
2.HelloWorldScene.cpp
#include "HelloWorldScene.h"
USING_NS_CC;
//创建场景方法
Scene* HelloWorld::createScene()
{
// 首先,先创建一个场景。在Cocos2dx里面,
//基本90%以上的Node(节点,场景也是一个Node)都可以用crate 创建出来。
auto scene = Scene::create();
// 创建一个层,这个层也就是类自己本身
// 好奇的朋友会问。HelloWorld是自己创建的类,可是我们并没有create这个方法,哪里来的呢?
// 还记得,HelloWorldScene.h文件里的:CREATE_FUNC(HelloWorld); 吗?没错就是来自于这里
// 为什么会有create,暂不讲解。有兴趣的可百度,C++ 宏定义。
auto layer = HelloWorld::create();
//add(添加的意思),Child(儿子),就是把括号里的儿子添加到自己身上。哈哈哈,很好理解吧。
scene->addChild(layer);
// 返回这个场景,交给谁?没错就是导演,导演在哪?,暂不告诉你,下期会讲解(要是没讲,记得吐槽我)。
return scene;
}
//初始化
bool HelloWorld::init()
{
// 注意:这里比较坑,刚学的时候被坑过一次。在这里只需记住一句话:有了你爸才能有你。你爸就是Layer(不是李刚)
// 初始化Layer(HelloWorld的爸爸)不为真,才往下面执行
if ( !Layer::init() )
{
return false;
}
// 导演,导演终于见到了导演。getInstance()这个方法,在cocos2dx里面经常用到,都是一个单例,单例是什么?暂不讲解。
// 只要知道这样就能拿到导演了,然后再拿到屏幕的大小
Size visibleSize = Director::getInstance()->getVisibleSize();
// 拿到屏幕的原点坐标,关于cocos2dx坐标的知识,会再后续文章单独讲解
Vec2 origin = Director::getInstance()->getVisibleOrigin();
// 创建一个按钮,看到没?又是create,
// 1.第一个参数:正常状态下的图片,2.按下去时候的图片,3.回调函数,没错就是HelloWorldScene.h文件里的那个
// 在cocos2dx 拥有很多的宏定义,都是已大写形式存在。能方便开发偷懒,哈哈哈!!
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
//设置这个按钮的位置
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
// 创建一个按钮层,它负责管理,添加到它上面的所有按钮,记住后面一定要跟一个NULL,
// 暂不解释,可作为个人思考,真想知道就扣扣我吧,其实我寂寞了,O(∩_∩)O哈哈~
auto menu = Menu::create(closeItem, NULL);
// 因为儿子已经设置了坐标,所有父亲的坐标设置为(0,0)就好了,Vec2::ZERO = Vec2(0,0)
// 儿子的坐标永远相对于父亲的坐标,后期会详解坐标
menu->setPosition(Vec2::ZERO);
//添加儿子咯,不用说,可是1是什么?先不用管,总之很厉害,哈哈哈
//好吧还是告诉你,1的意思就是:谁在上面,谁在下面?(有点邪恶)。数字越大,就越靠上,文字的是“1” 椰子图片的是“0”,所以文字在椰子图片上面。
//this是谁?HelloWorld自己,常用关键字,别忘了!!!
this->addChild(menu, 1);
// 创建文字,也就是我们第一张图看到的文字:HelloWorld
// 参数1.显示的文字,2.字体:也是就资源文件里的文件,3.字体大小
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
//哎,自己领悟吧这个....
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
//添加儿子
this->addChild(label, 1);
// 添加第一张图片看到的里面的那个外星人(其实我是椰子啦!!)
// 参数1:图片名
auto sprite = Sprite::create("HelloWorld.png");
//不解释
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
//不想解释,不要问为什么,有钱任性!!!!
this->addChild(sprite, 0);
//返回真干嘛?那你看谁调用它咯。提示:CREATE_FUNC(HelloWorld);
return true;
}
//按钮的回调,按了按钮之后会发生的事情都在这了。。。
void HelloWorld::menuCloseCallback(Ref* pSender)
{
// 这个,不要管总之很厉害。。
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
//导演说:杀青了,电影(游戏)结束。
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}