和很多游戏引擎一样Cocos2dx有导演(CCDirector)、场景(CCScene)、层(CCLayer)、菜单(CCMenu)、精灵(CCSprite)这些概念。
这些东西都继承了节点类(CCNode)。他们都具有(addChild)方法能将某些场景加入另一个场景中。某些精灵加入某个精灵中。这是用树做的。因为整个游戏只有一个导演类。那么也就是说这是树的根。
然后这些节点能绑定事件。
CCNode::schedule
源码中这里用了适配模式。
void CCNode::schedule(SEL_SCHEDULE selector) { this->schedule(selector, 0.0f, kCCRepeatForever, 0.0f); } void CCNode::schedule(SEL_SCHEDULE selector, float interval) { this->schedule(selector, interval, kCCRepeatForever, 0.0f); } .......
Cocos2dx有自己的一套垃圾回收装置。算法是当类被引用时+1类没有被引用时-1当为0时自动回收。
但这只是对crate()出来的类。而是用new开辟出的空间我们可以用宏定义清除。
#define CC_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0) #define CC_SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = 0; } } while(0) #define CC_SAFE_FREE(p) do { if(p) { free(p); (p) = 0; } } while(0) #define CC_SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0) #define CC_SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = 0; } } while(0) #define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0) #define CC_BREAK_IF(cond) if(cond) break
以下是我简单做的代码中的一个核心类
#include "HelloWorldScene.h" #include "SimpleAudioEngine.h" #include "GameOverLayer.h" USING_NS_CC; CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance 初始化该类,C++是在构造函数中初始化 bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayerColor::initWithColor(ccc4(0,255,0,255))) //红 绿 蓝 alpha(透明度) { return false; } #if 0 CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->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 CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); // create menu, it's an autorelease object CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu,1); //第一个参数表示层,第2个参数是z轴的位置,第二个参数越大那么就越靠前。 ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24); // position the label on the center of the screen pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); // add the label as a child to this layer this->addChild(pLabel, 1); // add "HelloWorld" splash screen" CCSprite* pSprite = CCSprite::create("HelloWorld.png"); // position the sprite on the center of the screen pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); // add the sprite as a child to this layer this->addChild(pSprite, 0); #endif CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); //获取长宽 CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); //获取原点坐标 CCSprite* pSprite = CCSprite::create("Player.png"); pSprite->setPosition(ccp(origin.x+20,origin.y+visibleSize.height/2)); this->addChild(pSprite,0); //第二个参数是显示优先级 #if 0 CCMenuItemImage *pMenuItem = CCMenuItemImage::create("button2.png", "button2.png", "button2.png", this, menu_selector(HelloWorld::responsFunc) ); pMenuItem->setPosition(ccp(30,30)); CCMenu* pMenu = CCMenu::create(pMenuItem,NULL); this->addChild(pMenu); #endif //Class::crate()不需要手动 new 需要手动释放 _projs = new CCArray; //设置飞镖 _targets = new CCArray; //设置目标 //添加一个精灵并且一开始就能移动. srand(time(NULL)); this->schedule(schedule_selector(HelloWorld::gameLogic),2); this->schedule(schedule_selector(HelloWorld::update)); //ps:this->schedule(schedule_selector(HelloWorld::gameLogic,2));会发生鬼畜 this->setTouchEnabled(true); CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.wav",true); _successCount = 0; return true; } void HelloWorld::update(float delta) //delta = 1.0/fps { CCArray *projToDelete = new CCArray; CCArray *targetToDelete= new CCArray; CCObject *itarget; CCObject *iproj; CCARRAY_FOREACH(_targets,itarget) { CCSprite *target = (CCSprite*)itarget; //设置当前目标转化为经理 CCRect targetZone = CCRectMake(target->getPositionX(), //获取目标的边界 target->getPositionY(), target->getContentSize().width, target->getContentSize().height); CCARRAY_FOREACH(_projs,iproj) //循环判定是否有飞镖打中目标 { CCSprite *proj = (CCSprite*)iproj; CCRect projZone = CCRectMake(proj->getPositionX(), //获取飞镖边界 proj->getPositionY(), proj->getContentSize().width, proj->getContentSize().height); if(projZone.intersectsRect(targetZone)) //如果有交集 { if(++_successCount>=5) { CCScene *overScene = GameOverLayer::scene(); CCDirector::sharedDirector()->replaceScene(overScene); //跳转场景 } projToDelete->addObject(proj); //将需要清除的飞镖和目标加入队列 targetToDelete->addObject(target); } } //end of iterate proj } //end of iterate target CCARRAY_FOREACH(projToDelete,iproj) //循环清除飞镖 { _projs->removeObject(iproj); CCSprite *proj = (CCSprite*)iproj; proj->removeFromParentAndCleanup(true); } CCARRAY_FOREACH(targetToDelete,itarget) //循环清除目标 { _targets->removeObject(itarget); CCSprite *target = (CCSprite*)itarget; target->removeFromParentAndCleanup(true); } CC_SAFE_RELEASE(targetToDelete); CC_SAFE_RELEASE(projToDelete); } HelloWorld::~HelloWorld() { CC_SAFE_RELEASE(_projs); CC_SAFE_RELEASE(_targets); } void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) { CCTouch *touch =(CCTouch*)pTouches->anyObject(); //获取触摸点坐标 CCPoint locInView = touch->getLocationInView(); //获得触摸点UI坐标 CCPoint loc = CCDirector::sharedDirector()->convertToGL(locInView); //将UI坐标转换为GL坐标 if(loc.x < 30) return; CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("pew-pew-lei.wav"); CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCSprite *proj = CCSprite::create("Projectile.png"); proj->setPosition(ccp(30,visibleSize.height/2)); double ax = 30; double ay = visibleSize.height/2; double D = sqrt(visibleSize.width*visibleSize.width+visibleSize.height*visibleSize.height); double d = sqrt((loc.x-ax)*(loc.x-ax)+(loc.y-ay)*(loc.y-ay)); double cx = (loc.x-ax)*D/d+ax; double cy = (loc.y-ay)*D/d+ay; CCMoveTo *move = CCMoveTo::create(D/320,ccp(cx,cy)); CCCallFuncN *dis = CCCallFuncN::create(this,callfuncN_selector(HelloWorld::disappear)); CCSequence *actions = CCSequence::create(move,dis,NULL); //如果CCSequence最后没加NULL编译能通过运行会弹对话框; proj->runAction(actions); this->addChild(proj); //将精灵加入层中 _projs->addObject(proj); //将精灵加入数组中 proj->setTag(2); //设置飞镖标记为2; } void HelloWorld::gameLogic(float t) // t就是上面的第2个参数 schedule(...,2) 是2 这么一个参数 { this->crateTarget(); } // void HelloWorld::crateTarget() { CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCSprite *mytarget = CCSprite::create("Target.png"); int y = rand()%(int)(visibleSize.height); mytarget->setPosition(ccp(visibleSize.width-30,y)); this->addChild(mytarget); _targets->addObject(mytarget); //将怪兽加入数组 mytarget->setTag(1); //设置怪物标记为1 CCMoveTo *move = CCMoveTo::create(2,ccp(30,y)); //第一个参数是运动时间,第二个参数是运动方向点 CCCallFuncN *selfDefineAction = CCCallFuncN::create(this,callfuncN_selector(HelloWorld::disappear)); CCSequence *actions = CCSequence::create(move,selfDefineAction,NULL); mytarget->runAction(actions); } void HelloWorld::responsFunc(CCObject *obj) { //CCLog("click"); CCMoveTo *move = CCMoveTo::create(2,ccp(30,40)); //第一个参数是运动时间,第二个参数是运动方向点 CCCallFuncN *selfDefineAction = CCCallFuncN::create(this,callfuncN_selector(HelloWorld::disappear)); CCSequence *action = CCSequence::create(move,selfDefineAction,NULL); target->runAction(action); } void HelloWorld::disappear(CCNode *who) { //who->setPosition(ccp(20,20)); //who->setScale(2); //放大两倍 int tag = who->getTag(); if(1 == tag) { CCLog("mylog-----------------target disappear "); _targets->removeObject(who); CCScene *overScene = GameOverLayer::scene(); CCLog("mylog-----------------get GameOverLayer::scene "); GameOverLayer *layer =(GameOverLayer*)overScene->getChildByTag(100); CCLog("mylog-----------------get layer by Tag "); /*CCLabelTTF *tmp = layer->_label; if(tmp==NULL) CCLog("mylog-----------------tmp==null "); CCLog("mylog-----------------get _label "); tmp->getString(); CCLog("mylog-----------------getString() "); tmp->setString("You lose"); CCLog("mylog-----------------set _label=You lose ");*/ CCDirector::sharedDirector()->replaceScene(overScene); CCLog("mylog-----------------success Change Scene "); } else if(2 == tag) { _projs->removeObject(who); } who->removeFromParentAndCleanup(true); } void HelloWorld::menuCloseCallback(CCObject* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); #else CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif #endif }