屌丝用不起Mac,只能选Windows或者Linux(个人喜好Ubuntu,Redhat还是做服务器更实用点)作为开发环境。由于Ubuntu装在虚拟机上,况且我编译链接、gcc、gdb、makefile仅懂皮毛,用makefile和gdb编译调试大型程序简直要我老命,我还是老老实实用Vs2012+VsVim的组合比较好。环境搭建可见点击打开链接,该文档写的相当清楚,对此不再累述。
没图说个几把。。。
上图
二、基本程序结构
既然有人愿意看我的文档,一定是比我更新手的新手(小菜向小小菜问好,哈哈)了,讲菜单创建前先说说程序的结构吧。LibAudio、libchipmunk、libcocos2d是依赖项目,HelloCpp是我们主要开发的项目。点开win32,里面有main.h,main.cpp文件,看到main函数,大家是不是感觉很爽?爽就对了,不用怀疑,这就是程序的入口。
没代码说个几把。。。
#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();</span>
16、17行的两句就是程序的入口了,我们可以顺着这个入口一直往里看。对的,我们看到了Class里面有AppDelegate.cpp和AppDelegate.h两个文件,AppDeletegate.cpp代码如下:
#include "AppDelegate.h"
//#include "HelloWorldScene.h"
#include "StartScene.h"
USING_NS_CC;
AppDelegate::AppDelegate() {
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLView::create("My birds");
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
//auto scene = HelloWorld::createScene();
auto scene = StartScene::createScene();
// run
director->runWithScene(scene);
return true;
}
// 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::getInstance()->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::getInstance()->resumeBackgroundMusic();
}
31是自带的用来创建场景(Scene)的语句,这里我们不用自带的,我们自己建(好吧,在HelloWorld上改也行,只是为了熟悉,还有不喜欢HelloWorld这个类名)了一个与HelloWorld一样的StartScene类,没代码说个几把,下面是自建的StartScene,先给出StartScene.h。
#ifndef __START_SCENE_H__
#define __START_SCENE_H__
#include "cocos2d.h"
class StartScene :
public cocos2d::Layer
{
public:
StartScene(void);
virtual ~StartScene(void);
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// a selector callback
void menuCallback(cocos2d::Ref* pSender);</span>
// implement the "static create()" method manually
CREATE_FUNC(StartScene);
};
#endif
注意,17行是被我修改过了的,这个是回调函数,大家一定在想为什么我把原来menuCloseCallback单词中的Close去掉了,不用怀疑,我就觉得这名字不好,我这个回调函数不是仅仅用来关闭程序的。。。仅仅只是名字上的区别而已,关键在于传入的参数以及函数内部的实现。
再给出StartScene.cpp
#include "StartScene.h"
#include "MainScene.h"
USING_NS_CC;
StartScene::StartScene(void)
{
}
StartScene::~StartScene(void)
{
}
Scene* StartScene::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = StartScene::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
bool StartScene::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto labelStart = LabelTTF::create("Start Game", "Arial", 24);
auto labelExit = LabelTTF::create("Exit Game","Arial",24);
auto startItem = MenuItemLabel::create(labelStart,CC_CALLBACK_1(StartScene::menuCallback,this));
startItem->setTag(1);
startItem->setPosition(Point(100,150));
auto exitItem = MenuItemLabel::create(labelExit,CC_CALLBACK_1(StartScene::menuCallback,this));
exitItem->setTag(2);
exitItem->setPosition(Point(100,100));
auto menu = Menu::create(startItem, exitItem, NULL);
this->addChild (menu,1);
return true;
}
void StartScene::menuCallback(Ref* pSender)
{
int tag = ((Node*)pSender)->getTag();
switch(tag){
case 1:
CCLOG("go to main_scene");
Director::getInstance()->replaceScene(MainScene::createScene());
break;
case 2:
CCLOG("end");
Director::getInstance()->end();
break;
}
}
简单来讲,我们在42、43行创建了两个标签,设置了标签的标识(Tag用以在用户点击时区分不同标签)、位置,然后通过标签创建相对应的Menu标签,再将Menu标签加入Menu菜单里面。
CC_CALLBACK_1这个函数比较重要,通过这个我们可以调用场景的回调函数,我这里是调用StartScene场景的menuCallback回调函数。然后我们可以看看menuCallback的定义,通过59行上的tag来判断我们在界面上点击了哪个标签,点击的那个标签的Tag标识(如46行的1、49行的2)将会被传过来。从而通过回调函数来执行场景的跳转。
在本例中,当点击startItem时将传来1,即执行case 1 里面的命令,将场景替换成MainScene(此处MainScene和自带HelloWorld类完全一样,就名字上有所区分);当点击exitItem时将传来2,执行case2里的命令,退出程序。 如果菜单有多项,也可以通过类似方法去增加菜单项,对此不再累述。