ADGame/Classes/GameViewController.m

/*
    File: GameViewController.m
Abstract: Main view controller for ADGame
 Version: 1.2
 
Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms.  If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
 
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple.  Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
 
The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
 
Copyright (C) 2012 Apple Inc. All Rights Reserved.
 
*/
 
#import "GameViewController.h"
#import "ScoreView.h"
 
// Class extention for private methods.
@interface GameViewController()
 
// Interstitials
- (void)cycleInterstitial;
- (void)presentInterlude;
 
// Game Input
- (void)actOnPlayer:(int)player;
 
// Game Logic
- (void)score:(int)idx;
- (void)startGame;
- (void)gameStartCountdown:(NSTimer *)timer;
- (void)winGame;
- (void)resetGame;
- (void)resetGameSoon;
- (void)layoutGame;
 
// Graphics
- (UIBezierPath *)scorePath;
 
@end
 
#pragma mark -
@implementation GameViewController
 
// Game Phases
enum {
    ADGameWaiting = 0,
    ADGameRequested,
    ADGameStarted1,
    ADGameStarted2,
    ADGameStarted3,
    ADGameStartedDeclare1,
    ADGameStartedDeclare2,
    ADGameStartedDeclare3,
    ADGameStartedWars1,
    ADGamePlaying,
    ADGameWon,
};
 
@synthesize titleLabel;
@synthesize player1;
@synthesize player2;
@synthesize player3;
@synthesize player4;
@synthesize scoreView;
 
#pragma mark -
#pragma mark Lifetime Management
 
- (void)viewDidLoad 
{
    [super viewDidLoad];
    [self cycleInterstitial]; // Prepare our interstitial for after the game so that we can be certain its ready to present
    [self resetGame]; // Get the game ready for the player
    scoreView.fillColor = [UIColor colorWithRed:0.4375 green:0.875 blue:1.0 alpha:0.75];
    scoreView.strokeColor = [UIColor colorWithRed:0.25 green:0.5625 blue:0.6875 alpha:0.5];
}
 
- (void)viewDidUnload
{
    interstitial.delegate = nil;
    
    self.titleLabel = nil;
    self.player1 = nil;
    self.player2 = nil;
    self.player3 = nil;
    self.player4 = nil;
    self.scoreView = nil;
    [interstitial release]; interstitial = nil;
    [super viewDidUnload];
}
 
- (void)dealloc
{
    interstitial.delegate = nil;
    
    [titleLabel release];
    [player1 release];
    [player2 release];
    [player3 release];
    [player4 release];
    [scoreView release];
    [interstitial release];
    [super dealloc];
}
 
#pragma mark -
#pragma mark View Layout
 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}
 
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [self layoutGame];
}
 
- (void)viewDidLayoutSubviews
{
    [self layoutGame];
}
 
#pragma mark -
#pragma mark Interstitial Management
 
- (void)cycleInterstitial
{
    // Clean up the old interstitial...
    interstitial.delegate = nil;
    [interstitial release];
    // and create a new interstitial. We set the delegate so that we can be notified of when 
    interstitial = [[ADInterstitialAd alloc] init];
    interstitial.delegate = self;
}
 
- (void)presentInterlude
{
    // If the interstitial managed to load, then we'll present it now.
    if (interstitial.loaded) {
        [interstitial presentFromViewController:self];
    } else {
        [self resetGameSoon];
    }
}
 
#pragma mark ADInterstitialViewDelegate methods
 
// When this method is invoked, the application should remove the view from the screen and tear it down.
// The content will be unloaded shortly after this method is called and no new content will be loaded in that view.
// This may occur either when the user dismisses the interstitial view via the dismiss button or
// if the content in the view has expired.
- (void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd
{
    [self cycleInterstitial];
    if (gamePhase == ADGameWon) {
        [self resetGameSoon];
    }
}
 
// This method will be invoked when an error has occurred attempting to get advertisement content. 
// The ADError enum lists the possible error codes.
- (void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error
{
    [self cycleInterstitial];
    if (gamePhase == ADGameWon) {
        [self resetGameSoon];
    }
}
 
#pragma mark -
#pragma mark Game Input
 
- (void)actOnPlayer:(int)player
{
    if (gamePhase == ADGamePlaying) {
        [self score:player];
    } else if (gamePhase == ADGameWaiting) {
        [self startGame];
    }
}
 
- (IBAction)scorePlayer1
{
    [self actOnPlayer:0];
}
 
- (IBAction)scorePlayer2
{
    [self actOnPlayer:1];
}
 
- (IBAction)scorePlayer3
{
    [self actOnPlayer:2];
}
 
- (IBAction)scorePlayer4
{
    [self actOnPlayer:3];
}
 
#pragma mark -
#pragma mark Game Logic
 
- (void)score:(int)idx
{
    scores[idx] += 0.05;
    scoreView.shape = [self scorePath];
    if (scores[idx] >= 1.0) {
        gamePhase = ADGameWon;
        gameWinner = idx+1;
        [self winGame];
    }
}
 
- (void)startGame
{
    // Only start a game if we haven't started and one hasn't been requested.
    if (gamePhase == ADGameWaiting) {
        gamePhase = ADGameRequested;
        titleLabel.hidden = NO;
        titleLabel.text = @"";
        titleLabel.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
        [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(gameStartCountdown:) userInfo:nil repeats:YES];
    }
}
 
- (void)gameStartCountdown:(NSTimer *)timer
{
    switch (gamePhase) {
        case ADGameRequested:
            titleLabel.text = @"1";
            break;
        case ADGameStarted1:
            titleLabel.text = @"2";
            break;
        case ADGameStarted2:
            titleLabel.text = @"3";
            break;
        case ADGameStarted3:
            titleLabel.text = @"4";
            break;
        case ADGameStartedDeclare1:
        case ADGameStartedDeclare2:
        case ADGameStartedDeclare3:
            titleLabel.text = @"I declare a thumb war!";
            break;
        case ADGameStartedWars1:
            titleLabel.hidden = YES;
            titleLabel.text = @"Thumb Wars!";
            scoreView.hidden = NO;
            [timer invalidate];
            break;
    }
    ++gamePhase;
}
 
- (void)winGame
{
    titleLabel.text = [NSString stringWithFormat:@"Player %i won!", gameWinner];
    titleLabel.hidden = NO;
    [UIView animateWithDuration:1.0 animations:^{
        scoreView.alpha = 0.0;
        titleLabel.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(titleLabel.bounds));
        player1.center = CGPointMake(player1.center.x, player1.center.y + 1024.0);
        player2.center = CGPointMake(player2.center.x + 1024.0, player2.center.y);
        player3.center = CGPointMake(player3.center.x, player3.center.y - 1024.0);
        player4.center = CGPointMake(player4.center.x - 1024.0, player4.center.y);
    } completion:^(BOOL finished) {
        [self presentInterlude];
    }];
}
 
- (void)resetGame
{
    scores[0] = scores[1] = scores[2] = scores[3] = 0.0;
    scoreView.hidden = YES;
    scoreView.alpha = 1.0;
    scoreView.shape = [self scorePath];
    titleLabel.text = @"Thumb Wars!";
    titleLabel.hidden = NO;
    gamePhase = ADGameWaiting;
    gameWinner = 0;
    [self layoutGame];
}
 
- (void)resetGameSoon
{
    // Give the user a few seconds to bask in the glory of having won before resetting the game.
    [self performSelector:@selector(resetGame) withObject:nil afterDelay:3.0];
}
 
- (void)layoutGame
{
    if (gamePhase < ADGameWon) {
        CGRect bounds = self.view.bounds;
        player1.center = CGPointMake(CGRectGetMidX(bounds), 56.0);
        player2.center = CGPointMake(56.0, CGRectGetMidY(bounds));
        player3.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds) - 56.0);
        player4.center = CGPointMake(CGRectGetMaxX(bounds) - 56.0, CGRectGetMidY(bounds));
        scoreView.shape = [self scorePath];
        titleLabel.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
    } else {
        titleLabel.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(titleLabel.bounds));
        titleLabel.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(titleLabel.bounds));
        player1.center = CGPointMake(player1.center.x, player1.center.y + 1024.0);
        player2.center = CGPointMake(player2.center.x + 1024.0, player2.center.y);
        player3.center = CGPointMake(player3.center.x, player3.center.y - 1024.0);
        player4.center = CGPointMake(player4.center.x - 1024.0, player4.center.y);
    }
}
 
#pragma mark -
#pragma mark Game Graphics
 
#define kOffset 20.0
 
CGPoint CenterPoint(CGPoint p1, CGPoint p2)
{
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
 
- (UIBezierPath *)scorePath
{
    CGRect bounds = scoreView.bounds;
    CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
    CGFloat xradius = bounds.size.width / 2.0 - kOffset, yradius = bounds.size.height / 2.0 - kOffset;
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    CGPoint p1 = CGPointMake(center.x, center.y - yradius * scores[0] - kOffset);
    CGPoint p2 = CGPointMake(center.x - xradius * scores[1] - kOffset, center.y);
    CGPoint p3 = CGPointMake(center.x, center.y + yradius * scores[2] + kOffset);
    CGPoint p4 = CGPointMake(center.x + xradius * scores[3] + kOffset, center.y);
    CGPoint cp12 = CenterPoint(CenterPoint(p1, p2), center);
    CGPoint cp23 = CenterPoint(CenterPoint(p2, p3), center);
    CGPoint cp34 = CenterPoint(CenterPoint(p3, p4), center);
    CGPoint cp41 = CenterPoint(CenterPoint(p4, p1), center);
    [path moveToPoint:p1];
    [path addQuadCurveToPoint:p2 controlPoint:cp12];
    [path addQuadCurveToPoint:p3 controlPoint:cp23];
    [path addQuadCurveToPoint:p4 controlPoint:cp34];
    [path addQuadCurveToPoint:p1 controlPoint:cp41];
    [path closePath];
    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(cp12.x, cp12.y, cp34.x - cp12.x, cp34.y - cp12.y)]];
    
    return path;
}
 
@end