Reputation: 990
I have an NSMutableArray in my game, in which the array stores "cloud" objects. When spawning the cloud, I iterate through the array and check whether there is a cloud that is nearby, if there is, then I do not spawn the cloud. Here is the code:
BOOL isCloudInRange = NO;
float distance;
do {
//Horizontal Position
isCloudInRange = NO;
if (self.sprite.physicsBody.velocity.dx > 0) {
cloud.position = CGPointMake(self.sprite.position.x + HW*16/5, 0);
}
else if (self.sprite.physicsBody.velocity.dx <0) {
cloud.position = CGPointMake(self.sprite.position.x-HW*16/5, 0);
}
else {
cloud.position = CGPointMake(self.sprite.position.x, 0);
}
//Vertical Position
int offset = arc4random() % (int) 2*self.frame.size.height;
offset -= (int) (self.frame.size.height);
if (self.sprite.physicsBody.velocity.dy > 0) {
cloud.position = CGPointMake(cloud.position.x, self.sprite.position.y + offset + self.sprite.physicsBody.velocity.dy);
}
else if (self.sprite.physicsBody.velocity.dy <0) {
cloud.position = CGPointMake(cloud.position.x, self.sprite.position.y - offset - self.sprite.physicsBody.velocity.dy);
}
else {
cloud.position = CGPointMake(cloud.position.x, self.sprite.position.y + 16*HW/5);
}
if (cloud.position.y <= 300) {
cloud.position = CGPointMake(cloud.position.x, 100 + arc4random() %200);
}
// THIS IS WHERE THE ERROR HAPPENS
for (SKNode *myNode in arrayOfClouds) {
float xPos = myNode.position.x;
float yPos = myNode.position.y;
distance = sqrt((cloud.position.x - xPos) * (cloud.position.x - xPos) + (cloud.position.y - yPos) * (cloud.position.y - yPos));
if (distance < 300.0f) {
NSLog(@"%f",distance);
isCloudInRange = YES;
}
}
} while (isCloudInRange);
If the bottom piece of code is changed to if (distance < 150.0f)
everything works fine. If the distance is kept at 300.0f, however, in a couple seconds or runtime, the game starts iterating forever. Here is an example of a typical log file with this code:
![hola][1]
Click this link if above image doesn't appear (I don't know why it isn't): https://i.sstatic.net/qX8h7.png
The logged floats are the distances between the cloud and whatever cloud is nearby. None of these distances seem to match (I don't have a million clouds spawning every second, they're set to spawn every second or so), and since it freezes with these logs as soon as the game starts, I know there cannot be that many clouds. What is happening? Please help.. Thanks!
Upvotes: 1
Views: 81
Reputation: 664
You say "When spawning the cloud, I iterate through the array and check whether there is a cloud that is nearby, if there is, then I do not spawn the cloud" but to me it looks like your doing the exact opposite. If a cloud is in range (<300) you set isCloudInRange to yes and repeat. Once there are enough clouds it always finds a cloud in range it should loop indefinitely. The more clouds you spawn the harder and harder this is to every get out of the loop ( noting you set it to no at top)
If you are moving clouds and checking to create them on the same thread ( same run loop of code or function calls that are synchronous), you can try moving this code to a background thread, using dispatch_asynch(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), your code block here); and see if that helps.
Info on how to set up concurrency with dispatch_asynch is here:
and blocks are explained:
Upvotes: 1
Reputation: 3008
The main issue I can see here is the following:
You have a do..while loop running checking your cloud distance. Once a cloud is in range, you mark it as YES and re-run the loop. The cloud's X position is never changed in the loop which means it will never move out of range again (infinite loop).
Ideally this is a check that should happen once per game loop (remove the do while).
Also it will be a little more efficient if you put a break; in your for loop. Once a cloud has been found in range there is no need to check the others so you may as well end you loop here.
for (SKNode *myNode in arrayOfClouds) {
float xPos = myNode.position.x;
float yPos = myNode.position.y;
distance = sqrt((cloud.position.x - xPos) * (cloud.position.x - xPos) + (cloud.position.y - yPos) * (cloud.position.y - yPos));
if (distance < 300.0f) {
NSLog(@"%f",distance);
isCloudInRange = YES;
break; // <--drop out of the for each loop now
}
}
Upvotes: 1