刚刚开始看cocos2dx。记录一下自己的学习状况,也是为了以后忘了还有个保存的地方,谨记。
cocos2d-x 3.6包中的helloworld项目名为cpp-empty-test。
运行结果如图:
很明显这个图片的范围超了(这是分辨率自适应),不过本文主要不是讲这个,这个后面再说。
首先贴main函数,这是所有程序的入口。
#include "main.h"
#include "../Classes/AppDelegate.h"
USING_NS_CC;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
return Application::getInstance()->run();
}
main函数在我的理解中,就做了两件事,初始化一个AppDelegate类。
Application是个单例模式,AppDelegate类是其子类,按照我的理解,AppDelegate类初始化完成后,Application即已经有了对象,getInstance()得到唯一实例,运行该实例。
内部如何运行暂且不管(初学暂时还不清楚),接下来会到达AppDelegate.cpp中,执行顺序如下。
void AppDelegate::initGLContextAttrs()
{
//设置 OpenGL context 属性,目前只能设置6个属性
//red,green,blue,alpha,depth,stencil
//不过我在helloworld项目中改变它并未发现有任何变化
GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};
GLView::setGLContextAttrs(glContextAttrs);
}
之后进入到applicationDidFinishLaunching(),这里可以算是游戏的入口。
bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
//director(导演:负责游戏场景的显示切换等,像电影导演一样掌控整个电影的一切) 是个单例模式的类 文档给出的解释如下
/**
@brief Class that creates and handles the main Window and manages how
and when to execute the Scenes.
The Director is also responsible for:
- initializing the OpenGL context
- setting the OpenGL buffer depth (default one is 0-bit)
- setting the projection (default one is 3D)
Since the Director is a singleton, the standard way to use it is by calling:
_ Director::getInstance()->methodName();
*/
auto director = Director::getInstance();
/**
* @brief By GLView you can operate the frame information of EGL view through some function.
*/
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLViewImpl::create("Cpp Empty Test");//这里可以设置程序显示的名字 上图中最上面的Cpp ···即为该处生成
director->setOpenGLView(glview);
}
director->setOpenGLView(glview);
/*
*根据当前的平台选择默认的设计方案大小及显示模式。
*关于ResolutionPolicy::SHOW_ALL和ResolutionPolicy::NO_BORDER详见CCGLView.h讲的很清楚,还有另外几种显示模式
*/
// Set the design resolution
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
// a bug in DirectX 11 level9-x on the device prevents ResolutionPolicy::NO_BORDER from working correctly
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
#else
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
#endif
Size frameSize = glview->getFrameSize();//默认大小
vector<string> searchPath;//保存搜索路径
/*
*根据屏幕大小,调整资源文件位置 本例中原则是根据高度大小选择不同资源文件
*调整资源文件大小
*原则是没有黑边(大概?正在试),这就是为什么结果中高会超出的原因。
*其中designResolutionSize默认大小是480*320
*/
// In this demo, we select resource according to the frame's height.
// If the resource size is different from design resolution size, you need to set contentScaleFactor.
// We use the ratio of resource's height to the height of design resolution,
// this can make sure that the resource's height could fit for the height of design resolution.
// if the frame's height is larger than the height of medium resource size, select large resource.
if (frameSize.height > mediumResource.size.height)
{
searchPath.push_back(largeResource.directory);
director->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height, largeResource.size.width/designResolutionSize.width));
}
// if the frame's height is larger than the height of small resource size, select medium resource.
else if (frameSize.height > smallResource.size.height)
{
searchPath.push_back(mediumResource.directory);
director->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height, mediumResource.size.width/designResolutionSize.width));
}
// if the frame's height is smaller than the height of medium resource size, select small resource.
else
{
searchPath.push_back(smallResource.directory);
director->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height, smallResource.size.width/designResolutionSize.width));
}
// set searching path
FileUtils::getInstance()->setSearchPaths(searchPath);
// 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
auto scene = HelloWorld::scene(); //生成scene(场景:负责显示一个游戏场景,就像电影的一个场景镜头)。
// run
director->runWithScene(scene);
return true;
}
上面的代码在auto scene = HelloWorld::scene();调用helloworld类的scene函数生成场景。如下
Scene* HelloWorld::scene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); //创建场景
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create(); //返回一个Node* 调用该函数时 会初始化HelloWorld 即调用HelloWorld::init()函数
// add layer as a child to scene
scene->addChild(layer);//将图层加入场景addChild()函数接收的是Node*对象 layer是Node的子类
// return the scene
return scene;
}
HelloWorld的头文件中以宏定义定义了create()函数。(吐个槽,为什么cocos这么多宏定义)
调用该函数时 会初始化HelloWorld 即调用HelloWorld::init()函数,如下
bool HelloWorld::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();//getVisibleSize:默示获得视口(可视区域)的大小,若不调用DesignResolutionSize(),则getVisibleSize()等于getWinSize()。(我按着翻译的,有错请指正)
auto 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
/*
*这部分基本是在图层中添加各种东西,如menu,label,sprite。
*cocos左下角是(0,0)坐标
*menu条目需要多次才能加入图层 如下顺序
*MenuItemImage MenuItemImage->setPosition menu menu->setPosition
*/
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",//选中状态的标志
CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));//设置了点击之后的回调函数
closeItem->setPosition(origin + Vec2(visibleSize) - Vec2(closeItem->getContentSize() / 2));
// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, nullptr);//应该是一个可变参数长度的函数。最后以nullptr作为收尾
menu->setPosition(Vec2::ZERO);//Vec2::ZERO 一些已经定义的位置
this->addChild(menu, 1);
/
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
auto label = LabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE);
// position the label on the center of the screen
label->setPosition(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);//第二个参数代表优先级,优先级越高的放在图层最上面 默认为0 都为0看先后
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");//背景
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize / 2) + origin);
// add the sprite as a child to this layer
this->addChild(sprite);
return true;
}
至此,最简单的例子的运行顺序就结束了。
AppDelegate::initGLContextAttrs()->bool AppDelegate::applicationDidFinishLaunching() ->HelloWorld::scene()->HelloWorld::init()->HelloWorld::scene()->bool AppDelegate::applicationDidFinishLaunching()
此外,程序中还有几个回调函数的例子。程序暂停恢复,按钮反馈。
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
Director::getInstance()->stopAnimation();
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
Director::getInstance()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}
void HelloWorld::menuCloseCallback(Ref* sender)
{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}