0
votes

I know this has been asked a lot before, but I can't find the solution. I have a CCSprite on the screen, the player, that is steered with the accelerometer. Then on top of the screen other CCSprites are spawned every 2 seconds, the enemies. I want all the enemies to follow the player, if the player moves the player the enemies should change direction and go towards that CCSprite. This is my code this far:

- (void)spawnEnemies
{
    monsterTxt = [[CCTexture2D alloc] initWithCGImage:[UIImage imageNamed:@"obj.png"].CGImage resolutionType:kCCResolutionUnknown];
    monster = [CCSprite spriteWithTexture:monsterTxt];

    ... 
    //random spawn position etc.


     CCMoveTo *movemonster = [CCMoveTo actionWithDuration:7.0 position:ccp(_rocket.boundingBox.origin.x, _rocket.boundingBox.origin.y)];
    [monster runAction:[CCSequence actions:movemonster, nil]];

    [_monsters addObject:monster];  //adds the sprite to a mutable array                
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    ...
    //determines new position and move sprite there

    [monster stopAllActions];

    CCMoveTo *movemonster = [CCMoveTo actionWithDuration:7.0 position:ccp(_rocket.boundingBox.origin.x, _rocket.boundingBox.origin.y)];
    [monster runAction:[CCSequence actions:movemonster, nil]];

}

Now when I start the game the sprites are going towards the player, but when the player moves the enemies doesn't update their destination, they just continue down and stops at the y-coordinate of the player. And after a while the app crashes. What am I doing wrong?

1
1. Are you sure your didAccelerate method is being called? 2. You should really do the changes to the actions in the Update function...keep the data from the didAccelerate callback in a class variable. You may be getting lots of calls to didAccelerate. - FuzzyBunnySlippers
If your CCCallBlockN block executes "some time later", where are you getting the "monster" from in your didAccelerate method. It looks like the block is removing it from the parent...that would deallocate it. If you then accessed it in didAccelerate, would it still exist (can't tell from what I see here). - FuzzyBunnySlippers
sorry I pasted old code. That block should not be there at all. But it doesn't really change anything, just that the enemies stops at the players y-value. - user3139210
Are you getting calls to didAccelerate? The behavior you are specifying would be in line with that not being called... - FuzzyBunnySlippers
No it has to be called because the player sprite is moved when the iphone is tilted which is specified in the didAccelerate method - user3139210

1 Answers

0
votes

My guess is that the problem may be in that section of code that you did not post.

In v2.1 of Cocos2d, to receive accelerometer measurements in your layer:

Do this in your init or onEnterTransitionDidFinish call:

   self.accelerometerEnabled = YES;

And overload the is method:

-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
   CCLOG(@"Acceleration (%f,%f,%f)",
         acceleration.x,
         acceleration.y,
         acceleration.z);
   // Do something meaningful...you probably want to send a notification to
   // some other scene/layer/logic.  It should cache that the acceleration value
   // and then do something on an update(...) call with it.  Then reset it so that
   // it does not get used the next update cycle untila new value comes in (here).
}

It seems you have this...and you have indicated you are receiving them...so I'm a bit confused.

SO (SANITY CHECK TIME)...

I created an example project (here) which has a single player sprite being chased by multiple monster sprites. When the user touches the screen (I did not use the accelerometer), the player sprite changes location and the sprites "chase" him. I added some random offset to their target positions so they would not all cluster on top of the player.

Here is the code for (the most important parts of) the file, which is a modified version of the HellowWorldLayer that comes with a cocos2d v2.1 project (I created it from the template):

-(void)createPlayer
{
   playerMoved = NO;

   if(self.player != nil)
   {
      [self removeChild:player];
      self.player = nil;
   }
   CGSize scrSize = [[CCDirector sharedDirector] winSize];
   CCSprite* playerSprite = [CCSprite spriteWithFile:@"Icon.png"];
   playerSprite.scale = 2.0;
   playerSprite.position = ccp(scrSize.width/2,scrSize.height/2);
   [self addChild:playerSprite];
   self.player = playerSprite;
}

-(void)createMonsters
{
   const int MAX_MONSTERS = 4;
   if(self.monsters.count > 0)
   {  // Get rid of them
      for(CCSprite* sprite in monsters)
      {
         [self removeChild:sprite];
      }
      [self.monsters removeAllObjects];
   }
   CGSize scrSize = [[CCDirector sharedDirector] winSize];
   for(int idx = 0; idx < MAX_MONSTERS; idx++)
   {
      CCSprite* sprite = [CCSprite spriteWithFile:@"Icon.png"];
      float randomX = (arc4random()%100)/100.0;
      float randomY = (arc4random()%100)/100.0;
      sprite.scale = 1.0;
      sprite.position = ccp(scrSize.width*randomX,scrSize.height*randomY);
      [self addChild:sprite];
      [monsters addObject:sprite];
   }
}

-(void)update:(ccTime)delta
{
   if(playerMoved)
   {  // Modify all the actions on all the monsters.
      CGPoint playerPos = player.position;
      for(CCSprite* sprite in monsters)
      {
         float randomX = (1.0)*(arc4random()%50);
         float randomY = (1.0)*(arc4random()%50);
         CGPoint position = ccp(playerPos.x+randomX,playerPos.y+randomY);
         [sprite stopAllActions];
         [sprite runAction:[CCMoveTo actionWithDuration:3.0 position:position]];
      }
      playerMoved = NO;
   }
}

I have a retained array of CCSprite* objects (monsters) and a CCSprite* for the player. I have a flag to tell me if the player has changed position (player moved). In the update loop, if the player has moved, stop all the actions on the monsters and update them.

On the screen it looks like this:

enter image description here

And then when I move the main sprite...

enter image description here

They follow it...

enter image description here

Was this helpful?