Hey, i’ve tried to use CCParallacScrollNode: https://github.com/jasonmarziani/CCParallaxScrollNode . Everything seems to be fine except, i think there are no deallocation, when e.g. i change the scene. Could you tell me, how to do this for this class, cause all my solutions come to errors. I have also seen a lot of Memory leaks through Xcode. So maybe, someone have experience with these classes and could share the edited code? Thank you.
i have port this code to cocos2d-x. if you need that i can share.
CCParallaxScrollNode.h
#ifndef _CCPARALLAX_SCROLL_NODE_H_
#define _CCPARALLAX_SCROLL_NODE_H_
#include "cocos2d.h"
//#include "CCParallaxScrollOffset.h"
namespace cocos2d {
class CC_DLL CCParallaxScrollNode : public CCNode
{
private:
ccArray *scrollOffsets;
CCSpriteBatchNode *batch;
bool init();
public:
~CCParallaxScrollNode();
//static CCParallaxScrollNode * node();
static CCParallaxScrollNode * makeWithBatchFile(const char *batchFileName);
void addChild(CCSprite *node, int z, const CCPoint &r, const CCPoint &p, const CCPoint &s);
void addChild(CCSprite *node, int z, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v);
void addChild(CCNode *node, int z);
void removeChild(CCSprite *node, bool cleanup);
void removeAllChildrenWithCleanup(bool cleanup);
void updateWithVelocity(const CCPoint &vel, ccTime dt);
void updateWithYPosition(float y, ccTime dt);
void addInfiniteScrollWithZ(int z, const CCPoint ∶, const CCPoint &pos, const CCPoint &dir, CCSprite *firstObject, ...);
void addInfiniteScrollXWithZ(int z, const CCPoint ∶, const CCPoint &pos, CCSprite *firstObject, ...);
void addInfiniteScrollYWithZ(int z, const CCPoint ∶, const CCPoint &pos, CCSprite *firstObject, ...);
void addInfiniteScrollWithObjects(CCArray *objects, int z, const CCPoint ∶, const CCPoint &pos, const CCPoint &dir);
void setScrollOffsets(ccArray *pScrollOffsets);
void setBatch(CCSpriteBatchNode *pBatch);
ccArray * getScrollOffsets();
CCSpriteBatchNode * getBatch();
//CC_SYNTHESIZE(ccArray *, scrollOffsets, ScrollOffsets);
//CC_SYNTHESIZE(CCSpriteBatchNode *, batch, Batch)
LAYER_NODE_FUNC(CCParallaxScrollNode);//какая-то хрень
};
} // namespace cocos2d
#endif //__CCPARALLAX_SCROLL_NODE_H__
CCParallaxScrollNode.cpp
#include "CCParallaxScrollNode.h"
#include "CCParallaxScrollOffset.h"
#include
#ifndef PTM_RATIO
#define PTM_RATIO 1//32
#endif
#ifndef SIGN
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
#endif
#include "support/data_support/ccCArray.h"
namespace cocos2d {
CCParallaxScrollNode::~CCParallaxScrollNode()
{
if (scrollOffsets) {
ccArrayFree(scrollOffsets);
scrollOffsets = 0;
}
}
bool CCParallaxScrollNode::init()
{
bool ret = true;
if (ret)
{
scrollOffsets = ccArrayNew(5);
}
return ret;
}
// CCParallaxScrollNode * CCParallaxScrollNode::node()
// {
// CCParallaxScrollNode *pRet = new CCParallaxScrollNode();
// pRet->autorelease();
// return pRet;
// }
CCParallaxScrollNode * CCParallaxScrollNode::makeWithBatchFile(const char *batchFileName)
{
CCParallaxScrollNode *parallax = CCParallaxScrollNode::node();
char *pngName = (char*)malloc(sizeof(char)*(strlen(batchFileName)+5));
strcpy(pngName, batchFileName);
*(pngName+strlen(batchFileName)) = 0;
parallax->setBatch(CCSpriteBatchNode::batchNodeWithFile(strcat(pngName, ".png")));
free(pngName);
((CCNode*)parallax)->addChild(parallax->batch);
pngName = (char*)malloc(sizeof(char)*(strlen(batchFileName)+7));
strcpy(pngName, batchFileName);
*(pngName+strlen(batchFileName)) = 0;
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(strcat(pngName, ".plist"));
free(pngName);
return parallax;
}
void CCParallaxScrollNode::updateWithVelocity(const CCPoint &vel, ccTime dt) {
CCSize screen = CCDirector::sharedDirector()->getWinSize();
CCPoint vel2 = ccpMult(vel, PTM_RATIO);
for (int i=scrollOffsets->num - 1; i >= 0; i--) {
CCParallaxScrollOffset *scrollOffset = (CCParallaxScrollOffset*)scrollOffsets->arr[i];
CCNode *child = scrollOffset->getChild();
CCPoint relVel = ccpMult(scrollOffset->getRelVelocity(), PTM_RATIO);
CCPoint totalVel = ccpAdd(vel2, relVel);
CCPoint offset = ccpCompMult(ccpMult(totalVel, dt), scrollOffset->getRatio());
child->setPosition(ccpAdd(child->getPosition(), offset));
if ( (vel2.x < 0 && child->getPosition().x + child->getContentSize().width < 0) ||
(vel2.x > 0 && child->getPosition().x > screen.width) ) {
child->setPosition(ccpAdd(child->getPosition(), ccp(-SIGN(vel2.x) * fabs(scrollOffset->getScrollOffset().x), 0)));
}
// Positive y indicates upward movement in cocos2d
if ( (vel2.y < 0 && child->getPosition().y + child->getContentSize().height < 0) ||
(vel2.y > 0 && child->getPosition().y > screen.height) ) {
child->setPosition(ccpAdd(child->getPosition(), ccp(0, -SIGN(vel2.y) * fabs(scrollOffset->getScrollOffset().y))));
}
}
}
void CCParallaxScrollNode::updateWithYPosition(float y, ccTime dt)
{
for (int i=scrollOffsets->num - 1; i >= 0; i--) {
CCParallaxScrollOffset *scrollOffset = (CCParallaxScrollOffset*)scrollOffsets->arr[i];
CCNode *child = scrollOffset->getChild();
float offset = y * scrollOffset->getRatio().y;//ccpCompMult(pos, scrollOffset.ratio);
child->setPosition(ccp(child->getPosition().x, scrollOffset->getOrigPosition().y + offset));
}
}
void CCParallaxScrollNode::addChild(CCSprite *node, int z, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v)
{
node->setAnchorPoint(ccp(0,0));
CCParallaxScrollOffset *obj = CCParallaxScrollOffset::scrollWithNode(node, r, p, s, v);
ccArrayAppendObjectWithResize(scrollOffsets, obj);
if (batch) {
batch->addChild(node, z);
} else {
((CCNode*)this)->addChild(node, z);
}
}
void CCParallaxScrollNode::addChild(CCSprite *node, int z, const CCPoint &r, const CCPoint &p, const CCPoint &s)
{
addChild(node, z, r, p, s, ccp(0,0));
}
void CCParallaxScrollNode::removeChild(CCSprite *node, bool cleanup)
{
for (int i=0; i < scrollOffsets->num; i++) {
CCParallaxScrollOffset *scrollOffset = (CCParallaxScrollOffset*)scrollOffsets->arr[i];
if(scrollOffset->getChild()->isEqual(node)) {
ccArrayRemoveObjectAtIndex(scrollOffsets, i);
break;
}
}
if (batch) {
batch->removeChild(node, cleanup);
}
}
void CCParallaxScrollNode::addChild(CCNode *node, int z)
{
CCNode::addChild(node, z);
}
void CCParallaxScrollNode::removeAllChildrenWithCleanup(bool cleanup)
{
ccArrayRemoveAllObjects(scrollOffsets);
if (batch) {
batch->removeAllChildrenWithCleanup(cleanup);
}
}
void CCParallaxScrollNode::addInfiniteScrollWithObjects(CCArray *objects, int z, const CCPoint ∶, const CCPoint &pos, const CCPoint &dir)
{
// NOTE: corrects for 1 pixel at end of each sprite to avoid thin lines appearing
// Calculate total width and height
float totalWidth = 0;
float totalHeight = 0;
for (int i = 0; i < objects->count(); i++) {
CCSprite *object = (CCSprite *)(objects->objectAtIndex(i));
totalWidth += object->getContentSize().width - 2;//1;
totalHeight += object->getContentSize().height - 2;//1;
}
// Position objects, add to parallax
CCPoint currPos = pos;
for (int i = 0; i < objects->count(); i++) {
CCSprite *object = (CCSprite *)(objects->objectAtIndex(i));
addChild(object, z, ratio, currPos, ccp(totalWidth, totalHeight));
CCPoint nextPosOffset = ccp(dir.x * (object->getContentSize().width - 2/*1*/), dir.y * (object->getContentSize().height - 2/*1*/));
currPos = ccpAdd(currPos, nextPosOffset);
}
}
void CCParallaxScrollNode::addInfiniteScrollWithZ(int z, const CCPoint ∶, const CCPoint &pos, const CCPoint &dir, CCSprite *firstObject, ...)
{
va_list args;
va_start(args, firstObject);
CCArray* argArray = CCArray::arrayWithCapacity(2);
for (CCSprite *arg = firstObject; arg != 0; arg = va_arg(args, CCSprite*)) {
argArray->addObject(arg);
}
va_end(args);
addInfiniteScrollWithObjects(argArray, z, ratio, pos, dir);
}
void CCParallaxScrollNode::addInfiniteScrollXWithZ(int z, const CCPoint ∶, const CCPoint &pos, CCSprite *firstObject, ...)
{
va_list args;
va_start(args, firstObject);
CCArray* argArray = CCArray::arrayWithCapacity(2);
for (CCSprite *arg = firstObject; arg != 0; arg = va_arg(args, CCSprite*)) {
argArray->addObject(arg);
}
va_end(args);
addInfiniteScrollWithObjects(argArray, z, ratio, pos, ccp(1, 0));
}
void CCParallaxScrollNode::addInfiniteScrollYWithZ(int z, const CCPoint ∶, const CCPoint &pos, CCSprite *firstObject, ...)
{
va_list args;
va_start(args, firstObject);
CCArray* argArray = CCArray::arrayWithCapacity(2);
for (CCSprite *arg = firstObject; arg != 0; arg = va_arg(args, CCSprite*)) {
argArray->addObject(arg);
}
va_end(args);
addInfiniteScrollWithObjects(argArray, z, ratio, pos, ccp(0, 1));
}
void CCParallaxScrollNode::setScrollOffsets(ccArray *pScrollOffsets)
{
scrollOffsets = pScrollOffsets;
}
void CCParallaxScrollNode::setBatch(CCSpriteBatchNode *pBatch)
{
batch = pBatch;
}
ccArray * CCParallaxScrollNode::getScrollOffsets()
{
return scrollOffsets;
}
CCSpriteBatchNode * CCParallaxScrollNode::getBatch()
{
return batch;
}
}// namespace cocos2d
CCParallaxScrollOffset.h
#ifndef _CCPARALLAX_SCROLL_OFFSET_H_
#define _CCPARALLAX_SCROLL_OFFSET_H_
#include "cocos2d.h"
namespace cocos2d {
class CC_DLL CCParallaxScrollOffset : public CCObject
{
private:
CCPoint scrollOffset, origPosition, relVelocity, ratio, position, currPosition;
CCNode *child;
public:
~CCParallaxScrollOffset();
static CCParallaxScrollOffset * scrollWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s);
static CCParallaxScrollOffset * scrollWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v);
bool initWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s);
bool initWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v);
// CC_PROPERTY_PASS_BY_REF(CCPoint, scrollOffset, ScrollOffset);
// CC_PROPERTY_PASS_BY_REF(CCPoint, origPosition, OrigPosition);
// CC_PROPERTY_PASS_BY_REF(CCPoint, relVelocity, RelVelocity);
// CC_PROPERTY_PASS_BY_REF(CCPoint, ratio, Ratio);
// CC_PROPERTY_PASS_BY_REF(CCPoint, position, Position);
// CC_PROPERTY_PASS_BY_REF(CCPoint, currPosition, CurrPosition);
//
// CC_PROPERTY(CCNode *, child, Child);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, scrollOffset, ScrollOffset);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, origPosition, OrigPosition);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, relVelocity, RelVelocity);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, ratio, Ratio);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, position, Position);
// CC_SYNTHESIZE_PASS_BY_REF(CCPoint, currPosition, CurrPosition);
//
// CC_SYNTHESIZE_PASS_BY_REF(CCNode *, child, Child);
void setScrollOffset(const CCPoint &val);
void setOrigPosition(const CCPoint &val);
void setRelVelocity(const CCPoint &val);
void setRatio(const CCPoint &val);
void setPosition(const CCPoint &val);
void setCurrPosition(const CCPoint &val);
void setChild(CCNode *val);
const CCPoint & getScrollOffset() const;
const CCPoint & getOrigPosition() const;
const CCPoint & getRelVelocity() const;
const CCPoint & getRatio() const;
const CCPoint & getPosition() const;
const CCPoint & getCurrPosition() const;
CCNode * getChild() const;
};
} // namespace cocos2d
#endif //__CCPARALLAX_SCROLL_NODE_H__
CCParallaxScrollOffset.cpp
#include "CCParallaxScrollOffset.h"
namespace cocos2d {
CCParallaxScrollOffset::~CCParallaxScrollOffset()
{
}
CCParallaxScrollOffset * CCParallaxScrollOffset::scrollWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s)
{
CCParallaxScrollOffset *pobSprite = new CCParallaxScrollOffset();
if (pobSprite && pobSprite->initWithNode(node, r, p, s))
{
pobSprite->autorelease();
return pobSprite;
}
CC_SAFE_DELETE(pobSprite);
return NULL;
}
CCParallaxScrollOffset * CCParallaxScrollOffset::scrollWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v)
{
CCParallaxScrollOffset *pobSprite = new CCParallaxScrollOffset();
if (pobSprite && pobSprite->initWithNode(node, r, p, s, v))
{
pobSprite->autorelease();
return pobSprite;
}
CC_SAFE_DELETE(pobSprite);
return NULL;
}
bool CCParallaxScrollOffset::initWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s)
{
return initWithNode(node, r, p, s, ccp(0,0));
}
bool CCParallaxScrollOffset::initWithNode(CCNode *node, const CCPoint &r, const CCPoint &p, const CCPoint &s, const CCPoint &v)
{
bool ret = true;
if(ret) {
child = node;
ratio = r;
scrollOffset = s;
relVelocity = v;
child->setPosition(p);
origPosition = p;
//currPosition = p;
child->setAnchorPoint(ccp(0, 0));
}
return ret;
}
void CCParallaxScrollOffset::setScrollOffset(const CCPoint &val)
{
scrollOffset = val;
}
void CCParallaxScrollOffset::setOrigPosition(const CCPoint &val)
{
origPosition = val;
}
void CCParallaxScrollOffset::setRelVelocity(const CCPoint &val)
{
relVelocity = val;
}
void CCParallaxScrollOffset::setRatio(const CCPoint &val)
{
ratio = val;
}
void CCParallaxScrollOffset::setPosition(const CCPoint &val)
{
position = val;
}
void CCParallaxScrollOffset::setCurrPosition(const CCPoint &val)
{
currPosition = val;
}
void CCParallaxScrollOffset::setChild(CCNode *val)
{
child = val;
}
const CCPoint & CCParallaxScrollOffset::getScrollOffset() const
{
return scrollOffset;
}
const CCPoint & CCParallaxScrollOffset::getOrigPosition() const
{
return origPosition;
}
const CCPoint & CCParallaxScrollOffset::getRelVelocity() const
{
return relVelocity;
}
const CCPoint & CCParallaxScrollOffset::getRatio() const
{
return ratio;
}
const CCPoint & CCParallaxScrollOffset::getPosition() const
{
return position;
}
const CCPoint & CCParallaxScrollOffset::getCurrPosition() const
{
return currPosition;
}
CCNode * CCParallaxScrollOffset::getChild() const
{
return child;
}
}// namespace cocos2d
Hi, I have seen your port and it looks wonderful, but, I have a question, I have checked that there is two methods to move the Parallax but I did not found one move the parallax using fingers. Also, do these classes support zoom in and zoom out?
Thanks!
Hi, i only ported that code to the C*+ and actually don’t know what void CCParallaxScrollNode::updateWithYPosition(float y, ccTime dt)
method is doing there.
“Also, do these classes support zoom in and zoom out?” - no, these classes don’t support zooming.
“but I did not found one move the parallax using fingers” - i have added two methods to the @ CCParallaxScrollNode@ class maybe you find it useful when move the parallax using fingers.
<pre>
void CCParallaxScrollNode::updateWithOffset
{
CCSize screen = CCDirector::sharedDirector~~>getWinSize;
CCPoint offsetPTM = ccpMult;
for {
CCParallaxScrollOffset scrollOffset = scrollOffsets~~>arr[i];
CCNode *child = scrollOffset~~>getChild;
CCPoint offset = ccpMult), 1);>getPosition;
CCPoint newPos = ccpAdd, offset);
CCPoint oldPos = child
if && .width < 0)) {
newPos.x = fabs.x);
} else if && ) {
newPos.x = fabs.x);>getContentSize.height < 0)) {
}
// Positive y indicates upward movement in cocos2d
if && .y + child
newPos.y= fabs.y);
} else if .y > screen.height)) {
newPos.y = fabs.y);>setPosition;
}
child
}
}
void CCParallaxScrollNode::updateWithPosition
{
CCSize screen = CCDirector::sharedDirector~~>getWinSize;
float fractpartX, fractpartY, intpart, xScrollOffset, yScrollOffset;
for {
CCParallaxScrollOffset *scrollOffset = scrollOffsets~~>arr[i];
CCNodechild = scrollOffset~~>getChild;
CCPoint offset = ccpMult), 1);>getPosition;
CCPoint newPos = ccpAdd, offset);
CCPoint oldPos = child
xScrollOffset = scrollOffset~~>getScrollOffset.x;
yScrollOffset = scrollOffset~~>getScrollOffset.y;
fractpartX = modff;
newPos.x = fractpartX*xScrollOffset;
fractpartY = modff;
newPos.y = fractpartY*yScrollOffset;
if && .width < 0)) {
newPos.x*= fabs(xScrollOffset);
} else if ((newPos.x > oldPos.x) && (newPos.x > screen.width)) {
newPos.x = fabs;= fabs(yScrollOffset);
}
// Positive y indicates upward movement in cocos2d
if && .height < 0)) {
newPos.y += fabs;
} else if && ) {
newPos.y
}
child->setPosition(newPos.x, newPos.y);
}
}