CC_SYNTHESIZE property fetching problem[solved] & vector operations

Hello friends,
I have made CC_SYNTHESIZE property in one class and trying to access it in another class and facing problem…
I have used 2 classes vrope.h to make property like this…
private:
int numPoints;

std::vector<VPoint*> vPoints;
// std::vector<VStick*> vSticks;

CC_SYNTHESIZE_READONLY(std::vector<VStick*>,vSticks,Sticks);

And in HelloWorld.h file i have ropes array like this…

std::vector<VRope *> *ropes;

Now in HelloWorld.m file i have used like this in ccTouchesMoved

std::vector<VRope *>::iterator rope;
for(rope = ropes~~>begin;rope != ropes~~>end();++rope)
{
std::vector<VStick *>::iterator stick;
for (stick = (*rope)->getSticks()->begin();stick != (*rope)>getSticks>end;++stick)
{
CCPoint pa = stick~~>getPointA;
CCPoint pb = stick~~>getPointB();
if (this->checkLineIntersection(pt0,pt1,pa,pb))
{
return;
}
}
}

I have tried also calling (rope)->getSticks()->begin() but that is also not working…
The upper for loop of ropes is working and i can access its methods but i am not getting how to work for the inner for loop to access sticks…

Has anybody know what should be the problem?

Ok i can access now by 2 modifications…
1.by making CC_SYNTHESIZE public instead of private…(Doesn’t matter as getter setter will be public)

2.By modifying 2 loops like this…

std::vector<VRope *>::iterator rope;

for(rope = ropes~~>begin;rope != ropes~~>end();**rope)
{
std::vector<VStick *>::iterator stick;
for ->getSticks.begin;stick != ->getSticks.end;**stick)
{
CCPoint pa = (*stick)->getPointA()->point();
CCPoint pb = (*stick)->getPointB()->point();
if (this->checkLineIntersection(pt0,pt1,pa,pb))
{
return;
}
}
}

  1. You don’t need to make CC_SYNTHESIZE public or private because it already contains access modifiers (setter and getter will be public anyway).
  2. For std::vector (and any other data except simple types) it is better to use CC_SYNTHESIZE_PASS_BY_REF, this prevents vector from being copied each time you access it.

Hello @redaur readur…Glad to see your reply again…I will remember this…

Do you know how to get index of an item in vector and removing elements in range from vector?

int nPoint = (int)(std::find(vSticks.begin(),vSticks.end(),stick)-vSticks.begin()); // Trying this for getting index

vSticks.erase(nPoint, numPoints-nPoint-1); //trying this to remove range…

But not working as not matching function with erase(int&,int)

1st part of Cut the Rope tutorial from RayWenderlich.com has been completed and found 2nd part bit confusing…
So as i finish 2nd part(with getting help from you as usual :slight_smile: ) will post the cocos2d-x port of tutorial in the forum…

You’re getting index right.

For erasing range you need to pass first and last iterators.

This is probably what are you wanting to do (sorry if misunderstood):

std::vector::iterator point = std::find(vSticks.begin(), vSticks.end(), stick);
vSticks.erase(point, point + 2);

Note that erase does remove elements in range including first but not including last pointed element.

You can always convert iterator to index by substracting the .begin() iterator from it:

size_t idx = it - v.begin();

and convert index to iterator (possibly for another collection) by adding it to the .begin() iterator:

std::vector::iterator it = v.begin() + idx;

Hello @redaur readur…I am eager to test your solution and i think it will work…
But before that i am facing one situation n before solving that i can not test this…
The problem is we had two for loops one to access rope methods and another to access sticks methods(as we have started this forum topic.)
In that both loops compile just fine but when i am running app and moving finger(as i have put loops in touchesMoved) app crashes…

std::vector<VRope *>::iterator rope;

for(rope = ropes~~>begin;rope != ropes~~>end();**rope) //Working
{
std::vector<VStick *>::iterator stick;
CCLOG (“Size %d”,(*rope)->getSticks.size); //Working…getting size of sticks…
for ->getSticks.begin;stick != ->getSticks.end;**stick)
{
VPoint* vp1 = (*stick)->getPointA(); //Not working(getPointA is public method of VStick class…)…Means for all methods calling it crashes…
CCPoint pa = (*stick)->getPointA()->point(); //Not working
CCLOG (“Point x %f”,pa.x); //Not reaching here…
CCPoint pb = (*stick)->getPointB()->point();
if (this->checkLineIntersection(pt0,pt1,pa,pb))
{
// Cut the rope here
return;
}
}
}

DO you have any idea about it…In the mean time i find some solution for it… :slight_smile:

If you can’t call objects methods using iterator that means the objects are probably invalid. Maybe they are already destroyed to the moment of execution of this code. How are they being created? Do they inherit from CCObject? Note that if they inherit CCObject, they aren’t automatically retained when put into vector because std::vector isn’t designed to do it.

I have 3 classes vrope,vstick and vpoint and they do not inherit CCObject…

In vrope.h

private:

CC_SYNTHESIZE_READONLY(std::vector<VStick*>,vSticks,Sticks);
std::vector<VPoint*> vPoints;
// std::vector<VStick*>
std::vectorcocos2d::CCSprite* ropeSprites;

In vrope.m

for(int i=0;i<numPoints-1;i++) {
VStick* tmpStick = new VStick(vPoints[i], vPoints[i+1]);
vSticks.push_back(tmpStick);
}
and done the same for vPoints and ropeSprites…

and trying to access stick class methods from touch methods of HelloWorldLayer.m(as in 2 for loop)

  1. do not know how numPoints is calculated but if it is the number of elements in vPoints then you are accessing out of array bounds in your ‘for’.

  2. if you look into CC_SYNTHESIZE_READONLY macro definition you can note that every time you invoke getSticks() you get the copy of array and if you’re modifying received array then you’re modifying its copy instead (no impact on original vector). Moreover, note you get a new copy every time you invoke getSticks(), this means that this code:

    for (stick = (*rope)->getSticks().begin();stick != (*rope)->getSticks().end();++stick)

will result in getting begin and end iterators pointing to different arrays!

Since cocos2dx doesn’t provide an appropriate macro you can define getter as this:

public:
   std::vector& getSticks() { return vSticks; }
private:
   std::vector vSticks;

This way you get a reference to the same array each time you invoke getSticks(). Whenever you modify the array using this method you can be sure you modify original array.

Perfect…You are great @redaur readur…The problem was exactly what you said…
Now trying to finish whole tutorial as soon as possible…
Thank you

Hello @redaur readur…I have posted code for that tutorial on the latest forum…I have that cutting rope method- cutRopeInStick(VStick* stick,b2Body* newBodyA,b2Body* newBodyB) from vrope.m…
Ropes are cutting properly but only have one issue.
it crashes sometime(by cutting at top or bottom of edge…)
And also if some idea to remove rope after cutting…

I’ve made a quick look into your code. You’re still accessing out of bounds. vPoints indices are valid from 0 to numPoints - 1, not to numPoints. vSticks indices are valid from 0 to numPoints - 2 (if there’re always 1 less sticks than points).

And BTW

std::vector::iterator point;
for(point = vPoints.begin()+idx;point != vPoints.begin()+numPoints-idx;++point)
{
newRopePoints.push_back(*point);
}

vPoints.erase(vPoints.begin()+idx, vPoints.begin()+numPoints-idx);

You don’t need iteration here, there’s vector method “insert”, you can use it just like you used erase:

newRopePoints.insert(newRopePoints.begin(), vPoints.begin() + idx, vPoints.begin + idx + 1);

or you can use std::copy algorithm like this:

std::copy(vPoints.begin() + idx, vPoints.begin + idx + 1, newRopePoints.begin());

I am not getting exactly where there is out of bounds…I am already taking vsticks less than one than vpoins…
And vector insert methods like u have mentioned were giving me not matching parameters and still giving. So i have taken iterations… :frowning:

First, if some collection contains X items, then valid indices are from 0 to X-1, totally X items. X isn’t valid index. So valid iterators for vPoints (of size numPoints) are from begin() to begin() + numPoints - 1.

Second, what is the meaning of this line?

for(point = vPoints.begin()+idx;point != vPoints.begin()+numPoints-idx;++point)

I see that if idx gets greater than numPoints/2 your ending iterator will precede your beginning iterator which makes your iteration run eternally.

For First point i change numPoints to numPoints-1 and check…
For Second point my basic purpose was to take range like this as in Objective c where vSticks was NSMutableArray:

// 1-First, find out where in your array the rope will be cut
int nPoint = [vSticks indexOfObject:stick];

C*+ code :
// 1-First, find out where in your array the rope will be cut
std::vector<VStick >::iterator nPointStick = std::find, vSticks.end, stick);
size_t idx = nPointStick - vSticks.begin;
// Instead of making everything again you’ll just use the arrays of
// sticks, points and sprites you already have and split them
// 2-This is the range that defines the new rope
NSRange newRopeRange = ;
// 3-Keep the sticks in a new array
NSArray *newRopeSticks = ;
C
+ code:
//2 and 3
std::vector<VStick*> newRopeSticks;

std::vector<VStick *>::iterator astick;
for(astick = vSticks.begin()idx;astick != vSticks.beginnumPoints-idx-1;**astick)
{
newRopeSticks.push_back(*astick);
}

Okay I still understand nothing about newRopeSticks but anyway the beginning iterator must precede the ending iterator whenever you iterate with ++.

Okay done…As you said the problem was looping.
Basically i wanted to take idx as my initial location and from that range of (numPoints-idx-1). (like from location 3 to 4 steps-means upto 7 not upto 4)
So i misunderstood between range and last limit…
Anyway issue is solved and updated to github…
Thank you @redaur readur