Yomo Yomo - 2 months ago 8
iOS Question

Multiple ints - They don't work at the same time (Obj-C)

I'm making a simple little game.

I have two ints:

1) One to make an object's position to be generated randomly on the Y- and X-axis.

2) One for the scoring function.

I use NSTimers to make the objects move, and for the score to add 1 every second.

The problem is that the game gets all bugged and the timers start going crazy when the both ints exist. If I remove the scoring int/timer, the objects move perfectly. And the other way around.

I can't seem to find the issue since it should be working.

Any ideas?

ViewController.h:

int scoreNumber;
int randomPosition;


ViewController.m:

#define IsIphone4 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )480 ) < DBL_EPSILON )

#define IsIphone5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )

#define IsIphone6 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )667 ) < DBL_EPSILON )

#define IsIphone6Plus ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )736 ) < DBL_EPSILON )

- (void)obstaclesMoving {

obstacle.center = CGPointMake(obstacle.center.x - 1, obstacle.center.y);
obstacle2.center = CGPointMake(obstacle2.center.x - 1, obstacle2.center.y);
obstacle3.center = CGPointMake(obstacle3.center.x - 1, obstacle3.center.y);

if (IsIphone4) {

if (obstacle.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 70;
obstacle.center = CGPointMake(320, randomPosition);
}

if (obstacle2.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 360;
obstacle2.center = CGPointMake(320, randomPosition);

}

if (obstacle3.center.x < 0) {
randomPosition = arc4random_uniform(100);
randomPosition = randomPosition + 215;
obstacle3.center = CGPointMake(320, randomPosition);

}

}

if (IsIphone5) {

if (obstacle.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 70;
obstacle.center = CGPointMake(320, randomPosition);
}

if (obstacle2.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 448;
obstacle2.center = CGPointMake(320, randomPosition);

}


if (obstacle3.center.x < 0) {
randomPosition = arc4random_uniform(100);
randomPosition = randomPosition + 259;
obstacle3.center = CGPointMake(320, randomPosition);

}

}

if (IsIphone6) {

if (obstacle.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 70;
obstacle.center = CGPointMake(375, randomPosition);
}

if (obstacle2.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 547;
obstacle2.center = CGPointMake(375, randomPosition);

}


if (obstacle3.center.x < 0) {
randomPosition = arc4random_uniform(100);
randomPosition = randomPosition + 309;
obstacle3.center = CGPointMake(375, randomPosition);

}

}

if (IsIphone6Plus) {

if (obstacle.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 70;
obstacle.center = CGPointMake(414, randomPosition);
}

if (obstacle2.center.x < 0) {
randomPosition = arc4random_uniform(60);
randomPosition = randomPosition + 616;
obstacle2.center = CGPointMake(414, randomPosition);

}


if (obstacle3.center.x < 0) {
randomPosition = arc4random_uniform(100);
randomPosition = randomPosition + 343;
obstacle3.center = CGPointMake(414, randomPosition);

}

}

}

- (IBAction)characterUp:(id)sender {

characterDrop = 5;

}

- (IBAction)characterDown:(id)sender {

characterDrop = -5;

}

- (void)characterMoving {

character.center = CGPointMake(character.center.x, character.center.y - characterDrop);

characterDrop = characterDrop - 0.1;

if ((CGRectIntersectsRect(character.frame, ground.frame)) && (characterDrop < -1)) {

[self gameOver];

//Sound for G.O.
}

if ((CGRectIntersectsRect(character.frame, roof.frame)) && (characterDrop < -1)) {

[self gameOver];

//Sound for G.O.
}

}

- (IBAction)startGame:(id)sender {

startGameButton.hidden = YES;

characterMovement = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(characterMoving) userInfo:nil repeats:YES];

characterDrop = -5;

obstacleTimer = [NSTimer scheduledTimerWithTimeInterval:0.0055 target:self selector:@selector(obstaclesMoving) userInfo:nil repeats:YES];

scorer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(scoring) userInfo:nil repeats:YES];

}

- (void)scoring {

scoreNumber = scoreNumber + 1;
scoreLabelInGame.text = [NSString stringWithFormat:@"%i", scoreNumber];
scoreLabelGameOver.text = [NSString stringWithFormat:@"%i", scoreNumber];

}

- (void)gameOver {

if (scoreNumber > bestScoreNumber) {

[[NSUserDefaults standardUserDefaults] setInteger:scoreNumber forKey:@"bestScoreSaved"];
bestScoreLabel.text = [NSString stringWithFormat:@"New best: %i", scoreNumber];

}

character.hidden = YES;
obstacle.hidden = YES;
obstacle2.hidden = YES;
obstacle3.hidden = YES;
startGameButton.hidden = YES;
scoreLabelInGame.hidden = YES;
characterUpButton.hidden = YES;
characterDownButton.hidden = YES;
scoreLabelGameOver.hidden = NO;
bestScoreLabel.hidden = NO;
gameOverLabel.hidden = NO;
restartGameButton.hidden = NO;
backButton.hidden = NO;

[characterMovement invalidate];
[obstacleTimer invalidate];
[obstacleTimer2 invalidate];
[obstacleTimer3 invalidate];
[obstacleTimer4 invalidate];
[scorer invalidate];

}

- (void)viewDidLoad {

bestScoreNumber = [[NSUserDefaults standardUserDefaults] integerForKey:@"bestScoreSaved"];
bestScoreLabel.text = [NSString stringWithFormat:@"Best: %li", (long)bestScoreNumber];

scoreNumber = 0;

scoreLabelGameOver.hidden = YES;
bestScoreLabel.hidden = YES;
gameOverLabel.hidden = YES;
restartGameButton.hidden = YES;
backButton.hidden = YES;

[super viewDidLoad];
// Do any additional setup after loading the view.
}

Answer

I think a cleaner approach would be to move to a CADisplayLink or a single NSTimer and move your views off of the selector it calls.

/* Add _amountOfTicks as an instance Variable */
{
  int _amountOfTicks;
  int scoreNumber;
  int randomPosition;
}

/* replace timers in startGame */
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick)];
displayLink.frameInterval = 1;
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

- (void)tick {

  _amountOfTicks++;
  if (_amountOfTicks > 16){
    _amountOfTicks = 1;
  }

  if (_amountOfTicks == 2) {
     [self characterMoving] 
  }

  if (_amountOfTicks == 4) {
     [self obstaclesMoving] 
  }

  if (_amountOfTicks == 16) {
     [self scoring] 
  }

}

Also, in the method below you're reducing the center.x by 1 then changing it back to the screens width directly below when checking for macros.

- (void)obstaclesMoving {

obstacle.center = CGPointMake(obstacle.center.x - 1, obstacle.center.y); /* reduce by 1 */
obstacle2.center = CGPointMake(obstacle2.center.x - 1, obstacle2.center.y);
obstacle3.center = CGPointMake(obstacle3.center.x - 1, obstacle3.center.y);

if (IsIphone4) {

  if (obstacle.center.x < 0) {
    randomPosition = arc4random_uniform(60);
    randomPosition = randomPosition + 70;
    obstacle.center = CGPointMake(320, randomPosition); /* changes it back to screen width which makes what you did up above useless */
  }
}
Comments