Game score increasing rapidly....

Discussion in 'iOS Programming' started by SunnyLi, Oct 31, 2010.

  1. SunnyLi Guest

    Joined:
    Oct 7, 2010
    #1
    Hi Guys,

    Im building just a simple game with a ball and a paddle at the bottom, everytime the ball hits the paddle you get 1 point. But the minute the score is increasing by 7-8 points everytime you hit the paddle. Im not sure where im going wrong could someone help.

    Code:
    #import "GameViewController.h"
    #import "KeepyUppiesViewController.h"
    #import "GameOverViewController.h"
    
    @implementation GameViewController
    
    @synthesize scoreLabel;
    @synthesize score;
    @synthesize ball;
    @synthesize paddle;
    @synthesize livesLabel;
    @synthesize messageLabel;
    
    - (void)startPlaying {
    	if (!lives) {
    		lives = 3;
    		score = 0;
    		
    	}
    	scoreLabel.text = [NSString stringWithFormat:@"%d", score];
    	livesLabel.text = [NSString stringWithFormat:@"%d", lives];
    	ball.center = CGPointMake(159, 239);
    	ballMovement = CGPointMake(4,4);
    	// choose whether the ball moves left to right or right to left
    	if (arc4random() % 100 < 50)
    		ballMovement.x = -ballMovement.x;
    	messageLabel.hidden = YES;
    	isPlaying = YES;
    	/*
    	[self initialiseTimer];
    	*/
    	[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    	
    }
    - (void)pauseGame {
    	[theTimer invalidate];
    	theTimer = nil;
    	
    }
    
    
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
    	
    	[self startPlaying];
    	
    	ballMovement = CGPointMake(4,4);
    	
    	[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    
    
    
    	 }
    - (void)initialiseTimer {
    	
    	
    	if (theTimer == nil) {
    		
    		float theInterval = 1.0f/50.0f;
    		
    		theTimer = [NSTimer scheduledTimerWithTimeInterval:theInterval target:self
    												  selector:@selector(animateBall:) userInfo:nil repeats:YES];
    		
    	}
    }
    
    - (void)animateBall:(NSTimer *)theTimer {
    	
    	ball.center = CGPointMake(ball.center.x+ballMovement.x, ball.center.y+ballMovement.y);
    	
    	BOOL paddleCollision = ball.center.y >= paddle.center.y - 16 &&
    	
    	ball.center.y <= paddle.center.y + 16 &&
    	ball.center.x > paddle.center.x - 32 &&
    	ball.center.x < paddle.center.x + 32;
    	
    
    	if(paddleCollision)
    		ballMovement.y = -ballMovement.y;
    	
    	
    	if (ball.center.x > 310 || ball.center.x < 16)
    		ballMovement.x = -ballMovement.x;
    	
    	if (ball.center.y < 32)
    		ballMovement.y = -ballMovement.y;
    	if (ball.center.y > 444) {
    		[self pauseGame];
    		isPlaying = NO;
    		lives--;
    		
    		livesLabel.text = [NSString stringWithFormat:@"%d", lives];
    		if (!lives) {
    			messageLabel.text = @"Game Over";
    			[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    			
    			GameOverViewController *second = [[GameOverViewController alloc] initWithNibName:nil bundle:nil];
    			second.score = score;
    			second.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    			[self presentModalViewController:second animated:YES];
    			
    			
    		} else {
    			messageLabel.text = @"Ball Hit The Floor :(";
    		}
    		messageLabel.hidden = NO;
    	}
    
    
    	
    	if (CGRectIntersectsRect(ball.frame, paddle.frame)) {
    		[self checkcollision];
    			[B]stopdetection = FALSE;[/B]
    		
    	}
    	
    	
    }
    
     - (void)checkcollision {
     if (!stopdetection && CGRectIntersectsRect(ball.frame, paddle.frame)) {
     
     
     [B]score ++;
     scoreLabel.text = [NSString stringWithFormat:@"%d", score];
     
     stopdetection = TRUE;[/B]
     
     float diff=ball.center.x - paddle.center.x;
     ballMovement.x=150;  // default if it hits the middle
     if (diff>150) {
     ballMovement.x=10;
     }
     if (diff<150) {
     ballMovement.x=-10;
     }
     
     
     }
     
     }
     
     - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    	if (isPlaying) {
    		
    		UITouch *touch = [[event allTouches] anyObject];
    		touchOffset = paddle.center.x -
    		[touch locationInView:touch.view].x;
    		
    	} else {
    		[self startPlaying];
    		
    	}
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    	if (isPlaying) {
    		
    		UITouch *touch = [[event allTouches] anyObject];
    		float distanceMoved =([touch locationInView:touch.view].x + touchOffset) -paddle.center.x;
    		float newX = paddle.center.x + distanceMoved;
    		if (newX > 30 && newX < 290)
    			
    			paddle.center = CGPointMake( newX, paddle.center.y );
    		
    	}
    }
    
    
    
    I think its the placement of the bits in bold but im not sure to be honest.
     
  2. Thomas Harte macrumors 6502

    Joined:
    Nov 30, 2005
    #2
    Score goes up by more than one because your ball overlaps the paddle for several frames. You seem to have added a stopdetection flag to try to prevent this, but you set it back to FALSE immediately after setting it to TRUE.

    In your code, I'd imagine you'd be better off incrementing the score at the same moment as you invert the y vector.
     
  3. hodgey87 Guest

    Joined:
    Mar 20, 2009
    #3
    Cheers for your reply :) yeh if i make the uiimageview really small i dont get as many problems with the score but occasionally i still get a 5 point increase/

    Im not sure what you mean by the inver the y vector.
     
  4. hodgey87 Guest

    Joined:
    Mar 20, 2009
    #4
    Been working on this again all day today, havent got much futher, the score is incrementing by 1 point each time but occasionally there is the 5 - 10 point increase.

    Code:
    #import "GameViewController.h"
    #import "KeepyUppiesViewController.h"
    #import "GameOverViewController.h"
    
    @implementation GameViewController
    
    @synthesize scoreLabel;
    @synthesize score;
    @synthesize ball;
    @synthesize paddle;
    @synthesize livesLabel;
    @synthesize messageLabel;
    
    - (void)startPlaying {
    	if (!lives) {
    		lives = 3;
    		score = 0;
    		
    	}
    	scoreLabel.text = [NSString stringWithFormat:@"%d", score];
    	livesLabel.text = [NSString stringWithFormat:@"%d", lives];
    	ball.center = CGPointMake(159, 239);
    	ballMovement = CGPointMake(4,4);
    	// choose whether the ball moves left to right or right to left
    	if (arc4random() % 100 < 50)
    		ballMovement.x = -ballMovement.x;
    	messageLabel.hidden = YES;
    	isPlaying = YES;
    	/*
    	[self initialiseTimer];
    	*/
    	[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    	
    }
    - (void)pauseGame {
    	[theTimer invalidate];
    	theTimer = nil;
    	
    }
    
    
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
    	
    	[self startPlaying];
    	
    	ballMovement = CGPointMake(4,4);
    	
    	[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    
    
    
    	 }
    - (void)initialiseTimer {
    	
    	
    	if (theTimer == nil) {
    		
    		float theInterval = 1.0f/50.0f;
    		
    		theTimer = [NSTimer scheduledTimerWithTimeInterval:theInterval target:self
    												  selector:@selector(animateBall:) userInfo:nil repeats:YES];
    		
    	}
    }
    
    - (void)animateBall:(NSTimer *)theTimer {
    	
    	ball.center = CGPointMake(ball.center.x+ballMovement.x, ball.center.y+ballMovement.y);
    	
    	BOOL paddleCollision = ball.center.y >= paddle.center.y - 16 &&
    	
    	ball.center.y <= paddle.center.y + 16 &&
    	ball.center.x > paddle.center.x - 32 &&
    	ball.center.x < paddle.center.x + 32;
    	
    
    	if(paddleCollision)
    		ballMovement.y = -ballMovement.y;
    	
    	
    	if (ball.center.x > 310 || ball.center.x < 16)
    		ballMovement.x = -ballMovement.x;
    	
    	if (ball.center.y < 32)
    		ballMovement.y = -ballMovement.y;
    	if (ball.center.y > 444) {
    		[self pauseGame];
    		isPlaying = NO;
    		lives--;
    		
    		livesLabel.text = [NSString stringWithFormat:@"%d", lives];
    		if (!lives) {
    			messageLabel.text = @"Game Over";
    			[self performSelector:@selector(initialiseTimer) withObject:nil afterDelay:2.0];
    			
    			GameOverViewController *second = [[GameOverViewController alloc] initWithNibName:nil bundle:nil];
    			second.score = score;
    			second.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    			[self presentModalViewController:second animated:YES];
    			
    			
    		} else {
    			messageLabel.text = @"Ball Hit The Floor :(";
    		}
    		messageLabel.hidden = NO;
    	}
    
    
    	
    	[B]if (CGRectIntersectsRect(ball.frame, paddle.frame)) {
    		
    		
    		score ++;
    		scoreLabel.text = [NSString stringWithFormat:@"%d", score];
    		
    		[self checkcollision];
    			stopdetection = FALSE;[/B]
    	
    	}
    	
    	
    }
    
    - (void)checkcollision {
    	
    		
    		
    		stopdetection = TRUE;
    		
    		float diff=ball.center.x - paddle.center.x;
    		ballMovement.x=150;  // default if it hits the middle
    		if (diff>150) {
    			ballMovement.x=10;
    		}
    		if (diff<150) {
    			ballMovement.x=-10;
    		}
    		
    
    	
    }
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    	if (isPlaying) {
    		
    		UITouch *touch = [[event allTouches] anyObject];
    		touchOffset = paddle.center.x -
    		[touch locationInView:touch.view].x;
    		
    	} else {
    		[self startPlaying];
    		
    	}
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    	if (isPlaying) {
    		
    		UITouch *touch = [[event allTouches] anyObject];
    		float distanceMoved =([touch locationInView:touch.view].x + touchOffset) -paddle.center.x;
    		float newX = paddle.center.x + distanceMoved;
    		if (newX > 30 && newX < 290)
    			
    			paddle.center = CGPointMake( newX, paddle.center.y );
    		
    	}
    }
    
    
     
  5. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #5
    You removed all the code that tests stopdetection. All that's left is one place that sets it to TRUE, and another place that sets it to FALSE. It almost looks like you're semi-randomly removing code and hoping it will work, instead of trying to analyze and understand the code you had.

    The fix is only going to be apparent when you analyze the code you had, and understand how it wasn't working. The best way to analyze the code is to step through it manually, taking careful note of the state of the stopdetection variable.

    Pretend you have a coworker you're walking through the code, and your job is to explain why your code does what it does, line by line. For example:
    Explainer (you): "This tests the ball and paddle rects for intersection. If they intersect, it's a collision, so this block is executed. If no collision, it's not. When there's a collision, the score is incremented by one. Then the scorelabel's text is changed to the new score."

    Explainee (me): "So the only condition for incrementing the score in the latest code is that the rects intersect. Does that seem correct, or is that what stopdetection was for?"

    Explainer: _____​

    By the way, this act of explaining to a coworker is part of a process called a code review. When you do it by yourself, it's called debugging.
     
  6. hodgey87 Guest

    Joined:
    Mar 20, 2009
    #6
    Thanks for your reply, i was doing that to be honest to start off with. But noww ive been through the code and commented the main parts of the code. I just dont understand how to stop the score from increasing randomly some times. This is the code im not sure on:

    Code:
    if (CGRectIntersectsRect(ball.frame, paddle.frame)) {
    		
    	
    		score ++;
    		scoreLabel.text = [NSString stringWithFormat:@"%d", score];
    		
    		stopdetection = FALSE;
    	
    	}
    	
    	
    }
    
    - (void)checkcollision {
    	
    	if (!stopdetection && CGRectIntersectsRect(ball.frame, paddle.frame)) {	
    		
    		stopdetection = TRUE;
    		
    		float diff=ball.center.x - paddle.center.x;
    		ballMovement.x=150;  // default if it hits the middle
    		if (diff>150) {
    			ballMovement.x=10;
    		}
    		if (diff<150) {
    			ballMovement.x=-10;
    		}
    	}
    
    	
    }
    
    
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    Your code is still mostly wrong, because checkcollision is never called.

    Going back to your original code:
    Code:
    	if (CGRectIntersectsRect(ball.frame, paddle.frame)) {
    		[self checkcollision];
    			stopdetection = FALSE;
    		
    	}
    
    Think about exactly what happens here. In checkcollision (original version), you conditionally set stopdetection to TRUE. Then immediately after it returns, you always set stopdetection to FALSE. Logically, that makes no sense if the variable was just set to TRUE by checkcollision.

    Now think about what ought to happen. When the ball and paddle first intersect, then that's a new collision (score increases). Next, you have to wait for the ball and paddle to stop intersecting, which signals the end of the collision. You should only start looking for new collisions after the end of the previous collision. It's this "no longer intersecting" part that all your code is missing. If you renamed the boolean variable to isColliding it might make more sense.
     

Share This Page