I have a little archer game I’m working on, and previously in my code I put every arrow sprite into a CCSprite[7]; array, and inside ccTime I would update the x/y coordinates and do some math to make the arrows move beautifully and smooth. So all the math/angles/movement works.
Later, while trying to implement collision detection, I couldn’t use a data type that would have made my life so much easier, I think it was CGRect, and it would get the contents of an sprite and check if that was intersecting another sprite. The error said that I had to use members of a NSMutable array or something like that, which is great because this is better for memory anyway, to put my sprites inside a batchNode and an NSMutable array. But there is a problem.
In every tutorial I’ve seen, projectiles move based on an action sequence with a predetermined time. Just an example of an action sequence (not in my code)
id action = [Sequence actions:
[ScaleTo actionWithDuration:.3 scale:0.7f],
[ScaleTo actionWithDuration:.3 scale:1.0f],
nil];
Everywhere I’ve seen, this is how sprites move around, but I cant do that because arrow velocities change depending on how long touches is held, angles that make the arrow look realistic and stuff like that.
So in my code in touchesBegan:
ccTouchesBegan:(NSSet *) blah blah {
...
...
self.nextProjectile = [[CCSprite spriteWithFile:@"arrow.png"];
_nextProjectile.rotation = vector2 - 90; //this is angle of where the user touched screen
//add projectiles to array
_nextProjectile.tag = arrowTracker;
[_batchNode addChild:_nextProjectile z:1];
[_projectiles addObject:_nextProjectile];
//Release? If I don't have this the arrow fails to move at all... and it was in the tutorial
if(_nextProjectile.tag == 1){
[_nextProjectile release];
_nextProjectile = nil;
}
}
Every time I touch, the first arrow doesn’t shoot out (this is NOT the problem, I can fix this easy) and the arrows shoot out perfectly, the movement is the exact same as when I was using a CCSprite array. The only problem is, every time I call ccTouchesBegan if the previous arrow was in mid-flight, it will stop all actions and just sit there. Mid air. So my problem is a logic error, obviously I’m doing something wrong in touchesBegan because it terminates the projection of the previous arrow!
So my questions are:
- How do I fix this.
- Should I just stick with CCsprite[7] (array of sprites)? Instead of finding the image’s contents, I could find the endpoint of the arrow and just check if that intersects another image, but this would take much more work/math/memory(I’m not too sure exactly on how memory works in general in programming… but I’m pretty sure CCSprite array takes more memory.
EDIT—————————————————————————————
This is where the arrow’s position is updated.
-(void)callEveryFrame:(ccTime)dt{
...
...
//move selected arrows
for(int xe = 0; xe < 7; xe++{
float x = _theArrowArray[xe].position.x;
float y = _theArrowArray[xe].position.y;
vyArray[xe] += gravity; vyArray is the velocity on the y axis array, I'm just adding gravity
x += vxArray[xe] *dt; // dt is after (ccTime) in the method definition
y += vyArray[xe] *dt;
CGPoint newLocation = CGPointMake(x,y);
_theArrowArray[xe].position = newlocation;
//The Code above this moves the arrows inside the CCSprite array, not the batch/nsmutable array.
//The code below is just a copy and paste with a little change to it, for the batchnode/nsmutable
float x2 = _nextProjectile.x; // mextProjectile was declared earlier in my code
float y2 = _nextProjectile.y;
vyArray[xe] += gravity; vyArray is the velocity on the y axis array, I'm just adding gravity
x2 += vxArray[xe] *dt*1.2; // This way(dt*1.2), both arrows are being shot out but this one has more gravity to it, so you can tell which arrow is which and see that both are working.
y2 += vyArray[xe] *dt*1.2;
CGPoint newLocation2 = CGPointMake(x2,y2);
_nextProjectile.position = newlocation2;
}
Don’t release the projectile unless the nextProjectile property retains it. CCSprite spriteWithFile returns an autoreleased object, which is retained by the batchNode and the projectiles array.
Weird thing is, the projectile is never set to have a tag == 1 so the code that releases the projectiles is probably going to be skipped.
My guess is regarding #1 that the projectile will be stopped but it isn’t removed because it’s still added to the node hierarchy. It would be helpful to see the code that actually removes the projectiles.
As for your second question I don’t understand your concern. You have 7 projectiles. Whether they use 7 Bytes, 700 Bytes or 7 Kilobytes simply doesn’t matter. This amount of memory is still negligible compared to even the smallest of textures.
Do yourself a favor and use the regular Foundation collections like NSMutableArray to store your objects. For one, they will retain added objects and release them when removed. You also get errors in case your code has a bug that causes the array to overrun. C style arrays may be a bit faster and may take less memory, but they’re also inherently unsafe and need to be handled with much greater care.