这篇我们来分析一下关于cocos2d-x中的HelloWorld究竟是如何在win32平台上实现运行的。
还记得上一篇创建的工程吗?进入上一篇所创建的TestFor_3_9的项目的目录,来看看该工程的目录结构:
在win32平台开发我们关心的主要是Classes、proj.win32和Resource这三个文件夹。当然,还有其它文件如cocos2d是源代码相关的文件,还有存放其它平台的项目文件夹,均以"proj."开头。下面的两个是配置问件,可以不用去了解它。
好,现在来看看主要的三个文件夹里分别有什么?
Classes文件夹:存放所有跨平台的类,所以以后创建类的时候都需要放在这里;
此时有两个类:HelloWorld和Appdelegate这两个类文件:
proj.win32文件夹:里面就是工程的编译文件了;
Resource文件夹:存放所有的资源文件
好了,然后打开解决方案,启动调试,,最后会出现如下结果:
Ok,以上只是对上节课进行简单回顾以及对项目目录的的了解。下面就进入正题吧~
在解析HelloWorld之前,我们需要明白cocos2d-x中的几个概念性的类:
1.节点类(Node);
2.场景类(Scene);
3.导演类(Director);
#include "main.h"
#include "AppDelegate.h"
#include "cocos2d.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();
}
Application* Application::getInstance()
{
CC_ASSERT(sm_pSharedApplication);
return sm_pSharedApplication;
}
Application * Application::sm_pSharedApplication = 0;
Application::Application()
: _instance(nullptr)
, _accelTable(nullptr)
{
_instance = GetModuleHandle(nullptr);
_animationInterval.QuadPart = 0;
CC_ASSERT(! sm_pSharedApplication);
sm_pSharedApplication = this;
}
int Application::run()
{
...
// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())
{
return 1;
}
...
return 0;
}
bool AppDelegate::applicationDidFinishLaunching() {
// 初始化导演类,并创建出窗口
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
glview = GLViewImpl::createWithRect("hello3.9", Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
glview = GLViewImpl::create("hello3.9");
#endif
director->setOpenGLView(glview);
}
// 这里是帧率的显示,也就是窗口左下角的一些信息,如果设置为false,则左下角的数字便会消失
director->setDisplayStats(true);
//这里是设置渲染帧率,此时每秒60帧
director->setAnimationInterval(1.0 / 60);
// Set the design resolution
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
Size frameSize = glview->getFrameSize();
// if the frame's height is larger than the height of medium size.
if (frameSize.height > mediumResolutionSize.height)
{
director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is larger than the height of small size.
else if (frameSize.height > smallResolutionSize.height)
{
director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is smaller than the height of medium size.
else
{
director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
}
register_all_packages();
// 在这里调用HelloWorld场景的创建
auto scene = HelloWorld::createScene();
// 在这里运行场景
director->runWithScene(scene);
return true;
}
看到最下面的两行,它调用了HelloWorld这个类的createScene()静态方法得到一个场景,然后通过导演类来运行这个场景!
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
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);
};
#endif // __HELLOWORLD_SCENE_H__
static cocos2d::Scene* createScene(); //这句是实现一个静态方法,将返回一个场景
virtual bool init(); //这句是重写了init方法,可以在这里实现一些初始化工作
void menuCloseCallback(cocos2d::Ref* pSender);//这是一个回调函数
#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; \
} \
}
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 这里的create真是和上面的CRATE_FUNC宏里面实现的一样,创建一个场景
auto scene = Scene::create();
// 调用HelloWorld层的create函数创建,也就是在.h中宏的调用
auto layer = HelloWorld::create();
// 然后在这个场景中把这个HelloWorld层加进来
scene->addChild(layer);
//返回这个场景
return scene;
}
// 这里就是初始化函数实现了
bool HelloWorld::init()
{
//////////////////////////////
//这里会需要调用一下父类的init(),以保证层的正常创建,如果初始化失败,返回false
if ( !Layer::init() )
{
return false;
}
//得到屏幕大小和坐标位置
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
/////////////////////////////
// 这里添加一个菜单,也就是左下角的按钮
//这里需要说明的是,菜单需要先创建,然后再创建菜单条目,最后再把菜单条目添加到菜单中
// 添加菜单条目(菜单条目的类型有多种创建方式,这里就不一一列举,一下是MenuItemImage,即图片菜单条目的创建)
//这里有三个参数,第一个是正常状态,也就是未被点击的时候,第二个是被选择状态,第三个调用的方法,此时是调用menuCloseCallback这个方法
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));
// 菜单的创建
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
//把菜单添加到HelloWorld这个层中
this->addChild(menu, 1);
/////////////////////////////
// HelloWorld场景中还有一个Label,也就是标签,标签的创建也有多种,这里是TTF标签
//这里有三个参数,第一个是显示的标签,第二个是字体格式,第三个是字体大小
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));
// 把标签添加到HelloWorld层中
this->addChild(label, 1);
/////////////////////////////////////
// HelloWorld层中还有一张图片,图片由精灵创建
auto sprite = Sprite::create("HelloWorld.png");
// 为图片精灵设置位置
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
//把图片精灵添加到HelloWorld层中
this->addChild(sprite, 0);
return true;
}
//这个是菜单条目回调函数,里面调用了退出这个应用程序的操作
void HelloWorld::menuCloseCallback(Ref* pSender)
{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
#include "AppDelegate.h"
#include "HelloWorldScene.h"//头文件包含,这个细节可不要忘记哦
USING_NS_CC;//使用cocos2dx的命名空间
static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);//窗口设计的大小
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);
AppDelegate::AppDelegate() {
}
AppDelegate::~AppDelegate()
{
}
//Opengl的一些文本属性
void AppDelegate::initGLContextAttrs()
{
//set OpenGL context attributions,now can only set six attributions:
//red,green,blue,alpha,depth,stencil
GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};
GLView::setGLContextAttrs(glContextAttrs);
}
static int register_all_packages()
{
return 0; //flag for packages manager
}
//程序进入后台时调用
void AppDelegate::applicationDidEnterBackground() {
Director::getInstance()->stopAnimation();
// SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}
// 程序恢复前台时调用
void AppDelegate::applicationWillEnterForeground() {
Director::getInstance()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}