2010-08-05 14:32:04 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "CCAction.h"
|
2010-08-06 11:58:03 +08:00
|
|
|
#include "CCIntervalAction.h"
|
2010-08-05 14:32:04 +08:00
|
|
|
#include "ccMacros.h"
|
|
|
|
#include "CCNode.h"
|
2010-08-25 10:19:20 +08:00
|
|
|
#include "CGPointExtension.h"
|
2010-08-05 14:32:04 +08:00
|
|
|
#include "CCDirector.h"
|
|
|
|
#include "NSZone.h"
|
|
|
|
|
|
|
|
namespace cocos2d {
|
|
|
|
//
|
|
|
|
// Action Base Class
|
|
|
|
//
|
|
|
|
|
|
|
|
CCAction::CCAction()
|
|
|
|
:m_pOriginalTarget(NULL)
|
|
|
|
,m_pTarget(NULL)
|
|
|
|
,m_nTag(kCCActionTagInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
CCAction::~CCAction()
|
|
|
|
{
|
|
|
|
CCLOGINFO("cocos2d: deallocing");
|
|
|
|
}
|
|
|
|
CCAction * CCAction::action()
|
|
|
|
{
|
|
|
|
CCAction * pRet = new CCAction();
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
|
2010-08-06 16:05:19 +08:00
|
|
|
char * CCAction::description()
|
2010-08-05 14:32:04 +08:00
|
|
|
{
|
2010-08-06 16:05:19 +08:00
|
|
|
char *ret = new char[100] ;
|
|
|
|
sprintf_s(ret, 100, "<CCAction | Tag = %d>", m_nTag);
|
2010-08-05 14:32:04 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
NSObject* CCAction::copyWithZone(NSZone *pZone)
|
|
|
|
{
|
|
|
|
NSZone *pNewZone = NULL;
|
|
|
|
CCAction *pRet = NULL;
|
|
|
|
if (pZone && pZone->m_pCopyObject)
|
|
|
|
{
|
2010-08-27 14:13:32 +08:00
|
|
|
pRet = (CCAction*)(pZone->m_pCopyObject);
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pRet = new CCAction();
|
|
|
|
pZone = pNewZone = new NSZone(pRet);
|
|
|
|
}
|
|
|
|
//copy member data
|
|
|
|
pRet->m_nTag = m_nTag;
|
|
|
|
CCX_SAFE_DELETE(pNewZone);
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCAction::startWithTarget(NSObject *aTarget)
|
|
|
|
{
|
|
|
|
m_pOriginalTarget = m_pTarget = aTarget;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCAction::stop()
|
|
|
|
{
|
|
|
|
m_pTarget = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CCAction::isDone()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCAction::step(ccTime dt)
|
|
|
|
{
|
|
|
|
CCLOG("[Action step]. override me");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCAction::update(ccTime time)
|
|
|
|
{
|
|
|
|
CCLOG("[Action update]. override me");
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// FiniteTimeAction
|
|
|
|
//
|
|
|
|
|
|
|
|
CCFiniteTimeAction *CCFiniteTimeAction::reverse()
|
|
|
|
{
|
|
|
|
CCLOG("cocos2d: FiniteTimeAction#reverse: Implement me");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// RepeatForever
|
|
|
|
//
|
|
|
|
CCRepeatForever::~CCRepeatForever()
|
|
|
|
{
|
2010-08-06 11:58:03 +08:00
|
|
|
m_pOther->release();
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
CCRepeatForever *CCRepeatForever::actionWithAction(CCIntervalAction *pAction)
|
|
|
|
{
|
|
|
|
CCRepeatForever *pRet = new CCRepeatForever();
|
2010-08-19 14:09:40 +08:00
|
|
|
if (pRet && pRet->initWithAction(pAction))
|
2010-08-05 14:32:04 +08:00
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
2010-08-19 14:09:40 +08:00
|
|
|
CCX_SAFE_DELETE(pRet);
|
2010-08-05 14:32:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCRepeatForever *CCRepeatForever::initWithAction(CCIntervalAction *pAction)
|
|
|
|
{
|
2010-08-06 11:58:03 +08:00
|
|
|
pAction->retain();
|
|
|
|
m_pOther = pAction;
|
2010-08-05 14:32:04 +08:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
NSObject* CCRepeatForever::copyWithZone(NSZone *pZone)
|
|
|
|
{
|
|
|
|
NSZone* pNewZone = NULL;
|
|
|
|
CCRepeatForever* pRet = NULL;
|
|
|
|
if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
|
|
|
|
{
|
2010-08-27 14:13:32 +08:00
|
|
|
pRet = (CCRepeatForever*)(pZone->m_pCopyObject);
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pRet = new CCRepeatForever();
|
|
|
|
pZone = pNewZone = new NSZone(pRet);
|
|
|
|
}
|
|
|
|
__super::copyWithZone(pZone);
|
|
|
|
// win32 : use the m_pOther's copy object.
|
2010-08-27 14:13:32 +08:00
|
|
|
pRet->initWithAction( (CCIntervalAction*)(m_pOther->copy()->autorelease()) );
|
2010-08-05 14:32:04 +08:00
|
|
|
CCX_SAFE_DELETE(pNewZone);
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCRepeatForever::startWithTarget(NSObject* pTarget)
|
|
|
|
{
|
|
|
|
__super::startWithTarget(pTarget);
|
2010-08-06 11:58:03 +08:00
|
|
|
m_pOther->startWithTarget(pTarget);
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCRepeatForever::step(ccTime dt)
|
|
|
|
{
|
2010-08-06 11:58:03 +08:00
|
|
|
m_pOther->step(dt);
|
|
|
|
if (m_pOther->isDone())
|
|
|
|
{
|
|
|
|
ccTime diff = dt + m_pOther->getDuration() - m_pOther->getElapsed();
|
|
|
|
m_pOther->startWithTarget(m_pTarget);
|
|
|
|
// to prevent jerk. issue #390
|
|
|
|
m_pOther->step(diff);
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCRepeatForever::isDone()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCIntervalAction *CCRepeatForever::reverse()
|
|
|
|
{
|
2010-08-06 11:58:03 +08:00
|
|
|
return dynamic_cast<CCIntervalAction*>(CCRepeatForever::actionWithAction(m_pOther->reverse()));
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Speed
|
|
|
|
//
|
|
|
|
CCSpeed::~CCSpeed()
|
|
|
|
{
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
CCX_SAFE_RELEASE(m_pOther);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCX_SAFE_RELEASE(m_pRepeat);
|
|
|
|
}
|
|
|
|
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CCSpeed * CCSpeed::actionWithAction(CCIntervalAction *pAction, float fRate)
|
|
|
|
{
|
|
|
|
CCSpeed *pRet = new CCSpeed();
|
2010-08-19 14:09:40 +08:00
|
|
|
if (pRet && pRet->initWithAction(pAction, fRate))
|
2010-08-05 14:32:04 +08:00
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
2010-08-19 14:09:40 +08:00
|
|
|
CCX_SAFE_DELETE(pRet)
|
2010-08-05 14:32:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-08-25 16:08:10 +08:00
|
|
|
CCSpeed* CCSpeed::actionWithAction(CCRepeatForever *pAction, float fRate)
|
|
|
|
{
|
|
|
|
CCSpeed *pRet = new CCSpeed();
|
|
|
|
if (pRet && pRet->initWithAction(pAction, fRate))
|
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
CCX_SAFE_DELETE(pRet)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-08-05 14:32:04 +08:00
|
|
|
CCSpeed * CCSpeed::initWithAction(CCIntervalAction *pAction, float fRate)
|
|
|
|
{
|
2010-08-06 11:58:03 +08:00
|
|
|
pAction->retain();
|
|
|
|
m_pOther = pAction;
|
2010-08-25 16:08:10 +08:00
|
|
|
m_pRepeat = NULL;
|
2010-08-05 14:32:04 +08:00
|
|
|
m_fSpeed = fRate;
|
|
|
|
return this;
|
|
|
|
}
|
2010-08-25 16:08:10 +08:00
|
|
|
|
|
|
|
CCSpeed* CCSpeed::initWithAction(CCRepeatForever *pAction, float fRate)
|
|
|
|
{
|
|
|
|
pAction->retain();
|
|
|
|
m_pRepeat = pAction;
|
|
|
|
m_pOther = NULL;
|
|
|
|
m_fSpeed = fRate;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-08-05 14:32:04 +08:00
|
|
|
NSObject *CCSpeed::copyWithZone(NSZone *pZone)
|
|
|
|
{
|
|
|
|
NSZone* pNewZone = NULL;
|
|
|
|
CCSpeed* pRet = NULL;
|
|
|
|
if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
|
|
|
|
{
|
|
|
|
pRet = dynamic_cast<CCSpeed*>(pZone->m_pCopyObject);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pRet = new CCSpeed();
|
|
|
|
pZone = pNewZone = new NSZone(pRet);
|
|
|
|
}
|
|
|
|
__super::copyWithZone(pZone);
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
pRet->initWithAction( dynamic_cast<CCIntervalAction*>(m_pOther->copy()->autorelease()) , m_fSpeed );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pRet->initWithAction( dynamic_cast<CCIntervalAction*>(m_pRepeat->copy()->autorelease()) , m_fSpeed );
|
|
|
|
}
|
|
|
|
|
2010-08-05 14:32:04 +08:00
|
|
|
CCX_SAFE_DELETE(pNewZone);
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCSpeed::startWithTarget(NSObject* pTarget)
|
|
|
|
{
|
|
|
|
__super::startWithTarget(pTarget);
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
m_pOther->startWithTarget(pTarget);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pRepeat->startWithTarget(pTarget);
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCSpeed::stop()
|
|
|
|
{
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
m_pOther->stop();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pRepeat->stop();
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
__super::stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCSpeed::step(ccTime dt)
|
|
|
|
{
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
m_pOther->step(dt * m_fSpeed);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pRepeat->step(dt * m_fSpeed);
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCSpeed::isDone()
|
|
|
|
{
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
return m_pOther->isDone();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return m_pRepeat->isDone();
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CCIntervalAction *CCSpeed::reverse()
|
|
|
|
{
|
2010-08-25 16:08:10 +08:00
|
|
|
if (m_pOther)
|
|
|
|
{
|
|
|
|
return dynamic_cast<CCIntervalAction*>(CCSpeed::actionWithAction(m_pOther->reverse(), m_fSpeed));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return dynamic_cast<CCIntervalAction*>(CCSpeed::actionWithAction(m_pRepeat->reverse(), m_fSpeed));
|
|
|
|
}
|
2010-08-05 14:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Follow
|
|
|
|
//
|
|
|
|
CCFollow::~CCFollow()
|
|
|
|
{
|
|
|
|
m_pobFollowedNode->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
CCFollow *CCFollow::actionWithTarget(CCNode *pFollowedNode)
|
|
|
|
{
|
|
|
|
CCFollow *pRet = new CCFollow();
|
2010-08-19 14:09:40 +08:00
|
|
|
if (pRet && pRet->initWithTarget(pFollowedNode))
|
2010-08-05 14:32:04 +08:00
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
2010-08-19 14:09:40 +08:00
|
|
|
CCX_SAFE_DELETE(pRet)
|
2010-08-05 14:32:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
CCFollow *CCFollow::actionWithTarget(CCNode *pFollowedNode, CGRect rect)
|
|
|
|
{
|
|
|
|
CCFollow *pRet = new CCFollow();
|
2010-08-19 14:09:40 +08:00
|
|
|
if (pRet && pRet->initWithTarget(pFollowedNode, rect))
|
2010-08-05 14:32:04 +08:00
|
|
|
{
|
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
|
|
|
}
|
2010-08-19 14:09:40 +08:00
|
|
|
CCX_SAFE_DELETE(pRet)
|
2010-08-05 14:32:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCFollow *CCFollow::initWithTarget(CCNode *pFollowedNode)
|
|
|
|
{
|
|
|
|
pFollowedNode->retain();
|
|
|
|
m_pobFollowedNode = pFollowedNode;
|
|
|
|
m_bBoundarySet = false;
|
|
|
|
m_bBoundaryFullyCovered = false;
|
|
|
|
|
|
|
|
CGSize winSize = CCDirector::getSharedDirector()->getWinSize();
|
|
|
|
m_obFullScreenSize = CGPointMake(winSize.width, winSize.height);
|
|
|
|
m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCFollow *CCFollow::initWithTarget(CCNode *pFollowedNode, CGRect rect)
|
|
|
|
{
|
|
|
|
pFollowedNode->retain();
|
|
|
|
m_pobFollowedNode = pFollowedNode;
|
|
|
|
m_bBoundarySet = true;
|
|
|
|
m_bBoundaryFullyCovered = false;
|
|
|
|
|
|
|
|
CGSize winSize = CCDirector::getSharedDirector()->getWinSize();
|
|
|
|
m_obFullScreenSize = CGPointMake(winSize.width, winSize.height);
|
|
|
|
m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
|
|
|
|
|
|
|
|
m_fLeftBoundary = -((rect.origin.x+rect.size.width) - m_obFullScreenSize.x);
|
|
|
|
m_fRightBoundary = -rect.origin.x ;
|
|
|
|
m_fTopBoundary = -rect.origin.y;
|
|
|
|
m_fBottomBoundary = -((rect.origin.y+rect.size.height) - m_obFullScreenSize.y);
|
|
|
|
|
|
|
|
if(m_fRightBoundary < m_fLeftBoundary)
|
|
|
|
{
|
|
|
|
// screen width is larger than world's boundary width
|
|
|
|
//set both in the middle of the world
|
|
|
|
m_fRightBoundary = m_fLeftBoundary = (m_fLeftBoundary + m_fRightBoundary) / 2;
|
|
|
|
}
|
|
|
|
if(m_fTopBoundary < m_fBottomBoundary)
|
|
|
|
{
|
|
|
|
// screen width is larger than world's boundary width
|
|
|
|
//set both in the middle of the world
|
|
|
|
m_fTopBoundary = m_fBottomBoundary = (m_fTopBoundary + m_fBottomBoundary) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (m_fTopBoundary == m_fBottomBoundary) && (m_fLeftBoundary == m_fRightBoundary) )
|
|
|
|
{
|
|
|
|
m_bBoundaryFullyCovered = true;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
NSObject *CCFollow::copyWithZone(NSZone *pZone)
|
|
|
|
{
|
|
|
|
NSZone *pNewZone = NULL;
|
|
|
|
CCFollow *pRet = NULL;
|
|
|
|
if(pZone && pZone->m_pCopyObject) //in case of being called at sub class
|
|
|
|
{
|
|
|
|
pRet = dynamic_cast<CCFollow*>(pZone->m_pCopyObject);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pRet = new CCFollow();
|
|
|
|
pZone = pNewZone = new NSZone(pRet);
|
|
|
|
}
|
|
|
|
__super::copyWithZone(pZone);
|
|
|
|
// copy member data
|
|
|
|
pRet->m_nTag = m_nTag;
|
|
|
|
CCX_SAFE_DELETE(pNewZone);
|
|
|
|
return pRet;
|
|
|
|
}
|
|
|
|
void CCFollow::step(ccTime dt)
|
|
|
|
{
|
|
|
|
#define CLAMP(x,y,z) MIN(MAX(x,y),z)
|
|
|
|
|
|
|
|
if(m_bBoundarySet)
|
|
|
|
{
|
|
|
|
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
|
|
|
|
if(m_bBoundaryFullyCovered)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CGPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
|
|
|
|
|
|
|
|
dynamic_cast<CCNode*>(m_pTarget)->setPosition(ccp(CLAMP(tempPos.x, m_fLeftBoundary, m_fRightBoundary),
|
|
|
|
CLAMP(tempPos.y, m_fBottomBoundary, m_fTopBoundary)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dynamic_cast<CCNode*>(m_pTarget)->setPosition(ccpSub(m_obHalfScreenSize, m_pobFollowedNode->getPosition()));
|
|
|
|
}
|
|
|
|
#undef CLAMP
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CCFollow::isDone()
|
|
|
|
{
|
|
|
|
return ( !m_pobFollowedNode->getIsRunning() );
|
|
|
|
}
|
|
|
|
void CCFollow::stop()
|
|
|
|
{
|
|
|
|
m_pTarget = NULL;
|
|
|
|
__super::stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
}//namespace cocos2d
|
|
|
|
|
|
|
|
|