Cocos2d从入门到睡觉:学习(一)

时间:2023-02-07 20:21:56

  在暑假闲着的时候,突然想着去做一款游戏,脑子里游戏大概的模样都想得差不多了,就差怎么去敲代码了,在之前接触过一款图形库Easyx,也看到很多人用它做出了各种各样的小游戏,因为计算机图形老师叫做实验,实现书上的一些图形绘制的算法,例如绘制线,圆,线段剪裁,多边形剪裁之类,就找到了Easyx,在数字图像处理的时候也用过,不过里面的GetImageBuffer方法对一些图片的stride值不为0,处理的时候就会出现问题,用GDI+的BitmapData,以单个像素中的单个字节区访问,比起GetImageBuffer直接获取一个显存指针好一些。。。
  总之Easy做游戏的话,简单的还可以,要是复杂了,感觉会很繁琐,于是乎就百度找到了Cocos2dx,
官网:http://www.cocos.com/docs/native/,里面介绍了一些Cocos2dx的一些基本概念。
例如,场景,层,导演,精灵,坐标系….很多很多基本概念,与如何使用Cocos2dx的一些基本方法。
Cocos2d从入门到睡觉:学习(一)
  所以过多的一些东西我就不写了,我想写的是写代码的过程与想法。
  在写的过程中,碰到了很多C++11的新特性,感觉很奇妙,写Cocos2dx对于练习C++挺有帮助的,让我感觉自己更加的无知了= =
  由于缺乏美工,所有资源都来自网络上,还有下载的Cocos2dx有官方写的用例,去看官方写的代码对自己会很有帮助,这是Cocos2dx学习第一篇,就来新建一个项目(由于是后面来写的文章,项目中已经有了自己写的一些类文件,编译过程很久很久很久很久,所以就不想重新弄一个项目来写blog了)。
Cocos2d从入门到睡觉:学习(一)
  新建的工程src中只有(AppDelegate与HelloWorldScene),看过一些以前的教程,发现Cocos2dx 3.X之前的版本中HelloWorldScene都是继承cocos2dx::Layer类,而3.x是继承cocos2dx::Scene,虽然感觉对普通人来说没多大差异orz
  在AppDelegate.cpp中,代码中大多都是有注释的,挺友好的
  其中的:

 auto scene = HelloWorld::createScene(); 
// run
director->runWithScene(scene);

  第一个是用于添加一个HelloWorld场景,添加之后由导演director执行这个场景,然后我们去看看HelloWorldScene这个类:

class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();

virtual bool init();

// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};

  当我第一眼看到的时候挺愣了,没有以前上课时候的什么构造函数很多很多之类的,然后就瞎想会不会他们都在一个大的main函数中执行,都是临时变量,因为没看到一个new,感觉写法很奇异,其中有一个宏CREATE_FUNC(HelloWorld)吸引了我的注意,然后去看了一下这个宏的定义:

#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = nullptr; \
return nullptr; \
} \
}

  也就是说在create()里面new了一个TYPE的实例,也就是HelloWorld的实例,然后调用init去初始化,而pRet在初始化后就会调用一个叫autorelease()的函数,在后面天数的摸索中发现了这个函数相当于一个引用计数,以前看过一篇引用计数,也学着写过,突然间有一种感觉,感觉C++很神奇。
然后再来看看新建项目后,我们的HelloWorldScene类的init()方法:

bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Scene::init() )
{
return false;
}

auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
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));

// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);

/////////////////////////////
// 3. add your codes below...

// add a label shows "Hello World"
// create and initialize a label

auto label = Label::createWithTTF("你好啊", "fonts/Marker Felt.ttf", 24);

// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));

// add the label as a child to this layer
this->addChild(label, 1);

// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");

// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(sprite, 0);
return true;
}

  其中的,只要英文勉勉强强,应该是能看懂注释的,看不懂可以百度或者有道翻译一下,我们可以发现,每个放置在场景HelloWorldScene的精灵都会addChild(sprite,0),在绘制层的顺序,默认参数值为0,表示最高优先层导入,该值越大表示该层在最后加载,若不放进场景,就无法显示,还有里面有图片菜单,也可以使用精灵菜单,菜单的create第三个参数是其回调函数,可填写或不填。
  在使用的过程中,我碰到
auto label = Label::createWithTTF("你好啊", "fonts/Marker Felt.ttf", 24);
  初始项目使用的字体无法显示中文,而更换其他字体后,会因为cpp文件保存的时候编码不是UTF-8而是GB2312(我的VS默认是这个),所以无法显示中文,解决方法是用EditPlus或者是手动把有中文字符的cpp文件编码格式保存为UTF-8,保存后也会出现一些问题,有一些字符在编译的时候编译器会报错,可以在其后面加字符 啊 或者英文字母或者 . ,当然这个方法不好用,而且不是完全之举,还是得找更好的办法。
学习(一)的内容就到此了,学习系列是记录我以前入门的方式与过程碰到的问题以及解决过程,有错误的话或者问题的留言说一下。