array removeObjectsAtIndexes: - iphone

I have a problem, with deleting items from an array..
first:
i have a variable of type int, called zan. in my HelloWordScene.h
int zan;
NSMutableArray * targets;
NSMutableArray *projectiles;
in my HelloWordScene.m. i have an object, animated:
-(id) init {
if((self = [super init])) {
[self schedule:#selector(update:)];
_targets = [[NSMutableArray alloc] init];
_projectiles = [[NSMutableArray alloc] init];
}
[self schedule:#selector(gameLogic:) interval:3];
return self;
}
in my selector I increment the var:
-(void)gameLogic:(ccTime)dt {
[self addTarget];
zan ++;
}
Later I have an animation and I have a addTarget:
// This loads an image of the same name (but ending in png), and goes through the
// plist to add definitions of each frame to the cache.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"zancudo.plist"];
// Create a sprite sheet with the images
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"zancudo.png"];
[self addChild:spriteSheet];
// Load up the frames of our animation
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 0; i <= 4; ++i) {
[walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"zancu000%d.png", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
// Create a sprite for our bear
CGSize winSize = [CCDirector sharedDirector].winSize;
self.bear = [CCSprite spriteWithSpriteFrameName:#"zancu0001.png"];
//random position
int minY = _bear.contentSize.width/2;
int maxY = winSize.width - _bear.contentSize.width/2;
int rangeY = maxY - minY;
int actualX = (arc4random() % rangeY) + minY;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
_bear.position = ccp(actualX,winSize.height + (_bear.contentSize.height/2));
self.walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
//animation
[spriteSheet addChild:_bear];
//∫aqui pasar un for para poder saber que position es
CCLOG(#"cantidad de zancudos%d",zan);
[_targets insertObject:_bear atIndex:zan];
i have deleted a mutable _target for index- i have a selector update. try delete a mutablearray this.
for (CCSprite *target in targetsToDelete) {
if (_targets.count!=0) {
for (int j=1; j==_targets.count; j++) {
[_targets removeObjectAtIndex:j];
}
}
I need help

use syntax like this for crash free delete;
NSArray *array = [NSArray arrayWithArray: _targets];
for(CCSprite *sprite in array)
{
if(sprite.tag == kToDelete) //mark somewhere in game :or use ur logic here
{
[_targets removeObject: sprite];
[sprite stopAllActions];
[sprite removeFromParentAndCleanup:YES];
}
}

Your loop will try and access an index out of the array's bounds...try this
for (int j = 0; j == _targets.count - 1; j++)
{
[_targets removeObjectAtIndex:j];
}
However, since it appears you are only removing the last element of the array with this code, you could skip the for loop and use:
[_targets removeLastObject];

The moment you remove an object from _targets, the effective count actually changes. So if you start the loop with a count of 10, and eventually the value of j will be out of bounds. I dont follow quite well the logic of your if ( the == ), but if you are trying to remove all objects, instead of the loop :
[_targets removeAllObjects];

Related

Infinite scrolling on a sprite(Parallax)

I am a newbie to the world of cocos2d i am developing my first tutorial and facing one problem
my problem is i have an image (1024 X 320) and my orientation is landscape i need to move that image continuously from right to left for this purpose i have used space shooter tutorial by Ray(Thanks to him) but the image doesn't seem to be appearing again and again.
my code is..
-(id) init
{
if( (self=[super init])) {
CGSize screenSize = [CCDirector sharedDirector].winSize;
// 1) Create the CCParallaxNode
backgroundNode = [CCParallaxNode node];
[self addChild:backgroundNode z:-1];
// 2) Create the sprites we'll add to the CCParallaxNode
Back = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
//Back.position=ccp(screenSize.width/2, screenSize.height/2);
Back.rotation = -90;
Back1 = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
Back1.rotation = -90;
// 3) Determine relative movement speeds for space dust and background
CGPoint dustSpeed = ccp(0.1, 0.1);
// 4) Add children to CCParallaxNode
[backgroundNode addChild:Back z:0 parallaxRatio:dustSpeed positionOffset:ccp(screenSize.width/2, screenSize.height/2)];
NSLog(#"back.content width is...%f",Back.contentSize.width);
[backgroundNode addChild:Back1 z:1 parallaxRatio:dustSpeed positionOffset:ccp(screenSize.width/2, screenSize.height*2)];
// 5) Enable updates
[self scheduleUpdate];
}
return self;
}
- (void)update:(ccTime)dt {
// 1) Update background position
CGPoint backgroundScrollVel = ccp(0,-1000);
backgroundNode.position = ccpAdd(backgroundNode.position, ccpMult(backgroundScrollVel, dt));
// 2) Check for background elements moving offscreen
NSArray *spaceDusts = [NSArray arrayWithObjects:Back, Back1, nil];
for (CCSprite *spaceDust in spaceDusts) {
if ([backgroundNode convertToWorldSpace:spaceDust.position].x < -spaceDust.contentSize.width) {
[backgroundNode incrementOffset:ccp(2*spaceDust.contentSize.width,0) forChild:spaceDust];
}
}
}
please help me out of this
Thanks in advance.
try this one
if (backgroundNode.position.y <-screenSize.height*2)
backgroundNode.position = ccp(0,0);
As init method is called only once the approach you are doing will be done only one time you need to again set the Position of the backgroundNode to 0 in your update method.
here the multiple may vary
Try this code it is creating a paralax moving from bottom to top change CGPointMake(0, 1.0) to this CGPointMake(1.0,0) in paraNode addChild line.
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) )
{
float yPos =0.0;
NSMutableString *fileNameString = [[NSMutableString alloc]initWithCapacity:0];
if (IS_IPHONE_5)
{
[fileNameString appendString:#"Background-568h.png"];
yPos= 560.0;
}
else
{
[fileNameString appendString:#"Background.png"];
yPos= 470.0;
}
background1 = [CCSprite spriteWithFile:fileNameString];
background1.tag = 1;
background1.anchorPoint = CGPointMake(0,0);
background2 = [CCSprite spriteWithFile:fileNameString];
background2.tag = 2;
background2.anchorPoint = CGPointMake(0,0);
background3 = [CCSprite spriteWithFile:fileNameString];
background3.tag = 3;
background3.anchorPoint = CGPointMake(0,0);
background4 = [CCSprite spriteWithFile:fileNameString];
background4.tag = 4;
background4.anchorPoint = CGPointMake(0,0);
paraNode = [CCParallaxNode node];
[paraNode addChild:background1 z:1 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, 0)];
[paraNode addChild:background2 z:2 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos)];
[paraNode addChild:background3 z:3 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos*2)];
[paraNode addChild:background4 z:4 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos*3)];
[self addChild:paraNode z:-1 tag:123];
[self updateFrameRate:0.7 andYposition:yPos];
[fileNameString release];
fileNameString = nil;
}
return self;
}
-(void)updateFrameRate:(float)speedValue andYposition:(float)yposToSet
{
move1 = [CCMoveBy actionWithDuration:speedValue position:CGPointMake(0, yposToSet)];
move2 = [CCMoveBy actionWithDuration:0.0 position:CGPointMake(0, -yposToSet)];
move3 = [CCMoveBy actionWithDuration:0.0 position:CGPointMake(0, 0)];
CCSequence* sequence = [CCSequence actions:move1,move2,move3, nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
[paraNode runAction:repeat];
}

Why is my grid not drawing?

I'm trying to setup a grid for path finding in a box2d environment. Is it my drawing method which is why none of the nodes and links between them are being drawn? here is my main class for drawing the world:
#interface HelloWorldLayer()
#end
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
if( (self=[super init]))
{
[self createGrid];
[self drawGrid];
}
return self;
}
-(void) dealloc
{
[super dealloc];
}
-(void) createGrid
{
//Create 2D array (grid)
nodeSpace = 50.0f;
gridSizeX = 500;
gridSizeY = 500;
grid = [[NSMutableArray alloc] initWithCapacity:(gridSizeX)];
for(int x=0; x<gridSizeX; x++){
[grid addObject:[[NSMutableArray alloc] initWithCapacity:(gridSizeY)]];
}
//Create AStar nodes
for(int x=0; x<gridSizeX; x++){
for(int y=0; y<gridSizeY; y++){
//Add a node
AStarNode *node = [[AStarNode alloc] init];
node.position = ccp(x*nodeSpace + nodeSpace/2, y*nodeSpace + nodeSpace/2);
[[grid objectAtIndex:x] addObject:node];
}
}
//Add neighbors
for(int x=0; x<gridSizeX; x++){
for(int y=0; y<gridSizeY; y++){
//Add a node
AStarNode *node = [[grid objectAtIndex:x] objectAtIndex:y];
//Add self as neighbor to neighboring nodes
[self addNeighbor:node toGridNodeX:x-1 Y:y-1]; //Top-Left
[self addNeighbor:node toGridNodeX:x-1 Y:y]; //Left
[self addNeighbor:node toGridNodeX:x-1 Y:y+1]; //Bottom-Left
[self addNeighbor:node toGridNodeX:x Y:y-1]; //Top
[self addNeighbor:node toGridNodeX:x Y:y+1]; //Bottom
[self addNeighbor:node toGridNodeX:x+1 Y:y-1]; //Top-Right
[self addNeighbor:node toGridNodeX:x+1 Y:y]; //Right
[self addNeighbor:node toGridNodeX:x+1 Y:y+1]; //Bottom-Right
}
}
}
/* Add neighbor helper method */
-(void) addNeighbor:(AStarNode*)node toGridNodeX:(int)x Y:(int)y {
if(x >= 0 && y >= 0 && x < gridSizeX && y < gridSizeY){
AStarNode *neighbor = [[grid objectAtIndex:x] objectAtIndex:y];
if(![AStarNode isNode:neighbor inList:node.neighbors]){
[node.neighbors addObject:neighbor];
}
}
}
-(void) drawGrid
{
for(int x=0; x<gridSizeX; x++){
for(int y=0; y<gridSizeY; y++){
//Draw node
AStarNode *node = [[grid objectAtIndex:x] objectAtIndex:y];
ccDrawColor4F(16, 16, 16, 8);
ccDrawPoint(node.position);
//Draw neighbor lines (there is going to be a lot of them)
for(int i=0; i<node.neighbors.count; i++){
AStarNode *neighbor = [node.neighbors objectAtIndex:i];
ccDrawColor4F(16, 16, 16, 8);
ccDrawLine(node.position, neighbor.position);
}
}
}
}
#end
You can only draw with OpenGL in draw or visit methods.
I did not think that drawing would work in init. Try to put that in an onEnter
-(void) onEnter {
// at this point, the node has been added, is running
// and will be visited as appropriate (i think)
[super onEnter]; // dont forget to super any 'onMethod' override of cocos2d
[self drawGrid];
}

Assertion failure Error when trying to stop sprite action in cocos2d iphone

I am having problem in stoping action. i have 2 sprite animation 1 is ant and second is grasshopper. WHen i am just calling ants animation it works fine but when i try to run both ant and grasshopper animation it gives me error.
* Assertion failure in -[CCSpriteBatchNode addChild:z:tag:], /Users/zohaib/Downloads/zohaibgame/zohaibgame/libs/cocos2d/CCSpriteBatchNode.m:183
it gives error when antMoveEnded is called.
ants animation code
-(void) walk_Ants
{
// 1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"ant-animation.plist"];
/// 2) Create a sprite batch node
CCSpriteBatchNode *spriteSheet_ant = [CCSpriteBatchNode
batchNodeWithFile:#"ant-animation.png"];
[self addChild:spriteSheet_ant];
// 3rd Step
// 3) Gather the list of frames
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 24; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
// 4th Step
// 4) Create the animation object
CCAnimation *walkAnim = [CCAnimation
animationWithSpriteFrames:walkAnimFrames delay:0.05f];
// 5th Step
// 5) Create the sprite and run the animation action
self.ants = [CCSprite spriteWithSpriteFrameName:#"1.png"];
_ants.position = ccp(winSize.width, winSize.height/6);
//_ants.position = ccp(459, 16);
self.walkActionAnt = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
[_ants runAction:_walkActionAnt];
[spriteSheet_ant addChild:_ants];
CCLOG(#"Position %#",NSStringFromCGPoint(_ants.position));
[self walkingAnts];
}
-(void) walkingAnts
{
// 2) Set the desired velocity
float antVelocity = 480.0/10.0;
// 3) Figure out the amount moved in X and Y
CGPoint waking_Path = CGPointMake(X_AXIS_ENDINGPATH, _ants.position.y);
CGPoint moveDifference = ccpSub(waking_Path, _ants.position);
// 4) Figure out the actual length moved
float distanceToMove = ccpLength(moveDifference);
// 5) Figure out how long it will take to move
float moveDuration = distanceToMove / antVelocity;
// 7) Run the appropriate actions
//[_ants stopAction:_moveAction];
id restartAntWalk = [CCCallFuncN actionWithTarget:self selector:#selector(antMoveEnded:)];
self.moveActionAnt = [CCSequence actions:
[CCMoveTo actionWithDuration:moveDuration position:waking_Path],
restartAntWalk,
nil];
//self.moveActionAnt.tag = 121;
[_ants runAction:_moveActionAnt];
_movingAnt = TRUE;
}
- (void) antMoveEnded: (ccTime) dt
{
if(_ants.position.x == -50)
{
[_ants stopAction:_moveActionAnt];
//[self stopActionByTag:121];
_movingAnt = FALSE;
[self walk_Ants];
}
}
GrassHopper code ( mantis )
-(void) mantisCome
{
float w_index = arc4random() % 480;
//float h_index = arc4random() % 320;
self.moveActionMantis = [CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(w_index, 63)],
nil];
[_mantis runAction:_moveActionMantis];
[self schedule:#selector(timer:) interval:5];
}
-(void) mantisGo
{
self.moveActionMantis = [CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(-50, 280)],
nil];
[_mantis runAction:_moveActionMantis];
[self unschedule:#selector(timer:)];
[self mantisAnimation];
}
#pragma -mark Mantis Animation
-(void) mantisAnimation
{
// 1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"mantis-animation.plist"];
/// 2) Create a sprite batch node
CCSpriteBatchNode *spriteSheet_mantis = [CCSpriteBatchNode
batchNodeWithFile:#"mantis-animation.png"];
[self addChild:spriteSheet_mantis];
// 3rd Step
// 3) Gather the list of frames
NSMutableArray *walkAnimFrames_mantis = [NSMutableArray array];
for(int i = 1; i <= 14; ++i) {
[walkAnimFrames_mantis addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
// 4th Step
// 4) Create the animation object
CCAnimation *walkAnim_mantis = [CCAnimation
animationWithSpriteFrames:walkAnimFrames_mantis delay:0.05f];
// 5th Step
// 5) Create the sprite and run the animation action
self.mantis = [CCSprite spriteWithSpriteFrameName:#"1.png"];
_mantis.position = ccp(winSize.width+100, winSize.height+100);
_mantis.flipX=YES;
//_mantis.position = ccp(459, 16);
self.walkActionMantis = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim_mantis]];
walkAnim_mantis.restoreOriginalFrame = NO;
[_mantis runAction:_walkActionMantis];
[spriteSheet_mantis addChild:_mantis];
//CCLOG(#"Position %#",NSStringFromCGPoint(_mantis.position));
[self mantisCome];
}
I figured out what was the problem.
when i was creating animation for ant i was using this code
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 24; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
self.ants = [CCSprite spriteWithSpriteFrameName:#"1.png"];
and when creating animaiton for mantis
NSMutableArray *walkAnimFrames_mantis = [NSMutableArray array];
for(int i = 1; i <= 14; ++i) {
[walkAnimFrames_mantis addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
self.mantis = [CCSprite spriteWithSpriteFrameName:#"1.png"];
i was using 1.png for both. self.ant and self.mantis. i created a new plist file and changed png name from 1.png to ant1.png . It works now.

how to animated sprite for cocos2d in ccz format

According to this tutorial PVR images seem to be the best format for iOS sprites. However after creating a sprite sheet with Texturepacker and exporting out to this format I cannot get the animation to work in cocos2d.
According to the documentation here I should be using
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"LuckyCompiled.plist"];
But neither the tutorial nor the documentation explain how to do animation, except for this. Which is what the code below is based on.
But this only places the base image onto the layer and does not animate.
CCSprite *sprite = [[CCSprite alloc]init];
sprite.position = ccp(player.contentSize.width/2+40, winSize.height/2+40);
// Obtain the shared instance of the cache
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
// load the frames
[cache addSpriteFramesWithFile:#"LuckyCompiled.plist"];
// It loads the frame named "frame1.png".
// IMPORTANT: It doesn't load the image "frame1.png". "frama1.png" is a just the name of the frame
CCSpriteFrame *frame = [cache spriteFrameByName:#"lucky1.png"];
[sprite setDisplayFrame:frame];
[self addChild:sprite];
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 1; i < 10; i++) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"lucky%d.png",i]];
[animFrames addObject:frame];
}
NSLog(#"animaframes %#",animFrames);
CCAnimation *animation = [CCAnimation animationWithSpriteFrames:[NSArray arrayWithArray:animFrames]];
[sprite runAction:[CCAnimate actionWithAnimation:animation]];
Answer:
Needed to have a delay otherwise animation wasnt noticeable
[CCAnimation animationWithSpriteFrames:[NSArray arrayWithArray:animFrames]];
should have been (also no need to make is nsarray, mutable is fine)
[CCAnimation animationWithSpriteFrames:frames delay:0.1f];
Here is the code that I tried, it works fine.
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"walkFrames.plist"];
player = [CCSprite spriteWithSpriteFrameName:#"f1.png"];
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:8];
for (int i = 1; i < 9; i++) {
NSString *file = [NSString stringWithFormat:#"f%d.png", i];
CCSpriteFrame *frame = [frameCache spriteFrameByName:file];
[frames addObject:frame];
}
CCAnimation *walkAnim =[CCAnimation animationWithSpriteFrames:frames delay:0.1f];
CCAnimate *animate = [CCAnimate actionWithAnimation:walkAnim];
CCRepeatForever *rep = [CCRepeatForever actionWithAction:animate];
player.position = ccp(23, 285);
[player runAction:rep];
[self addChild:player];

Debug label y value in cocos2d is off

I have a cocos2d game with a CCLayer called GameplayLayer placed inside a scene. Here is the layer's init code:
- (id)initWithScene1BackgroundLayer:(Scene1BackgroundLayer *)scene5UILayer {
if ((self = [super init])) {
uiLayer = scene5UILayer;
startTime = CACurrentMediaTime();
[self scheduleUpdate];
self.isAccelerometerEnabled = YES;
//chipmunk
[self createSpace];
[self createGround];
mouse = cpMouseNew(space);
self.isTouchEnabled = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"escapesceneatlas.plist"];
sceneSpriteBatchNode = [CCSpriteBatchNode
batchNodeWithFile:#"escapesceneatlas.png"];
hopper = [[[CPHopper alloc] initWithLocation:ccp(200,200) space:space groundBody:groundBody] autorelease];
} else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"escapesceneatlas.plist"];
sceneSpriteBatchNode = [CCSpriteBatchNode
batchNodeWithFile:#"escapesceneatlas.png"];
//Viking became hopper and starts at bottom
hopper = [[[CPHopper alloc] initWithLocation:ccp(100,100) space:space groundBody:groundBody] autorelease];
//An enemy robot called JJ1 also starts at bottom
genericBody = [[[CPGenericBody alloc] initWithLocation:ccp(210,200) space:space groundBody:groundBody] autorelease];
//add the batchnode to layer
[self addChild:sceneSpriteBatchNode z:0];
}
[self addLabel];
[sceneSpriteBatchNode addChild:hopper z:2];
[sceneSpriteBatchNode addChild:genericBody z:2];
}
return self;
}
The addLabel method calls the debugLabel of the hopper class like this:
-(void)addLabel{
//set debuglabel
CCLabelBMFont *debugLabel=[CCLabelBMFont labelWithString:#"NoneNone" fntFile:#"SpaceVikingFont.fnt"];
[self addChild:debugLabel];
[hopper setMyDebugLabel:debugLabel];
}
Then the debugLabel code in the hopper class is:
-(void)setDebugLabelTextAndPosition {
CGPoint newPosition = [self position];
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%d \n", newPosition.x, newPosition.y];
[myDebugLabel setString: [labelString stringByAppendingString:#" tracking..."]];
float yOffset = screenSize.height * 0.195f;
newPosition = ccp(newPosition.x,newPosition.y+yOffset);
[myDebugLabel setPosition:newPosition];
}
For some reason when I run it the X value is fine, its value seems reasonable, it starts out at 100 but the y value is approx 1,567,385 and then if i move the hopper it goes to 35,633,753 and keeps changing to huge random numbers. It seems very unsteady.
Why could this be?
There is a simple typo in your debug label code. You are formatting your floating point number as an integer which just gives garbage results. Because the stringWithFormat function will not implicitly convert the float to int but just take the bit representation of the float and interpret it as an integer number.
A more detailed explanation is given here.
So this
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%d \n", newPosition.x, newPosition.y];
should be
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%.2f \n", newPosition.x, newPosition.y];
.