Cocos2d-x简单的Demo

和很多游戏引擎一样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\n");
		_targets->removeObject(who);
		CCScene *overScene = GameOverLayer::scene();
		CCLog("mylog-----------------get GameOverLayer::scene\n");
		GameOverLayer *layer =(GameOverLayer*)overScene->getChildByTag(100);
		CCLog("mylog-----------------get layer by Tag\n");
		/*CCLabelTTF *tmp = layer->_label;
		if(tmp==NULL) CCLog("mylog-----------------tmp==null\n");
		CCLog("mylog-----------------get _label\n");
		tmp->getString();
		CCLog("mylog-----------------getString()\n");
		tmp->setString("You lose");
		CCLog("mylog-----------------set _label=You lose\n");*/
		CCDirector::sharedDirector()->replaceScene(overScene);
		CCLog("mylog-----------------success Change Scene\n");
	}
	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
}




 

posted @ 2014-09-29 12:05  leejuen  阅读(593)  评论(0编辑  收藏  举报