2

Sorry to bother, but I am in a bit of a pickle and I was wondering if anyone here could give me a hand.

I am currently designing a game in which enemies appear on the left side of the screen (out of boundaries) and move to the right. I have used a number of codes (this is using Sparrow Framework) and pretty much the number of enemies increases as you beat them. i.e. lvl 1-> 1 enemy, lvl 2-> 2 enemies, lvl3-> 3 enemies, etc...

I am having some trouble though with producing enemies. I have them appearing on 1 of 5 set paths (path numbers in NSMutableArray), selected by a random number generator, however they often appear on the same path, 1 on top of the other.

To produce the enemies, i am running a number of methods: addEnemy -> produces the enemies (animations) which then travel from left to right. onTouchEnemy -> if i touch the enemy, they die. activates drawEnemies drawEnemies -> calls addEnemy a number of times equal to your lvl. coded as:

for(int i = 0; i < level; i++){
  [self performSelector:@selector(addEnemy) withObject:nil afterDelay:3.0];
}

Is there a way to program so that there is a delay between activating the produce enemies method? I tried this afterDelay, but for some reason the program just ignores the 3 second delay and just produces enemies all in 1 go. This is rather irritating since i would like them to appear in a more orderly fashion.

I thank anyone willing to give me a hand with this. Sjkato.

iDev
  • 23,310
  • 7
  • 60
  • 85
SKato
  • 95
  • 6
  • 15

3 Answers3

2

Did you mean to do this, with a extra "*i" at the end? Like this:

for(int i = 0; i < level; i++){
    [self performSelector:@selector(addEnemy) withObject:nil afterDelay:3.0 * i];
}
Graham Perks
  • 23,007
  • 8
  • 61
  • 83
  • Er, sorry, but you kinda lost me with the '*i' added to the end of your code...do you mean that this will cause the program to delay at different times rather than just fire off all the addEnemy commands after 3 seconds? – SKato Sep 23 '10 at 16:03
  • 1
    Yes, that's exactly what I mean. You said they were all appearing at the same time. I thought you were maybe trying to stagger each enemy. In your code they'd all appear at the 3 second point. Note that performSelector:withObject:afterDelay: returns immediately. It doesn't pause for 3 seconds. So your code is queuing up a bunch of addEnemy calls which will all get called at the same time, 3 seconds hence. The "* i" will stagger them out, 3 seconds apart, if that's what you want. The method works fine, no need to switch to NSTimer. – Graham Perks Sep 23 '10 at 19:09
  • Thank you so much! I hadnt realised that you could do this and make the command work. I was having some issues trying to make Jasarien's suggestion work, but I wasnt sure how much of my entire code i would have to change to make it work. This is much simpler...thank you so much! – SKato Sep 24 '10 at 10:32
  • 1
    Great! Glad it worked. BTW it's normal on stackoverflow to click the up arrow or checkbox on responses you find helpful :) There are several on this page that might qualify. That way you're more likely to have questions answered in the future. – Graham Perks Sep 24 '10 at 13:03
2

performSelector:withObject:afterDelay: appears to ignore its delay because of the way the code executes. That for loop will iterate almost instantly, queuing up 3 calls to the addEnemy method. After 3 seconds the addEnemy methods execute, almost all at the same time.

To get a better result, you should look at NSTimer. You could set an interval of 3 seconds and tell it to repeat (you can invalidate the timer after the desired number of enemies has been produced).

Something like:

// creates and returns a new timer
// the timer is retained by the run loop for as long as it is valid
// invalidating the timer will cause the runloop to release it.
myTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                 target:self
                               selector:@selector(addEnemy)
                               userInfo:nil
                                repeats:YES];

This will cause the addEnemy method to be fired once every 3 seconds. You should keep a tally of how many enemies you have already made, and after the last one is made, stop the timer so that it doesn't fire again.

if (numberOfDesiredEnemies == numberOfEnemiesProduced)
{
    [myTimer invalidate], timer = nil;
}
Jasarien
  • 58,279
  • 31
  • 157
  • 188
  • Thank you very much for the responce. I think I understand the delay code a little better now that my suspicions were confirmed. I will try this code out then try out a varient to see if i can spice things up a little :) – SKato Sep 23 '10 at 16:01
0

Try to look through NSTimer class.
There are some methods that provide ability to perform selectors with predefined delay and loop conditions.

knuku
  • 6,082
  • 1
  • 35
  • 43
  • Thanks for the tip! I'll test out Jasarien's suggested code, then have a closer look at the NSTimer class. – SKato Sep 23 '10 at 16:02