Question

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?

Was it helpful?

Solution

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top