code:
#include "ActionManagerTest.h"
#include "../testResource.h"
#include "cocos2d.h"

enum
{
	kTagNode,
	kTagGrossini,
    kTagSequence,
};

CCLayer* nextActionManagerAction();
CCLayer* backActionManagerAction();
CCLayer* restartActionManagerAction();

static int sceneIdx = -1;

#define MAX_LAYER	5

CCLayer* createActionManagerLayer(int nIndex)
{
	switch(nIndex)
	{
		case 0: return new CrashTest();
		case 1: return new LogicTest();
		case 2: return new PauseTest();
        case 3: return new RemoveTest();
        case 4: return new ResumeTest();
	}

	return NULL;
}

CCLayer* nextActionManagerAction()
{
	sceneIdx++;
	sceneIdx = sceneIdx % MAX_LAYER;

	CCLayer* pLayer = createActionManagerLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

CCLayer* backActionManagerAction()
{
	sceneIdx--;
	int total = MAX_LAYER;
	if( sceneIdx < 0 )
		sceneIdx += total;

	CCLayer* pLayer = createActionManagerLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

CCLayer* restartActionManagerAction()
{
	CCLayer* pLayer = createActionManagerLayer(sceneIdx);
	pLayer->autorelease();

	return pLayer;
}

//------------------------------------------------------------------
//
// ActionManagerTest
//
//------------------------------------------------------------------

ActionManagerTest::ActionManagerTest(void)
{
}

ActionManagerTest::~ActionManagerTest(void)
{
}

std::string ActionManagerTest::title()
{
	return "No title";
}

void ActionManagerTest::onEnter()
{
	CCLayer::onEnter();

	CCSize s = CCDirector::sharedDirector()->getWinSize();

	CCLabelTTF* label = CCLabelTTF::labelWithString(title().c_str(), "Arial", 32);
	addChild(label, 1);
	label->setPosition( CCPointMake(s.width/2, s.height-50) );

	CCMenuItemImage *item1 = CCMenuItemImage::itemFromNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(ActionManagerTest::backCallback) );
	CCMenuItemImage *item2 = CCMenuItemImage::itemFromNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(ActionManagerTest::restartCallback) );
	CCMenuItemImage *item3 = CCMenuItemImage::itemFromNormalImage(s_pPathF1, s_pPathF2, this, menu_selector(ActionManagerTest::nextCallback));

	CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, NULL);

	menu->setPosition( CCPointZero );
	item1->setPosition( CCPointMake( s.width/2 - 100,30) );
	item2->setPosition( CCPointMake( s.width/2, 30) );
	item3->setPosition( CCPointMake( s.width/2 + 100,30) );

	addChild(menu, 1);
}

void ActionManagerTest::restartCallback(CCObject* pSender)
{
	CCScene* s = new ActionManagerTestScene();
	s->addChild(restartActionManagerAction());

	CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ActionManagerTest::nextCallback(CCObject* pSender)
{
	CCScene* s = new ActionManagerTestScene();
	s->addChild( nextActionManagerAction() );
	CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ActionManagerTest::backCallback(CCObject* pSender)
{
	CCScene* s = new ActionManagerTestScene();
	s->addChild( backActionManagerAction() );
	CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

//------------------------------------------------------------------
//
// Test1
//
//------------------------------------------------------------------

void CrashTest::onEnter()
{
	ActionManagerTest::onEnter();

	CCSprite* child = CCSprite::spriteWithFile(s_pPathGrossini);
	child->setPosition( CCPointMake(200,200) );
	addChild(child, 1);

	//Sum of all action's duration is 1.5 second.
	child->runAction(CCRotateBy::actionWithDuration(1.5f, 90));
	child->runAction(CCSequence::actions(
											CCDelayTime::actionWithDuration(1.4f),
											CCFadeOut::actionWithDuration(1.1f),
											NULL)
					);

	//After 1.5 second, self will be removed.
	runAction( CCSequence::actions(
									CCDelayTime::actionWithDuration(1.4f),
									CCCallFunc::actionWithTarget(this, callfunc_selector(CrashTest::removeThis)),
									NULL)
			 );
}

void CrashTest::removeThis()
{
	m_pParent->removeChild(this, true);

	nextCallback(this);
}

std::string CrashTest::title()
{
	return "Test 1. Should not crash";
}

//------------------------------------------------------------------
//
// Test2
//
//------------------------------------------------------------------
void LogicTest::onEnter()
{
	ActionManagerTest::onEnter();

	CCSprite* grossini = CCSprite::spriteWithFile(s_pPathGrossini);
	addChild(grossini, 0, 2);
	grossini->setPosition(CCPointMake(200,200));

	grossini->runAction( CCSequence::actions(
												CCMoveBy::actionWithDuration(1, CCPointMake(150,0)),
												CCCallFuncN::actionWithTarget(this, callfuncN_selector(LogicTest::bugMe)),
												NULL)
						);
}

void LogicTest::bugMe(CCNode* node)
{
	node->stopAllActions(); //After this stop next action not working, if remove this stop everything is working
	node->runAction(CCScaleTo::actionWithDuration(2, 2));
}

std::string LogicTest::title()
{
	return "Logic test";
}

//------------------------------------------------------------------
//
// PauseTest
//
//------------------------------------------------------------------

void PauseTest::onEnter()
{
	//
	// This test MUST be done in 'onEnter' and not on 'init'
	// otherwise the paused action will be resumed at 'onEnter' time
	//
	ActionManagerTest::onEnter();

	CCSize s = CCDirector::sharedDirector()->getWinSize();

	CCLabelTTF* l = CCLabelTTF::labelWithString("After 5 seconds grossini should move", "Thonburi", 16);
	addChild(l);
	l->setPosition( CCPointMake(s.width/2, 245) );

	//
	// Also, this test MUST be done, after [super onEnter]
	//
	CCSprite* grossini = CCSprite::spriteWithFile(s_pPathGrossini);
	addChild(grossini, 0, kTagGrossini);
	grossini->setPosition( CCPointMake(200,200) );

	CCAction* action = CCMoveBy::actionWithDuration(1, CCPointMake(150,0));

	CCActionManager::sharedManager()->addAction(action, grossini, true);

	schedule( schedule_selector(PauseTest::unpause), 3);
}

void PauseTest::unpause(ccTime dt)
{
	unschedule( schedule_selector(PauseTest::unpause) );
	CCNode* node = getChildByTag( kTagGrossini );
	CCActionManager::sharedManager()->resumeTarget(node);
}

std::string PauseTest::title()
{
	return "Pause Test";
}

//------------------------------------------------------------------
//
// RemoveTest
//
//------------------------------------------------------------------
void RemoveTest::onEnter()
{
    ActionManagerTest::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCLabelTTF* l = CCLabelTTF::labelWithString("Should not crash", "Thonburi", 16);
    addChild(l);
    l->setPosition( CCPointMake(s.width/2, 245) );

    CCMoveBy* pMove = CCMoveBy::actionWithDuration(2, CCPointMake(200, 0));
    CCCallFunc* pCallback = CCCallFunc::actionWithTarget(this, callfunc_selector(RemoveTest::stopAction));
    CCActionInterval* pSequence = (CCActionInterval*) CCSequence::actions(pMove, pCallback, NULL);
    pSequence->setTag(kTagSequence);

    CCSprite* pChild = CCSprite::spriteWithFile(s_pPathGrossini);
    pChild->setPosition(CCPointMake(200, 200));

    addChild(pChild, 1, kTagGrossini);
    pChild->runAction(pSequence);
}

void RemoveTest::stopAction()
{
    CCNode* pSprite = getChildByTag(kTagGrossini);
    pSprite->stopActionByTag(kTagSequence);
}

std::string RemoveTest::title()
{
    return "Remove Test";
}

//------------------------------------------------------------------
//
// ResumeTest
//
//------------------------------------------------------------------
std::string ResumeTest::title()
{
    return "Resume Test";
}

void ResumeTest::onEnter()
{
    ActionManagerTest::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCLabelTTF* l = CCLabelTTF::labelWithString("Grossini only rotate/scale in 3 seconds", "Thonburi", 16);
    addChild(l);
    l->setPosition( CCPointMake(s.width/2, 245));

    CCSprite* pGrossini = CCSprite::spriteWithFile(s_pPathGrossini);
    addChild(pGrossini, 0, kTagGrossini);
    pGrossini->setPosition(CCPointMake(s.width / 2, s.height / 2));

    pGrossini->runAction(CCScaleBy::actionWithDuration(2, 2));

    CCActionManager::sharedManager()->pauseTarget(pGrossini);
    pGrossini->runAction(CCRotateBy::actionWithDuration(2, 360));

    this->schedule(schedule_selector(ResumeTest::resumeGrossini), 3.0f);
}

void ResumeTest::resumeGrossini(ccTime time)
{
    this->unschedule(schedule_selector(ResumeTest::resumeGrossini));

    CCNode* pGrossini = getChildByTag(kTagGrossini);
    CCActionManager::sharedManager()->resumeTarget(pGrossini);
}

//------------------------------------------------------------------
//
// ActionManagerTestScene
//
//------------------------------------------------------------------
void ActionManagerTestScene::runThisTest()
{
    CCLayer* pLayer = nextActionManagerAction();
    addChild(pLayer);

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef _ACTION_MANAGER_TEST_H_
#define _ACTION_MANAGER_TEST_H_

#include "../testBasic.h"

class ActionManagerTest: public CCLayer
{
protected:
    CCTextureAtlas* m_atlas;

	std::string	m_strTitle;

public:
	ActionManagerTest(void);
	~ActionManagerTest(void);

	virtual std::string title();
	virtual void onEnter();

	void restartCallback(CCObject* pSender);
	void nextCallback(CCObject* pSender);
	void backCallback(CCObject* pSender);
};

class CrashTest : public ActionManagerTest
{
public:
	virtual std::string title();
	virtual void onEnter();
	void removeThis();
};

class LogicTest : public ActionManagerTest
{
public:
	virtual std::string title();
	virtual void onEnter();
	void bugMe(CCNode* node);
};

class PauseTest : public ActionManagerTest
{
public:
	virtual std::string title();
	virtual void onEnter();
	void unpause(ccTime dt);
};

class RemoveTest : public ActionManagerTest
{
public:
    virtual std::string title();
    virtual void onEnter();
    void stopAction();
};

class ResumeTest : public ActionManagerTest
{
public:
    virtual std::string title();
    virtual void onEnter();
    void resumeGrossini(ccTime time);
};

class ActionManagerTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif

license: mit


code:
#include "ActionsTest.h"
#include "../testResource.h"

CCLayer* NextAction();
CCLayer* BackAction();
CCLayer* RestartAction();

static int s_nActionIdx = -1;

CCLayer* CreateLayer(int nIndex)
{
    CCLayer * pLayer = NULL;

    switch (nIndex)
    {
    case ACTION_MANUAL_LAYER:
        pLayer = new ActionManual(); break;
    case ACTION_MOVE_LAYER:
        pLayer = new ActionMove(); break;
    case ACTION_SCALE_LAYER:
        pLayer = new ActionScale(); break;
    case ACTION_ROTATE_LAYER:
        pLayer = new ActionRotate(); break;
	case ACTION_SKEW_LAYER:
		pLayer = new ActionSkew(); break;
	case ACTION_SKEWROTATE_LAYER:
		pLayer = new ActionSkewRotateScale(); break;
    case ACTION_JUMP_LAYER:
        pLayer = new ActionJump(); break;
    case ACTION_BEZIER_LAYER:
        pLayer = new ActionBezier(); break;
    case ACTION_BLINK_LAYER:
        pLayer = new ActionBlink(); break;
    case ACTION_FADE_LAYER:
        pLayer = new ActionFade(); break;
    case ACTION_TINT_LAYER:
        pLayer = new ActionTint(); break;
    case ACTION_ANIMATE_LAYER:
        pLayer = new ActionAnimate(); break;
    case ACTION_SEQUENCE_LAYER:
        pLayer = new ActionSequence(); break;
    case ACTION_SEQUENCE2_LAYER:
        pLayer = new ActionSequence2(); break;
    case ACTION_SPAWN_LAYER:
        pLayer = new ActionSpawn(); break;
    case ACTION_REVERSE:
        pLayer = new ActionReverse(); break;
    case ACTION_DELAYTIME_LAYER:
        pLayer = new ActionDelayTime(); break;
    case ACTION_REPEAT_LAYER:
        pLayer = new ActionRepeat(); break;
    case ACTION_REPEATEFOREVER_LAYER:
        pLayer = new ActionRepeatForever(); break;
    case ACTION_ROTATETOREPEATE_LAYER:
        pLayer = new ActionRotateToRepeat(); break;
    case ACTION_ROTATEJERK_LAYER:
        pLayer = new ActionRotateJerk(); break;
    case ACTION_CALLFUNC_LAYER:
        pLayer = new ActionCallFunc(); break;
    case ACTION_CALLFUNCND_LAYER:
        pLayer = new ActionCallFuncND(); break;
    case ACTION_REVERSESEQUENCE_LAYER:
        pLayer = new ActionReverseSequence(); break;
    case ACTION_REVERSESEQUENCE2_LAYER:
        pLayer = new ActionReverseSequence2(); break;
    case ACTION_ORBIT_LAYER:
        pLayer = new ActionOrbit(); break;
    case ACTION_FLLOW_LAYER:
        pLayer = new ActionFollow(); break;
    default:
        break;
    }

    return pLayer;
}

CCLayer* NextAction()
{
    ++s_nActionIdx;
    s_nActionIdx = s_nActionIdx % ACTION_LAYER_COUNT;

    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}

CCLayer* BackAction()
{
    --s_nActionIdx;
    if( s_nActionIdx < 0 )
        s_nActionIdx += ACTION_LAYER_COUNT;

    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}

CCLayer* RestartAction()
{
    CCLayer* pLayer = CreateLayer(s_nActionIdx);
    pLayer->autorelease();

    return pLayer;
}

void ActionsTestScene::runThisTest()
{
    s_nActionIdx = -1;
    addChild(NextAction());

    CCDirector::sharedDirector()->replaceScene(this);
}

std::string ActionsDemo::title()
{
    return "ActionsTest";
}

std::string ActionsDemo::subtitle()
{
    return "";
}

void ActionsDemo::onEnter()
{
    CCLayer::onEnter();

    // Or you can create an sprite using a filename. only PNG is supported now. Probably TIFF too
    m_grossini = CCSprite::spriteWithFile(s_pPathGrossini);
    m_grossini->retain();

    m_tamara = CCSprite::spriteWithFile(s_pPathSister1);
    m_tamara->retain();

    m_kathia = CCSprite::spriteWithFile(s_pPathSister2);
    m_kathia->retain();

    addChild(m_grossini, 1);
    addChild(m_tamara, 2);
    addChild(m_kathia, 3);

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    m_grossini->setPosition( CCPointMake(s.width/2, s.height/3));
    m_tamara->setPosition( CCPointMake(s.width/2, 2*s.height/3));
    m_kathia->setPosition( CCPointMake(s.width/2, s.height/2));

    // add title and subtitle
    std::string str = title();
    const char * pTitle = str.c_str();
    CCLabelTTF* label = CCLabelTTF::labelWithString(pTitle, "Arial", 18);
    addChild(label, 1);
    label->setPosition( CCPointMake(s.width/2, s.height - 30) );

    std::string strSubtitle = subtitle();
    if( ! strSubtitle.empty() )
    {
        CCLabelTTF* l = CCLabelTTF::labelWithString(strSubtitle.c_str(), "Thonburi", 22);
        addChild(l, 1);
        l->setPosition( CCPointMake(s.width/2, s.height - 60) );
    }

    // add menu
    CCMenuItemImage *item1 = CCMenuItemImage::itemFromNormalImage(s_pPathB1, s_pPathB2, this, menu_selector(ActionsDemo::backCallback) );
    CCMenuItemImage *item2 = CCMenuItemImage::itemFromNormalImage(s_pPathR1, s_pPathR2, this, menu_selector(ActionsDemo::restartCallback) );
    CCMenuItemImage *item3 = CCMenuItemImage::itemFromNormalImage(s_pPathF1, s_pPathF2, this, menu_selector(ActionsDemo::nextCallback) );

    CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, NULL);

    menu->setPosition( CCPointZero );
    item1->setPosition( CCPointMake( s.width/2 - 100,30) );
    item2->setPosition( CCPointMake( s.width/2, 30) );
    item3->setPosition( CCPointMake( s.width/2 + 100,30) );

    addChild(menu, 1);
}

void ActionsDemo::onExit()
{
    m_grossini->release();
    m_tamara->release();
    m_kathia->release();

    CCLayer::onExit();
}

void ActionsDemo::restartCallback(CCObject* pSender)
{
    CCScene* s = new ActionsTestScene();
    s->addChild( RestartAction() );
    CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ActionsDemo::nextCallback(CCObject* pSender)
{
    CCScene* s = new ActionsTestScene();
    s->addChild( NextAction() );
    CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ActionsDemo::backCallback(CCObject* pSender)
{
    CCScene* s = new ActionsTestScene();
    s->addChild( BackAction() );
    CCDirector::sharedDirector()->replaceScene(s);
    s->release();
}

void ActionsDemo::centerSprites(unsigned int numberOfSprites)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    if( numberOfSprites == 1 )
    {
        m_tamara->setIsVisible(false);
        m_kathia->setIsVisible(false);
        m_grossini->setPosition(CCPointMake(s.width/2, s.height/2));
    }
    else if( numberOfSprites == 2 )
    {
        m_kathia->setPosition( CCPointMake(s.width/3, s.height/2));
        m_tamara->setPosition( CCPointMake(2*s.width/3, s.height/2));
        m_grossini->setIsVisible(false);
    }
    else if( numberOfSprites == 3 )
    {
        m_grossini->setPosition( CCPointMake(s.width/2, s.height/2));
        m_tamara->setPosition( CCPointMake(s.width/4, s.height/2));
        m_kathia->setPosition( CCPointMake(3 * s.width/4, s.height/2));
    }
}

void ActionsDemo::alignSpritesLeft(unsigned int numberOfSprites)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    if( numberOfSprites == 1 )
    {
        m_tamara->setIsVisible(false);
        m_kathia->setIsVisible(false);
        m_grossini->setPosition(CCPointMake(60, s.height/2));
    }
    else if( numberOfSprites == 2 )
    {
        m_kathia->setPosition( CCPointMake(60, s.height/3));
        m_tamara->setPosition( CCPointMake(60, 2*s.height/3));
        m_grossini->setIsVisible( false );
    }
    else if( numberOfSprites == 3 )
    {
        m_grossini->setPosition( CCPointMake(60, s.height/2));
        m_tamara->setPosition( CCPointMake(60, 2*s.height/3));
        m_kathia->setPosition( CCPointMake(60, s.height/3));
    }
}

//------------------------------------------------------------------
//
// ActionManual
//
//------------------------------------------------------------------
void ActionManual::onEnter()
{
    ActionsDemo::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    m_tamara->setScaleX( 2.5f);
    m_tamara->setScaleY( -1.0f);
    m_tamara->setPosition( CCPointMake(100,70) );
    m_tamara->setOpacity( 128);

    m_grossini->setRotation( 120);
    m_grossini->setPosition( CCPointMake(s.width/2, s.height/2));
    m_grossini->setColor( ccc3( 255,0,0));

    m_kathia->setPosition( CCPointMake(s.width-100, s.height/2));
    m_kathia->setColor( ccBLUE);
}

std::string ActionManual::subtitle()
{
    return "Manual Transformation";
}

//------------------------------------------------------------------
//
//	ActionMove
//
//------------------------------------------------------------------
void ActionMove::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCActionInterval*  actionTo = CCMoveTo::actionWithDuration(2, CCPointMake(s.width-40, s.height-40));
    CCActionInterval*  actionBy = CCMoveBy::actionWithDuration(2, CCPointMake(80,80));
    CCActionInterval*  actionByBack = actionBy->reverse();

    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::actions(actionBy, actionByBack, NULL));
    m_kathia->runAction(CCMoveTo::actionWithDuration(1, CCPointMake(40,40)));
}

std::string ActionMove::subtitle()
{
    return "MoveTo / MoveBy";
}

//------------------------------------------------------------------
//
// ActionScale
//
//------------------------------------------------------------------
void ActionScale::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCActionInterval*  actionTo = CCScaleTo::actionWithDuration( 2, 0.5f);
    CCActionInterval*  actionBy = CCScaleBy::actionWithDuration(2 ,  2);
    CCActionInterval*  actionBy2 = CCScaleBy::actionWithDuration(2, 0.25f, 4.5f);
    CCActionInterval*  actionByBack = actionBy->reverse();

    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::actions(actionBy, actionByBack, NULL));
    m_kathia->runAction( CCSequence::actions(actionBy2, actionBy2->reverse(), NULL));
}

std::string ActionScale::subtitle()
{
    return "ScaleTo / ScaleBy";
}

//------------------------------------------------------------------
//
//	ActionSkew
//
//------------------------------------------------------------------
void ActionSkew::onEnter()
{
	ActionsDemo::onEnter();

	centerSprites(3);

	CCActionInterval *actionTo = CCSkewTo::actionWithDuration(2, 37.2f, -37.2f);
	CCActionInterval *actionToBack = CCSkewTo::actionWithDuration(2, 0, 0);
	CCActionInterval *actionBy = CCSkewBy::actionWithDuration(2, 0.0f, -90.0f);
	CCActionInterval *actionBy2 = CCSkewBy::actionWithDuration(2, 45.0f, 45.0f);
	CCActionInterval *actionByBack = actionBy->reverse();

	m_tamara->runAction(CCSequence::actions(actionTo, actionToBack, NULL));
	m_grossini->runAction(CCSequence::actions(actionBy, actionByBack, NULL));

	m_kathia->runAction(CCSequence::actions(actionBy2, actionBy2->reverse(), NULL));
}

string ActionSkew::subtitle()
{
	return "SkewTo / SkewBy";
}

void ActionSkewRotateScale::onEnter()
{
    ActionsDemo::onEnter();

	m_tamara->removeFromParentAndCleanup(true);
	m_grossini->removeFromParentAndCleanup(true);
	m_kathia->removeFromParentAndCleanup(true);

	CCSize boxSize = CCSizeMake(100.0f, 100.0f);

	CCLayerColor *box = CCLayerColor::layerWithColor(ccc4f(255, 255, 0, 255));
	box->setAnchorPoint(ccp(0, 0));
	box->setPosition(ccp(190, 110));
	box->setContentSize(boxSize);

	static float markrside = 10.0f;
	CCLayerColor *uL = CCLayerColor::layerWithColor(ccc4f(255, 0, 0, 255));
	box->addChild(uL);
	uL->setContentSize(CCSizeMake(markrside, markrside));
	uL->setPosition(ccp(0.f, boxSize.height - markrside));
	uL->setAnchorPoint(ccp(0, 0));

	CCLayerColor *uR = CCLayerColor::layerWithColor(ccc4f(0, 0, 255, 255));
	box->addChild(uR);
	uR->setContentSize(CCSizeMake(markrside, markrside));
	uR->setPosition(ccp(boxSize.width - markrside, boxSize.height - markrside));
	uR->setAnchorPoint(ccp(0, 0));
	addChild(box);

	CCActionInterval *actionTo = CCSkewTo::actionWithDuration(2, 0.f, 2.f);
	CCActionInterval *rotateTo = CCRotateTo::actionWithDuration(2, 61.0f);
	CCActionInterval *actionScaleTo = CCScaleTo::actionWithDuration(2, -0.44f, 0.47f);

	CCActionInterval *actionScaleToBack = CCScaleTo::actionWithDuration(2, 1.0f, 1.0f);
	CCActionInterval *rotateToBack = CCRotateTo::actionWithDuration(2, 0);
	CCActionInterval *actionToBack = CCSkewTo::actionWithDuration(2, 0, 0);

	box->runAction(CCSequence::actions(actionTo, actionToBack, NULL));
	box->runAction(CCSequence::actions(rotateTo, rotateToBack, NULL));
	box->runAction(CCSequence::actions(actionScaleTo, actionScaleToBack, NULL));
}

string ActionSkewRotateScale::subtitle()
{
	return "Skew + Rotate + Scale";
}

//------------------------------------------------------------------
//
//	ActionRotate
//
//------------------------------------------------------------------
void ActionRotate::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCActionInterval*  actionTo = CCRotateTo::actionWithDuration( 2, 45);
    CCActionInterval*  actionTo2 = CCRotateTo::actionWithDuration( 2, -45);
    CCActionInterval*  actionTo0 = CCRotateTo::actionWithDuration(2 , 0);
    m_tamara->runAction( CCSequence::actions(actionTo, actionTo0, NULL));

    CCActionInterval*  actionBy = CCRotateBy::actionWithDuration(2 ,  360);
    CCActionInterval*  actionByBack = actionBy->reverse();
    m_grossini->runAction( CCSequence::actions(actionBy, actionByBack, NULL));

    m_kathia->runAction( CCSequence::actions(actionTo2, actionTo0->copy()->autorelease(), NULL));
}

std::string ActionRotate::subtitle()
{
    return "RotateTo / RotateBy";
}

//------------------------------------------------------------------
//
// ActionJump
//
//------------------------------------------------------------------
void ActionJump::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCActionInterval*  actionTo = CCJumpTo::actionWithDuration(2, CCPointMake(300,300), 50, 4);
    CCActionInterval*  actionBy = CCJumpBy::actionWithDuration(2, CCPointMake(300,0), 50, 4);
    CCActionInterval*  actionUp = CCJumpBy::actionWithDuration(2, CCPointMake(0,0), 80, 4);
    CCActionInterval*  actionByBack = actionBy->reverse();

    m_tamara->runAction( actionTo);
    m_grossini->runAction( CCSequence::actions(actionBy, actionByBack, NULL));
    m_kathia->runAction( CCRepeatForever::actionWithAction(actionUp));
}
std::string ActionJump::subtitle()
{
    return "JumpTo / JumpBy";
}

//------------------------------------------------------------------
//
// ActionBezier
//
//------------------------------------------------------------------
void ActionBezier::onEnter()
{
    ActionsDemo::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    //
    // startPosition can be any coordinate, but since the movement
    // is relative to the Bezier curve, make it (0,0)
    //

    centerSprites(3);

    // sprite 1
    ccBezierConfig bezier;
    bezier.controlPoint_1 = CCPointMake(0, s.height/2);
    bezier.controlPoint_2 = CCPointMake(300, -s.height/2);
    bezier.endPosition = CCPointMake(300,100);

    CCActionInterval*  bezierForward = CCBezierBy::actionWithDuration(3, bezier);
    CCActionInterval*  bezierBack = bezierForward->reverse();
    CCAction*  rep = CCRepeatForever::actionWithAction((CCActionInterval*)CCSequence::actions( bezierForward, bezierBack, NULL));

    // sprite 2
    m_tamara->setPosition(CCPointMake(80,160));
    ccBezierConfig bezier2;
    bezier2.controlPoint_1 = CCPointMake(100, s.height/2);
    bezier2.controlPoint_2 = CCPointMake(200, -s.height/2);
    bezier2.endPosition = CCPointMake(240,160);

    CCActionInterval*  bezierTo1 = CCBezierTo::actionWithDuration(2, bezier2);

    // sprite 3
    m_kathia->setPosition(CCPointMake(400,160));
    CCActionInterval*  bezierTo2 = CCBezierTo::actionWithDuration(2, bezier2);

    m_grossini->runAction( rep);
    m_tamara->runAction(bezierTo1);
    m_kathia->runAction(bezierTo2);

}

std::string ActionBezier::subtitle()
{
    return "BezierBy / BezierTo";
}

//------------------------------------------------------------------
//
// ActionBlink
//
//------------------------------------------------------------------
void ActionBlink::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

    CCActionInterval*  action1 = CCBlink::actionWithDuration(2, 10);
    CCActionInterval*  action2 = CCBlink::actionWithDuration(2, 5);

    m_tamara->runAction( action1);
    m_kathia->runAction(action2);
}

std::string  ActionBlink::subtitle()
{
    return "Blink";
}

//------------------------------------------------------------------
//
// ActionFade
//
//------------------------------------------------------------------
void ActionFade::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

    m_tamara->setOpacity( 0 );
    CCActionInterval*  action1 = CCFadeIn::actionWithDuration(1.0f);
    CCActionInterval*  action1Back = action1->reverse();

    CCActionInterval*  action2 = CCFadeOut::actionWithDuration(1.0f);
    CCActionInterval*  action2Back = action2->reverse();

    m_tamara->runAction( CCSequence::actions( action1, action1Back, NULL));
    m_kathia->runAction( CCSequence::actions( action2, action2Back, NULL));
}

std::string  ActionFade::subtitle()
{
    return "FadeIn / FadeOut";
}

//------------------------------------------------------------------
//
// ActionTint
//
//------------------------------------------------------------------

void ActionTint::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

    CCActionInterval*  action1 = CCTintTo::actionWithDuration(2, 255, 0, 255);
    CCActionInterval*  action2 = CCTintBy::actionWithDuration(2, -127, -255, -127);
    CCActionInterval*  action2Back = action2->reverse();

    m_tamara->runAction( action1);
    m_kathia->runAction( CCSequence::actions( action2, action2Back, NULL));
}

std::string  ActionTint::subtitle()
{
    return "TintTo / TintBy";
}

//------------------------------------------------------------------
//
// ActionAnimate
//
//------------------------------------------------------------------
void ActionAnimate::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);

    CCAnimation* animation = CCAnimation::animation();
    char frameName[100] = {0};
    for( int i=1;i<15;i++)
    {
        sprintf(frameName, "Images/grossini_dance_%02d.png", i);
        animation->addFrameWithFileName(frameName);
    }

    CCActionInterval*  action = CCAnimate::actionWithDuration(3, animation, false);
    CCActionInterval*  action_back = action->reverse();

    m_grossini->runAction( CCSequence::actions( action, action_back, NULL));
}

std::string ActionAnimate::subtitle()
{
    return "Animation";
}

//------------------------------------------------------------------
//
//	ActionSequence
//
//------------------------------------------------------------------
void ActionSequence::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCFiniteTimeAction*  action = CCSequence::actions(
        CCMoveBy::actionWithDuration( 2, CCPointMake(240,0)),
        CCRotateBy::actionWithDuration( 2,  540),
        NULL);

    m_grossini->runAction(action);
}

std::string ActionSequence::subtitle()
{
    return "Sequence: Move + Rotate";
}

//------------------------------------------------------------------
//
//	ActionSequence2
//
//------------------------------------------------------------------
void ActionSequence2::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    m_grossini->setIsVisible(false);

    CCFiniteTimeAction*  action = CCSequence::actions(
        CCPlace::actionWithPosition(CCPointMake(200,200)),
        CCShow::action(),
        CCMoveBy::actionWithDuration(1, CCPointMake(100,0)),
        CCCallFunc::actionWithTarget(this, callfunc_selector(ActionSequence2::callback1)),
        CCCallFuncN::actionWithTarget(this, callfuncN_selector(ActionSequence2::callback2)),
        CCCallFuncND::actionWithTarget(this, callfuncND_selector(ActionSequence2::callback3), (void*)0xbebabeba),
        NULL);

    m_grossini->runAction(action);
}

void ActionSequence2::callback1()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 1 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*1,s.height/2));

    addChild(label);
}

void ActionSequence2::callback2(CCNode* sender)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 2 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*2,s.height/2));

    addChild(label);
}

void ActionSequence2::callback3(CCNode* sender, void* data)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 3 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*3,s.height/2));

    addChild(label);
}

std::string ActionSequence2::subtitle()
{
    return "Sequence of InstantActions";
}

//------------------------------------------------------------------
//
//	ActionCallFunc
//
//------------------------------------------------------------------
void ActionCallFunc::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCFiniteTimeAction*  action = CCSequence::actions(
        CCMoveBy::actionWithDuration(2, CCPointMake(200,0)),
        CCCallFunc::actionWithTarget(this, callfunc_selector(ActionCallFunc::callback1)),
        NULL);

    CCFiniteTimeAction*  action2 = CCSequence::actions(
        CCScaleBy::actionWithDuration(2 ,  2),
        CCFadeOut::actionWithDuration(2),
        CCCallFuncN::actionWithTarget(this, callfuncN_selector(ActionSequence2::callback2)),
        NULL);

    CCFiniteTimeAction*  action3 = CCSequence::actions(
        CCRotateBy::actionWithDuration(3 , 360),
        CCFadeOut::actionWithDuration(2),
        CCCallFuncND::actionWithTarget(this, callfuncND_selector(ActionSequence2::callback3), (void*)0xbebabeba),
        NULL);

    m_grossini->runAction(action);
    m_tamara->runAction(action2);
    m_kathia->runAction(action3);
}

void ActionCallFunc::callback1()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 1 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*1,s.height/2));

    addChild(label);
}

void ActionCallFunc::callback2(CCNode* pSender)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 2 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*2,s.height/2));

    addChild(label);
}

void ActionCallFunc::callback3(CCNode* pTarget, void* data)
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF *label = CCLabelTTF::labelWithString("callback 3 called", "Marker Felt", 16);
    label->setPosition(CCPointMake( s.width/4*3,s.height/2));
    addChild(label);
}

std::string ActionCallFunc::subtitle()
{
    return "Callbacks: CallFunc and friends";
}

//------------------------------------------------------------------
//
// ActionCallFuncND
//
//------------------------------------------------------------------
void ActionCallFuncND::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);

    CCFiniteTimeAction* action = CCSequence::actions(CCMoveBy::actionWithDuration(2.0f, ccp(200,0)),
        //CCCallFuncND::actionWithTarget(m_grossini, callfuncND_selector(ActionCallFuncND::removeFromParentAndCleanup), (void*)true),
        NULL);

    m_grossini->runAction(action);
}

std::string ActionCallFuncND::title()
{
    return "CallFuncND + auto remove";
}

std::string ActionCallFuncND::subtitle()
{
    return "CallFuncND + removeFromParentAndCleanup. Grossini dissapears in 2s";
}

//------------------------------------------------------------------
//
// ActionSpawn
//
//------------------------------------------------------------------

void ActionSpawn::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCAction*  action = CCSpawn::actions(
        CCJumpBy::actionWithDuration(2, CCPointMake(300,0), 50, 4),
        CCRotateBy::actionWithDuration( 2,  720),
        NULL);

    m_grossini->runAction(action);
}

std::string ActionSpawn::subtitle()
{
    return "Spawn: Jump + Rotate";
}

//------------------------------------------------------------------
//
// ActionRepeatForever
//
//------------------------------------------------------------------
void ActionRepeatForever::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);

    CCFiniteTimeAction*  action = CCSequence::actions(
        CCDelayTime::actionWithDuration(1),
        CCCallFuncN::actionWithTarget( this, callfuncN_selector(ActionRepeatForever::repeatForever) ),
        NULL);

    m_grossini->runAction(action);
}

void ActionRepeatForever::repeatForever(CCNode* pSender)
{
    CCRepeatForever *repeat = CCRepeatForever::actionWithAction( CCRotateBy::actionWithDuration(1.0f, 360) );

    pSender->runAction(repeat);
}

std::string ActionRepeatForever::subtitle()
{
    return "CallFuncN + RepeatForever";
}

//------------------------------------------------------------------
//
// ActionRotateToRepeat
//
//------------------------------------------------------------------
void ActionRotateToRepeat::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

    CCActionInterval*  act1 = CCRotateTo::actionWithDuration(1, 90);
    CCActionInterval*  act2 = CCRotateTo::actionWithDuration(1, 0);
    CCActionInterval*  seq = (CCActionInterval*)(CCSequence::actions(act1, act2, NULL));
    CCAction*  rep1 = CCRepeatForever::actionWithAction(seq);
    CCActionInterval*  rep2 = CCRepeat::actionWithAction((CCFiniteTimeAction*)(seq->copy()->autorelease()), 10);

    m_tamara->runAction(rep1);
    m_kathia->runAction(rep2);
}

std::string ActionRotateToRepeat ::subtitle()
{
    return "Repeat/RepeatForever + RotateTo";
}

//------------------------------------------------------------------
//
// ActionRotateJerk
//
//------------------------------------------------------------------
void ActionRotateJerk::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(2);

    CCFiniteTimeAction*  seq = CCSequence::actions(
        CCRotateTo::actionWithDuration(0.5f, -20),
        CCRotateTo::actionWithDuration(0.5f, 20),
        NULL);

    CCActionInterval*  rep1 = CCRepeat::actionWithAction(seq, 10);
    CCAction*  rep2 = CCRepeatForever::actionWithAction( (CCActionInterval*)(seq->copy()->autorelease()) );

    m_tamara->runAction(rep1);
    m_kathia->runAction(rep2);
}

std::string ActionRotateJerk::subtitle()
{
    return "RepeatForever / Repeat + Rotate";
}

//------------------------------------------------------------------
//
// ActionReverse
//
//------------------------------------------------------------------
void ActionReverse::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCActionInterval*  jump = CCJumpBy::actionWithDuration(2, CCPointMake(300,0), 50, 4);
    CCFiniteTimeAction*  action = CCSequence::actions( jump, jump->reverse(), NULL);

    m_grossini->runAction(action);
}

std::string ActionReverse::subtitle()
{
    return "Reverse an action";
}

//------------------------------------------------------------------
//
// ActionDelayTime
//
//------------------------------------------------------------------
void ActionDelayTime::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCActionInterval*  move = CCMoveBy::actionWithDuration(1, CCPointMake(150,0));
    CCFiniteTimeAction*  action = CCSequence::actions( move, CCDelayTime::actionWithDuration(2), move, NULL);

    m_grossini->runAction(action);
}

std::string ActionDelayTime::subtitle()
{
    return "DelayTime: m + delay + m";
}

//------------------------------------------------------------------
//
// ActionReverseSequence
//
//------------------------------------------------------------------
void ActionReverseSequence::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(1);

    CCActionInterval*  move1 = CCMoveBy::actionWithDuration(1, CCPointMake(250,0));
    CCActionInterval*  move2 = CCMoveBy::actionWithDuration(1, CCPointMake(0,50));
    CCFiniteTimeAction*  seq = CCSequence::actions( move1, move2, move1->reverse(), NULL);
    CCFiniteTimeAction*  action = CCSequence::actions( seq, seq->reverse(), NULL);

    m_grossini->runAction(action);
}

std::string ActionReverseSequence::subtitle()
{
    return "Reverse a sequence";
}

//------------------------------------------------------------------
//
// ActionReverseSequence2
//
//------------------------------------------------------------------
void ActionReverseSequence2::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(2);

    // Test:
    //   Sequence should work both with IntervalAction and InstantActions
    CCActionInterval*  move1 = CCMoveBy::actionWithDuration(1, CCPointMake(250,0));
    CCActionInterval*  move2 = CCMoveBy::actionWithDuration(1, CCPointMake(0,50));
    CCToggleVisibility*  tog1 = new CCToggleVisibility();
    CCToggleVisibility*  tog2 = new CCToggleVisibility();
    tog1->autorelease();
    tog2->autorelease();
    CCFiniteTimeAction*  seq = CCSequence::actions( move1, tog1, move2, tog2, move1->reverse(), NULL);
    CCActionInterval*  action = CCRepeat::actionWithAction((CCActionInterval*)(CCSequence::actions( seq, seq->reverse(), NULL)), 3);

    // Test:
    //   Also test that the reverse of Hide is Show, and vice-versa
    m_kathia->runAction(action);

    CCActionInterval*  move_tamara = CCMoveBy::actionWithDuration(1, CCPointMake(100,0));
    CCActionInterval*  move_tamara2 = CCMoveBy::actionWithDuration(1, CCPointMake(50,0));
    CCActionInstant*  hide = new CCHide();
    hide->autorelease();
    CCFiniteTimeAction*  seq_tamara = CCSequence::actions( move_tamara, hide, move_tamara2, NULL);
    CCFiniteTimeAction*  seq_back = seq_tamara->reverse();
    m_tamara->runAction( CCSequence::actions( seq_tamara, seq_back, NULL));
}
std::string ActionReverseSequence2::subtitle()
{
    return "Reverse sequence 2";
}

//------------------------------------------------------------------
//
// ActionRepeat
//
//------------------------------------------------------------------
void ActionRepeat::onEnter()
{
    ActionsDemo::onEnter();

    alignSpritesLeft(2);

    CCActionInterval*  a1 = CCMoveBy::actionWithDuration(1, CCPointMake(150,0));
    CCActionInterval*  action1 = CCRepeat::actionWithAction(
        CCSequence::actions( CCPlace::actionWithPosition(CCPointMake(60,60)), a1, NULL) ,
        3);
    CCAction*  action2 = CCRepeatForever::actionWithAction(
        (CCActionInterval*)(CCSequence::actions((CCActionInterval*)(a1->copy()->autorelease()), a1->reverse(), NULL))
        );

    m_kathia->runAction(action1);
    m_tamara->runAction(action2);
}

std::string ActionRepeat::subtitle()
{
    return "Repeat / RepeatForever actions";
}

//------------------------------------------------------------------
//
// ActionOrbit
//
//------------------------------------------------------------------
void ActionOrbit::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(3);

    CCActionInterval*  orbit1 = CCOrbitCamera::actionWithDuration(2,1, 0, 0, 180, 0, 0);
    CCFiniteTimeAction*  action1 = CCSequence::actions(
        orbit1,
        orbit1->reverse(),
        NULL);

    CCActionInterval*  orbit2 = CCOrbitCamera::actionWithDuration(2,1, 0, 0, 180, -45, 0);
    CCFiniteTimeAction*  action2 = CCSequence::actions(
        orbit2,
        orbit2->reverse(),
        NULL);

    CCActionInterval*  orbit3 = CCOrbitCamera::actionWithDuration(2,1, 0, 0, 180, 90, 0);
    CCFiniteTimeAction*  action3 = CCSequence::actions(
        orbit3,
        orbit3->reverse(),
        NULL);

    m_kathia->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)action1));
    m_tamara->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)action2));
    m_grossini->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)action3));

    CCActionInterval*  move = CCMoveBy::actionWithDuration(3, CCPointMake(100,-100));
    CCActionInterval*  move_back = move->reverse();
    CCFiniteTimeAction*  seq = CCSequence::actions(move, move_back, NULL);
    CCAction*  rfe = CCRepeatForever::actionWithAction((CCActionInterval*)seq);
    m_kathia->runAction(rfe);
    m_tamara->runAction((CCAction*)(rfe->copy()->autorelease()));
    m_grossini->runAction((CCAction*)(rfe->copy()->autorelease()));
}

std::string ActionOrbit::subtitle()
{
    return "OrbitCamera action";
}

//------------------------------------------------------------------
//
// ActionFollow
//
//------------------------------------------------------------------
void ActionFollow::onEnter()
{
    ActionsDemo::onEnter();

    centerSprites(1);
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    m_grossini->setPosition(CCPointMake(-200, s.height / 2));
    CCActionInterval* move      = CCMoveBy::actionWithDuration(2, CCPointMake(s.width * 3, 0));
    CCActionInterval* move_back = move->reverse();
    CCFiniteTimeAction* seq       = CCSequence::actions(move, move_back, NULL);
    CCAction* rep               = CCRepeatForever::actionWithAction((CCActionInterval*)seq);

    m_grossini->runAction(rep);

    this->runAction(CCFollow::actionWithTarget(m_grossini, CCRectMake(0, 0, s.width * 2 - 100, s.height)));
}

std::string ActionFollow::subtitle()
{
    return "Follow action";
}


code:
#ifndef _ActionsTest_H_
#define _ActionsTest_H_

#include "../testBasic.h"
////----#include "cocos2d.h"

using namespace cocos2d;

enum
{
    ACTION_MANUAL_LAYER = 0,
    ACTION_MOVE_LAYER,
    ACTION_SCALE_LAYER,
    ACTION_ROTATE_LAYER,
	ACTION_SKEW_LAYER,
	ACTION_SKEWROTATE_LAYER,
    ACTION_JUMP_LAYER,
    ACTION_BEZIER_LAYER,
    ACTION_BLINK_LAYER,
    ACTION_FADE_LAYER,
    ACTION_TINT_LAYER,
    ACTION_ANIMATE_LAYER,
    ACTION_SEQUENCE_LAYER,
    ACTION_SEQUENCE2_LAYER,
    ACTION_SPAWN_LAYER,
    ACTION_REVERSE,
    ACTION_DELAYTIME_LAYER,
    ACTION_REPEAT_LAYER,
    ACTION_REPEATEFOREVER_LAYER,
    ACTION_ROTATETOREPEATE_LAYER,
    ACTION_ROTATEJERK_LAYER,
    ACTION_CALLFUNC_LAYER,
    ACTION_CALLFUNCND_LAYER,
    ACTION_REVERSESEQUENCE_LAYER,
    ACTION_REVERSESEQUENCE2_LAYER,
    ACTION_ORBIT_LAYER,
    ACTION_FLLOW_LAYER,
    ACTION_LAYER_COUNT,
};

// the class inherit from TestScene
// every Scene each test used must inherit from TestScene,
// make sure the test have the menu item for back to main menu
class ActionsTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

class ActionsDemo : public CCLayer
{
protected:
    CCSprite*	m_grossini;
    CCSprite*	m_tamara;
    CCSprite*	m_kathia;
public:
    virtual void onEnter();
    virtual void onExit();

    void centerSprites(unsigned int numberOfSprites);
    void alignSpritesLeft(unsigned int numberOfSprites);
    virtual std::string title();
    virtual std::string subtitle();

    void restartCallback(CCObject* pSender);
    void nextCallback(CCObject* pSender);
    void backCallback(CCObject* pSender);
};

class ActionManual : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionMove : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionScale : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionSkew : public ActionsDemo
{
	virtual void onEnter();
	virtual std::string subtitle();
};

class ActionSkewRotateScale : public ActionsDemo
{
	virtual void onEnter();
	virtual std::string subtitle();
};

class ActionRotate : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionJump : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionBezier : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionBlink : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionFade : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionTint : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionAnimate : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionSequence : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionSequence2 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void callback1();
    void callback2(CCNode* sender);
    void callback3(CCNode* sender, void* data);
};

class ActionSpawn : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionReverse : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionRepeat : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionDelayTime : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionReverseSequence : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionReverseSequence2 : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionOrbit : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionRepeatForever : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void repeatForever(CCNode* pTarget);
};

class ActionRotateToRepeat : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionRotateJerk : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

class ActionCallFunc : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();

    void callback1();
    void callback2(CCNode* pTarget);
    void callback3(CCNode* pTarget, void* data);
};

class ActionCallFuncND : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string title();
    virtual std::string subtitle();
};

class ActionFollow : public ActionsDemo
{
public:
    virtual void onEnter();
    virtual std::string subtitle();
};

#endif


code:
#include "Box2dTest.h"
#include "../testResource.h"

#define PTM_RATIO 32
enum
{
	kTagTileMap = 1,
	kTagSpriteManager = 1,
	kTagAnimation1 = 1,
};

Box2DTestLayer::Box2DTestLayer()
{
	setIsTouchEnabled( true );
	setIsAccelerometerEnabled( true );

	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
	//UXLOG(L"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);

	// Define the gravity vector.
	b2Vec2 gravity;
	gravity.Set(0.0f, -10.0f);

	// Do we want to let bodies sleep?
	bool doSleep = true;

	// Construct a world object, which will hold and simulate the rigid bodies.
	world = new b2World(gravity);
	world->SetAllowSleeping(doSleep);
	world->SetContinuousPhysics(true);

/*
	m_debugDraw = new GLESDebugDraw( PTM_RATIO );
	world->SetDebugDraw(m_debugDraw);

	uint flags = 0;
	flags += b2DebugDraw::e_shapeBit;
	flags += b2DebugDraw::e_jointBit;
	flags += b2DebugDraw::e_aabbBit;
	flags += b2DebugDraw::e_pairBit;
	flags += b2DebugDraw::e_centerOfMassBit;
	m_debugDraw->SetFlags(flags);
*/

	// Define the ground body.
	b2BodyDef groundBodyDef;
	groundBodyDef.position.Set(screenSize.width/2/PTM_RATIO, screenSize.height/2/PTM_RATIO); // bottom-left corner

	// Call the body factory which allocates memory for the ground body
	// from a pool and creates the ground box shape (also from a pool).
	// The body is also added to the world.
	b2Body* groundBody = world->CreateBody(&groundBodyDef);

	// Define the ground box shape.
	b2PolygonShape groundBox;
    // bottom
    groundBox.SetAsBox(screenSize.width/2/PTM_RATIO, 0, b2Vec2(0, -screenSize.height/2/PTM_RATIO), 0);
 	groundBody->CreateFixture(&groundBox, 0);

    // top
    groundBox.SetAsBox(screenSize.width/2/PTM_RATIO, 0, b2Vec2(0, screenSize.height/2/PTM_RATIO), 0);
    groundBody->CreateFixture(&groundBox, 0);

    // left
    groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(-screenSize.width/2/PTM_RATIO, 0), 0);
    groundBody->CreateFixture(&groundBox, 0);

    // right
    groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(screenSize.width/2/PTM_RATIO, 0), 0);
    groundBody->CreateFixture(&groundBox, 0);
	//Set up sprite

	CCSpriteBatchNode *mgr = CCSpriteBatchNode::batchNodeWithFile(s_pPathBlock, 150);
	addChild(mgr, 0, kTagSpriteManager);

	addNewSpriteWithCoords( CCPointMake(screenSize.width/2, screenSize.height/2) );

	CCLabelTTF *label = CCLabelTTF::labelWithString("Tap screen", "Marker Felt", 32);
	addChild(label, 0);
	label->setColor( ccc3(0,0,255) );
	label->setPosition( CCPointMake( screenSize.width/2, screenSize.height-50) );

	scheduleUpdate();
}

Box2DTestLayer::~Box2DTestLayer()
{
	delete world;
	world = NULL;

	//delete m_debugDraw;
}

void Box2DTestLayer::draw()
{
	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states:  GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	//world->DrawDebugData();

	// restore default GL states
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

void Box2DTestLayer::addNewSpriteWithCoords(CCPoint p)
{
	//UXLOG(L"Add sprite %0.2f x %02.f",p.x,p.y);
	CCSpriteBatchNode* batch = (CCSpriteBatchNode*)getChildByTag(kTagSpriteManager);

	//We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
	//just randomly picking one of the images
	int idx = (CCRANDOM_0_1() > .5 ? 0:1);
	int idy = (CCRANDOM_0_1() > .5 ? 0:1);
	CCSprite *sprite = CCSprite::spriteWithTexture(batch->getTexture(), CCRectMake(32 * idx,32 * idy,32,32));
	batch->addChild(sprite);

	sprite->setPosition( CCPointMake( p.x, p.y) );

	// Define the dynamic body.
	//Set up a 1m squared box in the physics world
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;
	bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
	bodyDef.userData = sprite;
	b2Body *body = world->CreateBody(&bodyDef);

	// Define another box shape for our dynamic body.
	b2PolygonShape dynamicBox;
	dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box

	// Define the dynamic body fixture.
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &dynamicBox;
	fixtureDef.density = 1.0f;
	fixtureDef.friction = 0.3f;
	body->CreateFixture(&fixtureDef);
}

void Box2DTestLayer::update(ccTime dt)
{
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/

	int velocityIterations = 8;
	int positionIterations = 1;

	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	world->Step(dt, velocityIterations, positionIterations);

	//Iterate over the bodies in the physics world
	for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
	{
		if (b->GetUserData() != NULL) {
			//Synchronize the AtlasSprites position and rotation with the corresponding body
			CCSprite* myActor = (CCSprite*)b->GetUserData();
			myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
			myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
		}
	}
}

void Box2DTestLayer::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
	//Add a new body/atlas sprite at the touched location
	CCSetIterator it;
	CCTouch* touch;

	for( it = touches->begin(); it != touches->end(); it++)
	{
		touch = (CCTouch*)(*it);

		if(!touch)
			break;

		CCPoint location = touch->locationInView();

		location = CCDirector::sharedDirector()->convertToGL(location);

		addNewSpriteWithCoords( location );
	}
}

/*
void Box2DTestLayer::accelerometer(UIAccelerometer* accelerometer, CCAcceleration* acceleration)
{
	static float prevX=0, prevY=0;

//#define kFilterFactor 0.05f
#define kFilterFactor 1.0f	// don't use filter. the code is here just as an example

	float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
	float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;

	prevX = accelX;
	prevY = accelY;

	// accelerometer values are in "Portrait" mode. Change them to Landscape left
	// multiply the gravity by 10
	b2Vec2 gravity( -accelY * 10, accelX * 10);

	world->SetGravity( gravity );
}
*/

void Box2DTestScene::runThisTest()
{
    CCLayer* pLayer = new Box2DTestLayer();
    addChild(pLayer);
    pLayer->release();

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef _BOX2D_TEST_H_
#define _BOX2D_TEST_H_

#include "cocos2d.h"
#include "Box2D/Box2D.h"
#include "../testBasic.h"

class Box2DTestLayer : public CCLayer
{
	b2World* world;
	//GLESDebugDraw *m_debugDraw;

public:
	Box2DTestLayer();
	~Box2DTestLayer();

	virtual void draw();

	void addNewSpriteWithCoords(CCPoint p);
	void update(ccTime dt);
	virtual void ccTouchesEnded(CCSet* touches, CCEvent* event);

	//CREATE_NODE(Box2DTestLayer);
} ;

class Box2DTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif


code:
#include "Box2dView.h"
#include "GLES-Render.h"
#include "Test.h"

#define kAccelerometerFrequency 30
#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10

extern int g_totalEntries;

Settings settings;

enum
{
	kTagBox2DNode,
};

//------------------------------------------------------------------
//
// MenuLayer
//
//------------------------------------------------------------------
enum
{
	IDC_NEXT = 100,
	IDC_BACK,
	IDC_RESTART
};

MenuLayer::MenuLayer(void)
{
}

MenuLayer::~MenuLayer(void)
{
}

MenuLayer* MenuLayer::menuWithEntryID(int entryId)
{
	MenuLayer* pLayer = new MenuLayer();
	pLayer->initWithEntryID(entryId);
	pLayer->autorelease();

	return pLayer;
}

bool MenuLayer::initWithEntryID(int entryId)
{
	CCSize s = CCDirector::sharedDirector()->getWinSize();

	m_entryID = entryId;

	setIsTouchEnabled( true );

	Box2DView* view = Box2DView::viewWithEntryID( entryId );
	addChild(view, 0, kTagBox2DNode);
	view->setScale(15);
	view->setAnchorPoint( ccp(0,0) );
	view->setPosition( ccp(s.width/2, s.height/3) );
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
//	CCLabelBMFont* label = CCLabelBMFont::labelWithString(view->title().c_str(),  "fonts/arial16.fnt");
//#else
	CCLabelTTF* label = CCLabelTTF::labelWithString(view->title().c_str(), "Arial", 28);
//#endif
	addChild(label, 1);
	label->setPosition( ccp(s.width/2, s.height-50) );

	CCMenuItemImage *item1 = CCMenuItemImage::itemFromNormalImage("Images/b1.png", "Images/b2.png", this, menu_selector(MenuLayer::backCallback) );
	CCMenuItemImage *item2 = CCMenuItemImage::itemFromNormalImage("Images/r1.png","Images/r2.png", this, menu_selector(MenuLayer::restartCallback) );
	CCMenuItemImage *item3 = CCMenuItemImage::itemFromNormalImage("Images/f1.png", "Images/f2.png", this, menu_selector(MenuLayer::nextCallback) );

	CCMenu *menu = CCMenu::menuWithItems(item1, item2, item3, NULL);

	menu->setPosition( CCPointZero );
	item1->setPosition( ccp( s.width/2 - 100,30) );
	item2->setPosition( ccp( s.width/2, 30) );
	item3->setPosition( ccp( s.width/2 + 100,30) );

	addChild(menu, 1);

	return true;
}

void MenuLayer::restartCallback(CCObject* sender)
{
	CCScene* s = new Box2dTestBedScene();
	MenuLayer* box = MenuLayer::menuWithEntryID(m_entryID);
	s->addChild( box );
	CCDirector::sharedDirector()->replaceScene( s );
    s->release();
}

void MenuLayer::nextCallback(CCObject* sender)
{
	CCScene* s = new Box2dTestBedScene();
	int next = m_entryID + 1;
	if( next >= g_totalEntries)
		next = 0;
	MenuLayer* box = MenuLayer::menuWithEntryID(next);
	s->addChild( box );
	CCDirector::sharedDirector()->replaceScene( s );
    s->release();
}

void MenuLayer::backCallback(CCObject* sender)
{
	CCScene* s = new Box2dTestBedScene();
	int next = m_entryID - 1;
	if( next < 0 ) {
		next = g_totalEntries - 1;
	}

	MenuLayer* box = MenuLayer::menuWithEntryID(next);

	s->addChild( box );
	CCDirector::sharedDirector()->replaceScene( s );
    s->release();
}

void MenuLayer::registerWithTouchDispatcher()
{
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);
}

bool MenuLayer::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
	return true;
}

//-(void) MenuLayer::ccTouchEnded:(UITouch *)touch withEvent:(CCEvent *)event
//{
//}
//
//-(void) MenuLayer::ccTouchCancelled:(UITouch *)touch withEvent:(CCEvent *)event
//{
//}

void MenuLayer::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
	CCPoint touchLocation = touch->locationInView();
	CCPoint prevLocation = touch->previousLocationInView();

	touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
	prevLocation = CCDirector::sharedDirector()->convertToGL( prevLocation );

	CCPoint diff = ccpSub(touchLocation,prevLocation);

	CCNode *node = getChildByTag( kTagBox2DNode );
	CCPoint currentPos = node->getPosition();
	node->setPosition( ccpAdd(currentPos, diff) );
}

//------------------------------------------------------------------
//
// Box2DView
//
//------------------------------------------------------------------
Box2DView::Box2DView(void)
{
}

Box2DView* Box2DView::viewWithEntryID(int entryId)
{
	Box2DView* pView = new Box2DView();
	pView->initWithEntryID(entryId);
	pView->autorelease();

	return pView;
}

bool Box2DView::initWithEntryID(int entryId)
{
//	setIsAccelerometerEnabled( true );
	setIsTouchEnabled( true );

	schedule( schedule_selector(Box2DView::tick) );

	m_entry = g_testEntries + entryId;
	m_test = m_entry->createFcn();

    return true;
}

std::string Box2DView::title()
{
	return std::string(m_entry->name);
}

void Box2DView::tick(ccTime dt)
{
	m_test->Step(&settings);
}

void Box2DView::draw()
{
	CCLayer::draw();

	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states:  GL_VERTEX_ARRAY,
	// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	m_test->m_world->DrawDebugData();

	// restore default GL states
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

Box2DView::~Box2DView()
{
	delete m_test;
}

void Box2DView::registerWithTouchDispatcher()
{
	// higher priority than dragging
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, -10, true);
}

bool Box2DView::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
	CCPoint touchLocation = touch->locationInView();
	touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );

	CCPoint nodePosition = convertToNodeSpace( touchLocation );
//	NSLog(@"pos: %f,%f -> %f,%f", touchLocation.x, touchLocation.y, nodePosition.x, nodePosition.y);

	return m_test->MouseDown(b2Vec2(nodePosition.x,nodePosition.y));
}

void Box2DView::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
	CCPoint touchLocation = touch->locationInView();
	touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
	CCPoint nodePosition = convertToNodeSpace( touchLocation );

	m_test->MouseMove(b2Vec2(nodePosition.x,nodePosition.y));
}

void Box2DView::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
	CCPoint touchLocation = touch->locationInView();
	touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
	CCPoint nodePosition = convertToNodeSpace( touchLocation );

	m_test->MouseUp(b2Vec2(nodePosition.x,nodePosition.y));
}

// void Box2DView::accelerometer(UIAccelerometer* accelerometer, CCAcceleration* acceleration)
// {
// 	//// Only run for valid values
// 	//if (acceleration.y!=0 && acceleration.x!=0)
// 	//{
// 	//	if (test) test->SetGravity((float)-acceleration.y,(float)acceleration.x);
// 	//}
// }

void Box2dTestBedScene::runThisTest()
{
    addChild(MenuLayer::menuWithEntryID(0));

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef _BOX2D_VIEW_H_
#define _BOX2D_VIEW_H_

//#include "cocos2d.h"
#include "../testBasic.h"

class MenuLayer : public CCLayer
{
	int		m_entryID;

public:
	MenuLayer(void);
	virtual ~MenuLayer(void);

	bool initWithEntryID(int entryId);

	void restartCallback(CCObject* sender);
	void nextCallback(CCObject* sender);
	void backCallback(CCObject* sender);

	virtual void registerWithTouchDispatcher();

	virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
	virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);

public:
	static MenuLayer* menuWithEntryID(int entryId);
};

struct TestEntry;
class Test;
class Box2DView : public CCLayer
{
	TestEntry*	m_entry;
	Test*		m_test;
	int			m_entryID;
public:
	Box2DView(void);
	virtual ~Box2DView(void);

	bool initWithEntryID(int entryId);
	std::string title();
	void tick(ccTime dt);
	void draw();

	virtual void registerWithTouchDispatcher();
	virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
	virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
	virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
	//virtual void accelerometer(UIAccelerometer* accelerometer, CCAcceleration* acceleration);

	static Box2DView* viewWithEntryID(int entryId);
};

class Box2dTestBedScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif


code:
#include "GLES-Render.h"
#include "CCGL.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

GLESDebugDraw::GLESDebugDraw()
	: mRatio( 1.0f )
{
}
GLESDebugDraw::GLESDebugDraw( float32 ratio )
	: mRatio( ratio )
{
}

void GLESDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
	b2Vec2* vertices = new b2Vec2[vertexCount];
	for( int i=0;i<vertexCount;i++)
	{
		vertices[i] = old_vertices[i];
		vertices[i] *= mRatio;
	}

	glColor4f(color.r, color.g, color.b,1);
	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glDrawArrays(GL_LINE_LOOP, 0, vertexCount);

	delete[] vertices;
}

void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
	b2Vec2* vertices = new b2Vec2[vertexCount];
	for( int i=0;i<vertexCount;i++) {
		vertices[i] = old_vertices[i];
		vertices[i] *= mRatio;
	}

	glVertexPointer(2, GL_FLOAT, 0, vertices);

	glColor4f(color.r, color.g, color.b,0.5f);
	glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);

	glColor4f(color.r, color.g, color.b,1);
	glDrawArrays(GL_LINE_LOOP, 0, vertexCount);

	delete[] vertices;
}

void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{

	const float32 k_segments = 16.0f;
	int vertexCount=16;
	const float32 k_increment = 2.0f * b2_pi / k_segments;
	float32 theta = 0.0f;

	GLfloat*	glVertices = new GLfloat[vertexCount*2];
	for (int i = 0; i < k_segments; ++i)
	{
		b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
		glVertices[i*2]=v.x * mRatio;
		glVertices[i*2+1]=v.y * mRatio;
		theta += k_increment;
	}

	glColor4f(color.r, color.g, color.b,1);
	glVertexPointer(2, GL_FLOAT, 0, glVertices);

	glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);

	delete[] glVertices;
}

void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{

	const float32 k_segments = 16.0f;
	int vertexCount=16;
	const float32 k_increment = 2.0f * b2_pi / k_segments;
	float32 theta = 0.0f;

	GLfloat*	glVertices = new GLfloat[vertexCount*2];
	for (int i = 0; i < k_segments; ++i)
	{
		b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
		glVertices[i*2]=v.x * mRatio;
		glVertices[i*2+1]=v.y * mRatio;
		theta += k_increment;
	}

	glColor4f(color.r, color.g, color.b,0.5f);
	glVertexPointer(2, GL_FLOAT, 0, glVertices);
	glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
	glColor4f(color.r, color.g, color.b,1);
	glDrawArrays(GL_LINE_LOOP, 0, vertexCount);

	// Draw the axis line
	DrawSegment(center,center+radius*axis,color);

	delete[] glVertices;
}

void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
	glColor4f(color.r, color.g, color.b,1);
	GLfloat	glVertices[] =
	{
		p1.x * mRatio, p1.y * mRatio,
		p2.x * mRatio, p2.y * mRatio
	};
	glVertexPointer(2, GL_FLOAT, 0, glVertices);
	glDrawArrays(GL_LINES, 0, 2);
}

void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
	b2Vec2 p1 = xf.p, p2;
	const float32 k_axisScale = 0.4f;

	p2 = p1 + k_axisScale * xf.q.GetXAxis();
	DrawSegment(p1,p2,b2Color(1,0,0));

	p2 = p1 + k_axisScale * xf.q.GetYAxis();
	DrawSegment(p1,p2,b2Color(0,1,0));
}

void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
	glColor4f(color.r, color.g, color.b,1);
	glPointSize(size);
	GLfloat				glVertices[] = {
		p.x * mRatio, p.y * mRatio
	};
	glVertexPointer(2, GL_FLOAT, 0, glVertices);
	glDrawArrays(GL_POINTS, 0, 1);
	glPointSize(1.0f);
}

void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
{
//	NSLog(@"DrawString: unsupported: %s", string);
	//printf(string);
	/* Unsupported as yet. Could replace with bitmap font renderer at a later date */
}

void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
{
	glColor4f(c.r, c.g, c.b,1);

	GLfloat				glVertices[] = {
		aabb->lowerBound.x * mRatio, aabb->lowerBound.y * mRatio,
		aabb->upperBound.x * mRatio, aabb->lowerBound.y * mRatio,
		aabb->upperBound.x * mRatio, aabb->upperBound.y * mRatio,
		aabb->lowerBound.x * mRatio, aabb->upperBound.y * mRatio
	};
	glVertexPointer(2, GL_FLOAT, 0, glVertices);
	glDrawArrays(GL_LINE_LOOP, 0, 8);

}


code:
#ifndef RENDER_H
#define RENDER_H

//#import <UIKit/UIKit.h>
//#import <OpenGLES/EAGL.h>
//#import <OpenGLES/ES1/gl.h>
//#import <OpenGLES/ES1/glext.h>

#include "Box2D/Box2D.h"

struct b2AABB;

// This class implements debug drawing callbacks that are invoked
// inside b2World::Step.
class GLESDebugDraw : public b2Draw
{
	float32 mRatio;
public:
	GLESDebugDraw();

	GLESDebugDraw( float32 ratio );

	virtual void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);

	virtual void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);

	virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);

	virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);

	virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);

	virtual void DrawTransform(const b2Transform& xf);

    virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);

    virtual void DrawString(int x, int y, const char* string, ...);

    virtual void DrawAABB(b2AABB* aabb, const b2Color& color);
};

#endif


code:
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#include "Test.h"
#include "GLES-Render.h"

#include <stdio.h>

void DestructionListener::SayGoodbye(b2Joint* joint)
{
	if (test->m_mouseJoint == joint)
	{
		test->m_mouseJoint = NULL;
	}
	else
	{
		test->JointDestroyed(joint);
	}
}

Test::Test()
{
	b2Vec2 gravity;
	gravity.Set(0.0f, -10.0f);
	m_world = new b2World(gravity);
	m_bomb = NULL;
	m_textLine = 30;
	m_mouseJoint = NULL;
	m_pointCount = 0;

	m_destructionListener.test = this;
	m_world->SetDestructionListener(&m_destructionListener);
	m_world->SetContactListener(this);
	m_world->SetDebugDraw(&m_debugDraw);

	m_bombSpawning = false;

	m_stepCount = 0;

	b2BodyDef bodyDef;
	m_groundBody = m_world->CreateBody(&bodyDef);

	memset(&m_maxProfile, 0, sizeof(b2Profile));
	memset(&m_totalProfile, 0, sizeof(b2Profile));
}

Test::~Test()
{
	// By deleting the world, we delete the bomb, mouse joint, etc.
	delete m_world;
	m_world = NULL;
}

void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
	const b2Manifold* manifold = contact->GetManifold();

	if (manifold->pointCount == 0)
	{
		return;
	}

	b2Fixture* fixtureA = contact->GetFixtureA();
	b2Fixture* fixtureB = contact->GetFixtureB();

	b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
	b2GetPointStates(state1, state2, oldManifold, manifold);

	b2WorldManifold worldManifold;
	contact->GetWorldManifold(&worldManifold);

	for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
	{
		ContactPoint* cp = m_points + m_pointCount;
		cp->fixtureA = fixtureA;
		cp->fixtureB = fixtureB;
		cp->position = worldManifold.points[i];
		cp->normal = worldManifold.normal;
		cp->state = state2[i];
		++m_pointCount;
	}
}

void Test::DrawTitle(int x, int y, const char *string)
{
    m_debugDraw.DrawString(x, y, string);
}

class QueryCallback : public b2QueryCallback
{
public:
	QueryCallback(const b2Vec2& point)
	{
		m_point = point;
		m_fixture = NULL;
	}

	bool ReportFixture(b2Fixture* fixture)
	{
		b2Body* body = fixture->GetBody();
		if (body->GetType() == b2_dynamicBody)
		{
			bool inside = fixture->TestPoint(m_point);
			if (inside)
			{
				m_fixture = fixture;

				// We are done, terminate the query.
				return false;
			}
		}

		// Continue the query.
		return true;
	}

	b2Vec2 m_point;
	b2Fixture* m_fixture;
};

bool Test::MouseDown(const b2Vec2& p)
{
	m_mouseWorld = p;

	if (m_mouseJoint != NULL)
	{
		return false;
	}

	// Make a small box.
	b2AABB aabb;
	b2Vec2 d;
	d.Set(0.001f, 0.001f);
	aabb.lowerBound = p - d;
	aabb.upperBound = p + d;

	// Query the world for overlapping shapes.
	QueryCallback callback(p);
	m_world->QueryAABB(&callback, aabb);

	if (callback.m_fixture)
	{
		b2Body* body = callback.m_fixture->GetBody();
		b2MouseJointDef md;
		md.bodyA = m_groundBody;
		md.bodyB = body;
		md.target = p;
		md.maxForce = 1000.0f * body->GetMass();
		m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
		body->SetAwake(true);
        return true;
	}
    return false;
}

void Test::SpawnBomb(const b2Vec2& worldPt)
{
	m_bombSpawnPoint = worldPt;
	m_bombSpawning = true;
}

void Test::CompleteBombSpawn(const b2Vec2& p)
{
	if (m_bombSpawning == false)
	{
		return;
	}

	const float multiplier = 30.0f;
	b2Vec2 vel = m_bombSpawnPoint - p;
	vel *= multiplier;
	LaunchBomb(m_bombSpawnPoint,vel);
	m_bombSpawning = false;
}

void Test::ShiftMouseDown(const b2Vec2& p)
{
	m_mouseWorld = p;

	if (m_mouseJoint != NULL)
	{
		return;
	}

	SpawnBomb(p);
}

void Test::MouseUp(const b2Vec2& p)
{
	if (m_mouseJoint)
	{
		m_world->DestroyJoint(m_mouseJoint);
		m_mouseJoint = NULL;
	}

	if (m_bombSpawning)
	{
		CompleteBombSpawn(p);
	}
}

void Test::MouseMove(const b2Vec2& p)
{
	m_mouseWorld = p;

	if (m_mouseJoint)
	{
		m_mouseJoint->SetTarget(p);
	}
}

void Test::LaunchBomb()
{
	b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
	b2Vec2 v = -5.0f * p;
	LaunchBomb(p, v);
}

void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
{
	if (m_bomb)
	{
		m_world->DestroyBody(m_bomb);
		m_bomb = NULL;
	}

	b2BodyDef bd;
	bd.type = b2_dynamicBody;
	bd.position = position;
	bd.bullet = true;
	m_bomb = m_world->CreateBody(&bd);
	m_bomb->SetLinearVelocity(velocity);

	b2CircleShape circle;
	circle.m_radius = 0.3f;

	b2FixtureDef fd;
	fd.shape = &circle;
	fd.density = 20.0f;
	fd.restitution = 0.0f;

	b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
	b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);

	b2AABB aabb;
	aabb.lowerBound = minV;
	aabb.upperBound = maxV;

	m_bomb->CreateFixture(&fd);
}

void Test::Step(Settings* settings)
{
	float32 timeStep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);

	if (settings->pause)
	{
		if (settings->singleStep)
		{
			settings->singleStep = 0;
		}
		else
		{
			timeStep = 0.0f;
		}

		m_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
		m_textLine += 15;
	}

	uint32 flags = 0;
	flags += settings->drawShapes			* b2Draw::e_shapeBit;
	flags += settings->drawJoints			* b2Draw::e_jointBit;
	flags += settings->drawAABBs			* b2Draw::e_aabbBit;
	flags += settings->drawPairs			* b2Draw::e_pairBit;
	flags += settings->drawCOMs				* b2Draw::e_centerOfMassBit;
	m_debugDraw.SetFlags(flags);

	m_world->SetWarmStarting(settings->enableWarmStarting > 0);
	m_world->SetContinuousPhysics(settings->enableContinuous > 0);
	m_world->SetSubStepping(settings->enableSubStepping > 0);

	m_pointCount = 0;

	m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);

	m_world->DrawDebugData();

	if (timeStep > 0.0f)
	{
		++m_stepCount;
	}

	if (settings->drawStats)
	{
		int32 bodyCount = m_world->GetBodyCount();
		int32 contactCount = m_world->GetContactCount();
		int32 jointCount = m_world->GetJointCount();
		m_debugDraw.DrawString(5, m_textLine, "bodies/contacts/joints = %d/%d/%d", bodyCount, contactCount, jointCount);
		m_textLine += 15;

		int32 proxyCount = m_world->GetProxyCount();
		int32 height = m_world->GetTreeHeight();
		int32 balance = m_world->GetTreeBalance();
		float32 quality = m_world->GetTreeQuality();
		m_debugDraw.DrawString(5, m_textLine, "proxies/height/balance/quality = %d/%d/%d/%g", proxyCount, height, balance, quality);
		m_textLine += 15;
	}

	// Track maximum profile times
	{
		const b2Profile& p = m_world->GetProfile();
		m_maxProfile.step = b2Max(m_maxProfile.step, p.step);
		m_maxProfile.collide = b2Max(m_maxProfile.collide, p.collide);
		m_maxProfile.solve = b2Max(m_maxProfile.solve, p.solve);
		m_maxProfile.solveInit = b2Max(m_maxProfile.solveInit, p.solveInit);
		m_maxProfile.solveVelocity = b2Max(m_maxProfile.solveVelocity, p.solveVelocity);
		m_maxProfile.solvePosition = b2Max(m_maxProfile.solvePosition, p.solvePosition);
		m_maxProfile.solveTOI = b2Max(m_maxProfile.solveTOI, p.solveTOI);
		m_maxProfile.broadphase = b2Max(m_maxProfile.broadphase, p.broadphase);

		m_totalProfile.step += p.step;
		m_totalProfile.collide += p.collide;
		m_totalProfile.solve += p.solve;
		m_totalProfile.solveInit += p.solveInit;
		m_totalProfile.solveVelocity += p.solveVelocity;
		m_totalProfile.solvePosition += p.solvePosition;
		m_totalProfile.solveTOI += p.solveTOI;
		m_totalProfile.broadphase += p.broadphase;
	}

	if (settings->drawProfile)
	{
		const b2Profile& p = m_world->GetProfile();

		b2Profile aveProfile;
		memset(&aveProfile, 0, sizeof(b2Profile));
		if (m_stepCount > 0)
		{
			float32 scale = 1.0f / m_stepCount;
			aveProfile.step = scale * m_totalProfile.step;
			aveProfile.collide = scale * m_totalProfile.collide;
			aveProfile.solve = scale * m_totalProfile.solve;
			aveProfile.solveInit = scale * m_totalProfile.solveInit;
			aveProfile.solveVelocity = scale * m_totalProfile.solveVelocity;
			aveProfile.solvePosition = scale * m_totalProfile.solvePosition;
			aveProfile.solveTOI = scale * m_totalProfile.solveTOI;
			aveProfile.broadphase = scale * m_totalProfile.broadphase;
		}

		m_debugDraw.DrawString(5, m_textLine, "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, m_maxProfile.step);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, m_maxProfile.collide);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, m_maxProfile.solve);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "solve init [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveInit, aveProfile.solveInit, m_maxProfile.solveInit);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "solve velocity [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveVelocity, aveProfile.solveVelocity, m_maxProfile.solveVelocity);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "solve position [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solvePosition, aveProfile.solvePosition, m_maxProfile.solvePosition);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "solveTOI [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveTOI, aveProfile.solveTOI, m_maxProfile.solveTOI);
		m_textLine += 15;
		m_debugDraw.DrawString(5, m_textLine, "broad-phase [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.broadphase, aveProfile.broadphase, m_maxProfile.broadphase);
		m_textLine += 15;
	}

	if (m_mouseJoint)
	{
		b2Vec2 p1 = m_mouseJoint->GetAnchorB();
		b2Vec2 p2 = m_mouseJoint->GetTarget();

		b2Color c;
		c.Set(0.0f, 1.0f, 0.0f);
		m_debugDraw.DrawPoint(p1, 4.0f, c);
		m_debugDraw.DrawPoint(p2, 4.0f, c);

		c.Set(0.8f, 0.8f, 0.8f);
		m_debugDraw.DrawSegment(p1, p2, c);
	}

	if (m_bombSpawning)
	{
		b2Color c;
		c.Set(0.0f, 0.0f, 1.0f);
		m_debugDraw.DrawPoint(m_bombSpawnPoint, 4.0f, c);

		c.Set(0.8f, 0.8f, 0.8f);
		m_debugDraw.DrawSegment(m_mouseWorld, m_bombSpawnPoint, c);
	}

	if (settings->drawContactPoints)
	{
		//const float32 k_impulseScale = 0.1f;
		const float32 k_axisScale = 0.3f;

		for (int32 i = 0; i < m_pointCount; ++i)
		{
			ContactPoint* point = m_points + i;

			if (point->state == b2_addState)
			{
				// Add
				m_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
			}
			else if (point->state == b2_persistState)
			{
				// Persist
				m_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
			}

			if (settings->drawContactNormals == 1)
			{
				b2Vec2 p1 = point->position;
				b2Vec2 p2 = p1 + k_axisScale * point->normal;
				m_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f));
			}
			else if (settings->drawContactForces == 1)
			{
				//b2Vec2 p1 = point->position;
				//b2Vec2 p2 = p1 + k_forceScale * point->normalForce * point->normal;
				//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
			}

			if (settings->drawFrictionForces == 1)
			{
				//b2Vec2 tangent = b2Cross(point->normal, 1.0f);
				//b2Vec2 p1 = point->position;
				//b2Vec2 p2 = p1 + k_forceScale * point->tangentForce * tangent;
				//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
			}
		}
	}
}


code:
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#ifndef TEST_H
#define TEST_H

#include <Box2D/Box2D.h>
#include "GLES-Render.h"

#include <cstdlib>

class Test;
struct Settings;

typedef Test* TestCreateFcn();

#define	RAND_LIMIT	32767

/// Random number in range [-1,1]
inline float32 RandomFloat()
{
	float32 r = (float32)(std::rand() & (RAND_LIMIT));
	r /= RAND_LIMIT;
	r = 2.0f * r - 1.0f;
	return r;
}

/// Random floating point number in range [lo, hi]
inline float32 RandomFloat(float32 lo, float32 hi)
{
	float32 r = (float32)(std::rand() & (RAND_LIMIT));
	r /= RAND_LIMIT;
	r = (hi - lo) * r + lo;
	return r;
}

/// Test settings. Some can be controlled in the GUI.
struct Settings
{
	Settings() :
		viewCenter(0.0f, 20.0f),
		hz(60.0f),
		velocityIterations(8),
		positionIterations(3),
		drawShapes(1),
		drawJoints(1),
		drawAABBs(0),
		drawPairs(0),
		drawContactPoints(0),
		drawContactNormals(0),
		drawContactForces(0),
		drawFrictionForces(0),
		drawCOMs(0),
		drawStats(0),
		drawProfile(0),
		enableWarmStarting(1),
		enableContinuous(1),
		enableSubStepping(0),
		pause(0),
		singleStep(0)
		{}

	b2Vec2 viewCenter;
	float32 hz;
	int32 velocityIterations;
	int32 positionIterations;
	int32 drawShapes;
	int32 drawJoints;
	int32 drawAABBs;
	int32 drawPairs;
	int32 drawContactPoints;
	int32 drawContactNormals;
	int32 drawContactForces;
	int32 drawFrictionForces;
	int32 drawCOMs;
	int32 drawStats;
	int32 drawProfile;
	int32 enableWarmStarting;
	int32 enableContinuous;
	int32 enableSubStepping;
	int32 pause;
	int32 singleStep;
};

struct TestEntry
{
	const char *name;
	TestCreateFcn *createFcn;
};

extern TestEntry g_testEntries[];
// This is called when a joint in the world is implicitly destroyed
// because an attached body is destroyed. This gives us a chance to
// nullify the mouse joint.
class DestructionListener : public b2DestructionListener
{
public:
	void SayGoodbye(b2Fixture* fixture) { B2_NOT_USED(fixture); }
	void SayGoodbye(b2Joint* joint);

	Test* test;
};

const int32 k_maxContactPoints = 2048;

struct ContactPoint
{
	b2Fixture* fixtureA;
	b2Fixture* fixtureB;
	b2Vec2 normal;
	b2Vec2 position;
	b2PointState state;
};

class Test : public b2ContactListener
{
public:

	Test();
	virtual ~Test();

	void SetTextLine(int32 line) { m_textLine = line; }
    void DrawTitle(int x, int y, const char *string);
	virtual void Step(Settings* settings);
	virtual void Keyboard(unsigned char key) { B2_NOT_USED(key); }
	virtual void KeyboardUp(unsigned char key) { B2_NOT_USED(key); }
	void ShiftMouseDown(const b2Vec2& p);
	virtual bool MouseDown(const b2Vec2& p);
	virtual void MouseUp(const b2Vec2& p);
	void MouseMove(const b2Vec2& p);
	void LaunchBomb();
	void LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);

	void SpawnBomb(const b2Vec2& worldPt);
	void CompleteBombSpawn(const b2Vec2& p);

	// Let derived tests know that a joint was destroyed.
	virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }

	// Callbacks for derived classes.
	virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
	virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
	virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
	virtual void PostSolve(const b2Contact* contact, const b2ContactImpulse* impulse)
	{
		B2_NOT_USED(contact);
		B2_NOT_USED(impulse);
	}

public:
	friend class DestructionListener;
	friend class BoundaryListener;
	friend class ContactListener;

	b2Body* m_groundBody;
	b2AABB m_worldAABB;
	ContactPoint m_points[k_maxContactPoints];
	int32 m_pointCount;
	DestructionListener m_destructionListener;
	GLESDebugDraw m_debugDraw;
	int32 m_textLine;
	b2World* m_world;
	b2Body* m_bomb;
	b2MouseJoint* m_mouseJoint;
	b2Vec2 m_bombSpawnPoint;
	bool m_bombSpawning;
	b2Vec2 m_mouseWorld;
	int32 m_stepCount;

	b2Profile m_maxProfile;
	b2Profile m_totalProfile;
};

#endif


code:
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#include "Test.h"

#include <cstring>
using namespace std;

#include "Tests/AddPair.h"
#include "Tests/ApplyForce.h"
#include "Tests/BodyTypes.h"
#include "Tests/Breakable.h"
#include "Tests/Bridge.h"
#include "Tests/BulletTest.h"
#include "Tests/Cantilever.h"
#include "Tests/Car.h"
#include "Tests/ContinuousTest.h"
#include "Tests/Chain.h"
#include "Tests/CharacterCollision.h"
#include "Tests/CollisionFiltering.h"
#include "Tests/CollisionProcessing.h"
#include "Tests/CompoundShapes.h"
#include "Tests/Confined.h"
#include "Tests/DistanceTest.h"
#include "Tests/Dominos.h"
#include "Tests/DumpShell.h"
#include "Tests/DynamicTreeTest.h"
#include "Tests/EdgeShapes.h"
#include "Tests/EdgeTest.h"
#include "Tests/Gears.h"
#include "Tests/OneSidedPlatform.h"
#include "Tests/Pinball.h"
#include "Tests/PolyCollision.h"
#include "Tests/PolyShapes.h"
#include "Tests/Prismatic.h"
#include "Tests/Pulleys.h"
#include "Tests/Pyramid.h"
#include "Tests/RayCast.h"
#include "Tests/Revolute.h"
//#include "Tests/Rope.h"
#include "Tests/RopeJoint.h"
#include "Tests/SensorTest.h"
#include "Tests/ShapeEditing.h"
#include "Tests/SliderCrank.h"
#include "Tests/SphereStack.h"
#include "Tests/TheoJansen.h"
#include "Tests/Tiles.h"
#include "Tests/TimeOfImpact.h"
#include "Tests/Tumbler.h"
#include "Tests/VaryingFriction.h"
#include "Tests/VaryingRestitution.h"
#include "Tests/VerticalStack.h"
#include "Tests/Web.h"

TestEntry g_testEntries[] =
{
	{"Tumbler", Tumbler::Create},
	{"Tiles", Tiles::Create},
	{"Dump Shell", DumpShell::Create},
	{"Gears", Gears::Create},
	{"Cantilever", Cantilever::Create},
	{"Varying Restitution", VaryingRestitution::Create},
	{"Character Collision", CharacterCollision::Create},
	{"Edge Test", EdgeTest::Create},
	{"Body Types", BodyTypes::Create},
	{"Shape Editing", ShapeEditing::Create},
	{"Car", Car::Create},
	{"Apply Force", ApplyForce::Create},
	{"Prismatic", Prismatic::Create},
	{"Vertical Stack", VerticalStack::Create},
	{"SphereStack", SphereStack::Create},
	{"Revolute", Revolute::Create},
	{"Pulleys", Pulleys::Create},
	{"Polygon Shapes", PolyShapes::Create},
	//{"Rope", Rope::Create},
	{"Web", Web::Create},
	{"RopeJoint", RopeJoint::Create},
	{"One-Sided Platform", OneSidedPlatform::Create},
	{"Pinball", Pinball::Create},
	{"Bullet Test", BulletTest::Create},
	{"Continuous Test", ContinuousTest::Create},
	{"Time of Impact", TimeOfImpact::Create},
	{"Ray-Cast", RayCast::Create},
	{"Confined", Confined::Create},
	{"Pyramid", Pyramid::Create},
	{"Theo Jansen's Walker", TheoJansen::Create},
	{"Edge Shapes", EdgeShapes::Create},
	{"PolyCollision", PolyCollision::Create},
	{"Bridge", Bridge::Create},
	{"Breakable", Breakable::Create},
	{"Chain", Chain::Create},
	{"Collision Filtering", CollisionFiltering::Create},
	{"Collision Processing", CollisionProcessing::Create},
	{"Compound Shapes", CompoundShapes::Create},
	{"Distance Test", DistanceTest::Create},
	{"Dominos", Dominos::Create},
	{"Dynamic Tree", DynamicTreeTest::Create},
	{"Sensor Test", SensorTest::Create},
	{"Slider Crank", SliderCrank::Create},
	{"Varying Friction", VaryingFriction::Create},
	{"Add Pair Stress Test", AddPair::Create},
//	{NULL, NULL}
};

int g_totalEntries = sizeof(g_testEntries) / sizeof(g_testEntries[0]);


code:
#ifndef AddPair_H
#define AddPair_H

class AddPair : public Test
{
public:

	AddPair()
	{
		m_world->SetGravity(b2Vec2(0.0f,0.0f));
		{
			b2CircleShape shape;
			shape.m_p.SetZero();
			shape.m_radius = 0.1f;

			float minX = -6.0f;
			float maxX = 0.0f;
			float minY = 4.0f;
			float maxY = 6.0f;

			for (int32 i = 0; i < 400; ++i)
			{
				b2BodyDef bd;
				bd.type = b2_dynamicBody;
				bd.position = b2Vec2(RandomFloat(minX,maxX),RandomFloat(minY,maxY));
				b2Body* body = m_world->CreateBody(&bd);
				body->CreateFixture(&shape, 0.01f);
			}
		}

		{
			b2PolygonShape shape;
			shape.SetAsBox(1.5f, 1.5f);
			b2BodyDef bd;
			bd.type = b2_dynamicBody;
			bd.position.Set(-40.0f,5.0f);
			bd.bullet = true;
			b2Body* body = m_world->CreateBody(&bd);
			body->CreateFixture(&shape, 1.0f);
			body->SetLinearVelocity(b2Vec2(150.0f, 0.0f));
		}
	}

	static Test* Create()
	{
		return new AddPair;
	}
};

#endif


code:
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#ifndef APPLY_FORCE_H
#define APPLY_FORCE_H

class ApplyForce : public Test
{
public:
	ApplyForce()
	{
		m_world->SetGravity(b2Vec2(0.0f, 0.0f));

		const float32 k_restitution = 0.4f;

		b2Body* ground;
		{
			b2BodyDef bd;
			bd.position.Set(0.0f, 20.0f);
			ground = m_world->CreateBody(&bd);

			b2EdgeShape shape;

			b2FixtureDef sd;
			sd.shape = &shape;
			sd.density = 0.0f;
			sd.restitution = k_restitution;

			// Left vertical
			shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f));
			ground->CreateFixture(&sd);

			// Right vertical
			shape.Set(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f));
			ground->CreateFixture(&sd);

			// Top horizontal
			shape.Set(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f));
			ground->CreateFixture(&sd);

			// Bottom horizontal
			shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f));
			ground->CreateFixture(&sd);
		}

		{
			b2Transform xf1;
			xf1.q.Set(0.3524f * b2_pi);
			xf1.p = xf1.q.GetXAxis();

			b2Vec2 vertices[3];
			vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f));
			vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f));
			vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f));

			b2PolygonShape poly1;
			poly1.Set(vertices, 3);

			b2FixtureDef sd1;
			sd1.shape = &poly1;
			sd1.density = 4.0f;

			b2Transform xf2;
			xf2.q.Set(-0.3524f * b2_pi);
			xf2.p = -xf2.q.GetXAxis();

			vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f));
			vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f));
			vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f));

			b2PolygonShape poly2;
			poly2.Set(vertices, 3);

			b2FixtureDef sd2;
			sd2.shape = &poly2;
			sd2.density = 2.0f;

			b2BodyDef bd;
			bd.type = b2_dynamicBody;
			bd.angularDamping = 5.0f;
			bd.linearDamping = 0.1f;

			bd.position.Set(0.0f, 2.0);
			bd.angle = b2_pi;
			bd.allowSleep = false;
			m_body = m_world->CreateBody(&bd);
			m_body->CreateFixture(&sd1);
			m_body->CreateFixture(&sd2);
		}

		{
			b2PolygonShape shape;
			shape.SetAsBox(0.5f, 0.5f);

			b2FixtureDef fd;
			fd.shape = &shape;
			fd.density = 1.0f;
			fd.friction = 0.3f;

			for (int i = 0; i < 10; ++i)
			{
				b2BodyDef bd;
				bd.type = b2_dynamicBody;

				bd.position.Set(0.0f, 5.0f + 1.54f * i);
				b2Body* body = m_world->CreateBody(&bd);

				body->CreateFixture(&fd);

				float32 gravity = 10.0f;
				float32 I = body->GetInertia();
				float32 mass = body->GetMass();

				// For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m)
				float32 radius = b2Sqrt(2.0f * I / mass);

				b2FrictionJointDef jd;
				jd.localAnchorA.SetZero();
				jd.localAnchorB.SetZero();
				jd.bodyA = ground;
				jd.bodyB = body;
				jd.collideConnected = true;
				jd.maxForce = mass * gravity;
				jd.maxTorque = mass * radius * gravity;

				m_world->CreateJoint(&jd);
			}
		}
	}

	void Keyboard(unsigned char key)
	{
		switch (key)
		{
		case 'w':
			{
				b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -200.0f));
				b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 2.0f));
				m_body->ApplyForce(f, p);
			}
			break;

		case 'a':
			{
				m_body->ApplyTorque(50.0f);
			}
			break;

		case 'd':
			{
				m_body->ApplyTorque(-50.0f);
			}
			break;
		}
	}

	static Test* Create()
	{
		return new ApplyForce;
	}

	b2Body* m_body;
};

#endif


code:
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#ifndef BODY_TYPES_H
#define BODY_TYPES_H

class BodyTypes : public Test
{
public:
	BodyTypes()
	{
		b2Body* ground = NULL;
		{
			b2BodyDef bd;
			ground = m_world->CreateBody(&bd);

			b2EdgeShape shape;
			shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));

			b2FixtureDef fd;
			fd.shape = &shape;

			ground->CreateFixture(&fd);
		}

		// Define attachment
		{
			b2BodyDef bd;
			bd.type = b2_dynamicBody;
			bd.position.Set(0.0f, 3.0f);
			m_attachment = m_world->CreateBody(&bd);

			b2PolygonShape shape;
			shape.SetAsBox(0.5f, 2.0f);
			m_attachment->CreateFixture(&shape, 2.0f);
		}

		// Define platform
		{
			b2BodyDef bd;
			bd.type = b2_dynamicBody;
			bd.position.Set(-4.0f, 5.0f);
			m_platform = m_world->CreateBody(&bd);

			b2PolygonShape shape;
			shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi);

			b2FixtureDef fd;
			fd.shape = &shape;
			fd.friction = 0.6f;
			fd.density = 2.0f;
			m_platform->CreateFixture(&fd);

			b2RevoluteJointDef rjd;
			rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f));
			rjd.maxMotorTorque = 50.0f;
			rjd.enableMotor = true;
			m_world->CreateJoint(&rjd);

			b2PrismaticJointDef pjd;
			pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f));

			pjd.maxMotorForce = 1000.0f;
			pjd.enableMotor = true;
			pjd.lowerTranslation = -10.0f;
			pjd.upperTranslation = 10.0f;
			pjd.enableLimit = true;

			m_world->CreateJoint(&pjd);

			m_speed = 3.0f;
		}

		// Create a payload
		{
			b2BodyDef bd;
			bd.type = b2_dynamicBody;
			bd.position.Set(0.0f, 8.0f);
			b2Body* body = m_world->CreateBody(&bd);

			b2PolygonShape shape;
			shape.SetAsBox(0.75f, 0.75f);

			b2FixtureDef fd;
			fd.shape = &shape;
			fd.friction = 0.6f;
			fd.density = 2.0f;

			body->CreateFixture(&fd);
		}
	}

	void Keyboard(unsigned char key)
	{
		switch (key)
		{
		case 'd':
			m_platform->SetType(b2_dynamicBody);
			break;

		case 's':
			m_platform->SetType(b2_staticBody);
			break;

		case 'k':
			m_platform->SetType(b2_kinematicBody);
			m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f));
			m_platform->SetAngularVelocity(0.0f);
			break;
		}
	}

	void Step(Settings* settings)
	{
		// Drive the kinematic body.
		if (m_platform->GetType() == b2_kinematicBody)
		{
			b2Vec2 p = m_platform->GetTransform().p;
			b2Vec2 v = m_platform->GetLinearVelocity();

			if ((p.x < -10.0f && v.x < 0.0f) ||
				(p.x > 10.0f && v.x > 0.0f))
			{
				v.x = -v.x;
				m_platform->SetLinearVelocity(v);
			}
		}

		Test::Step(settings);
		m_debugDraw.DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic");
		m_textLine += 15;
	}

	static Test* Create()
	{
		return new BodyTypes;
	}

	b2Body* m_attachment;
	b2Body* m_platform;
	float32 m_speed;
};

#endif