指で引っ張って飛ばすゴルフゲーム

(XcodeのiOS6 Simulatorでつくってみた。)

ポイント

・touchesMovedでボールから引っ張った絵を描画

・UIViewに減衰に関する値を設定して、ボール通る速さを変える

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

// ボールの状態

typedef enum {

    BallStop,

    BallTouch,

    BallRelease,

} BallStatus;

@interface ViewController () {

    BallStatus status;

    CGPoint startPoint;

    CGPoint releasePoint;

    float speed;

    CADisplayLink *timer;

}

@property (nonatomic, strong) UIView *ball;

@property (nonatomic, strong) UIView *sibaA;

@property (nonatomic, strong) UIView *sibaB;

@property (nonatomic, strong) UIView *banker;

@property (nonatomic, strong) UIView *cup;

@property (nonatomic, strong) NSMutableArray *anchorArray;

@end

@implementation ViewController

@synthesize ball, anchorArray;

@synthesize sibaA, sibaB, banker, cup;

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    self.view.backgroundColor = [UIColor greenColor];

    anchorArray = [[NSMutableArray alloc] init];

    

    // グラウンド

    [self createGround];

    

    // ボール

    [self setUpBall];

    

    // スタート

    [self start];

}

– (void)viewDidDisappear:(BOOL)animated

{

    ball = nil;

    anchorArray = nil;

}

– (void)createGround

{

    // グラウンドを作る

    sibaA = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];

    sibaA.backgroundColor = [UIColor colorWithRed:0 green:0.6 blue:0 alpha:1.0];

    sibaA.center = CGPointMake(160, 340);

    sibaA.layer.cornerRadius = 15.0;

    [self.view addSubview:sibaA];

    

    sibaB = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];

    sibaB.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0 alpha:1.0];

    sibaB.center = CGPointMake(120, 120);

    sibaB.layer.cornerRadius = 15.0;

    [self.view addSubview:sibaB];

    

    banker = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];

    banker.backgroundColor = [UIColor brownColor];

    banker.center = CGPointMake(220, 200);

    banker.layer.cornerRadius = 25.0;

    [self.view addSubview:banker];

    

    cup = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    cup.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];

    cup.center = CGPointMake(280, 50);

    cup.layer.cornerRadius = 20.0;

    cup.layer.transform = CATransform3DMakeRotation(M_PI * 0.2, 1.0, 0, 0);

    cup.layer.zPosition = 100;

    [self.view addSubview:cup];

}

– (void)setUpBall

{

    // ゴルフボールを作る

    ball = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];

    ball.center = CGPointMake(160, 350);

    ball.backgroundColor = [UIColor whiteColor];

    ball.layer.cornerRadius = 10.0;

    ball.layer.zPosition = 200;

    [self.view addSubview:ball];

}

– (void)start

{

    timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateDisp:)];

    [timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

}

– (void)updateDisp:(CADisplayLink*)sender

{

    if (status == BallRelease) {

        float dx = (startPoint.xreleasePoint.x) * speed * 0.001;

        float dy = (startPoint.yreleasePoint.y) * speed * 0.001;

        ball.center = CGPointMake(ball.center.x + dx, ball.center.y + dy);

        

        float groundCondition = [self checkGroundCondition:ball.frame];

        

        // カップに入ったかチェックする

        if (groundCondition < 0) {

            status = BallStop;

            [UIView animateWithDuration:1.0 animations:^{

                ball.center = cup.center;

                ball.transform = CGAffineTransformMakeScale(0.5, 0.5);

            } completion:^(BOOL finished) {

                // クリアエフェクト

                UILabel *clearLabel = [[UILabel alloc] init];

                clearLabel.font = [UIFont boldSystemFontOfSize:50];

                clearLabel.text = @”Clear!”;

                [clearLabel sizeToFit];

                clearLabel.center = CGPointMake(160, –200);

                clearLabel.backgroundColor = [UIColor clearColor];

                [self.view addSubview:clearLabel];

                

                [UIView animateWithDuration:0.5 animations:^{

                    clearLabel.center = self.view.center;

                }];

                

            }];

        }

        

        speed = speed – groundCondition;

        if (speed < 0) {

            status = BallStop;

            startPoint = ball.center;

        }

    }

}

– (float)checkGroundCondition:(CGRect)rect

{

    // 地面によってスピードの減衰を変える

    if (CGRectIntersectsRect(rect, sibaA.frame)) {

        return 2.0;

    }

    else if (CGRectIntersectsRect(rect, sibaB.frame)) {

        return 3.0;

    }

    else if (CGRectIntersectsRect(rect, banker.frame)) {

        return 10.0;

    }

    else if (CGRectIntersectsRect(rect, cup.frame)) {

        return1.0;

    }

    return 1.0;

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    UITouch *t = [touches anyObject];

    CGPoint p = [t locationInView:self.view];

    if (CGRectContainsPoint(ball.frame, p)) {

        startPoint = ball.center;

    }

}

– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

    // 引っ張るとアンカーがのびるように

    UITouch *t = [touches anyObject];

    CGPoint p = [t locationInView:self.view];

    

    for (UIView *v in self.anchorArray) {

        [v removeFromSuperview];

    }

    

    float dx = startPoint.x – p.x;

    float dy = startPoint.y – p.y;

    int len = hypotf(dx, dy);

    for (int i=10; i<len; i+=10) {

        UIView *anchorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];

        anchorView.layer.borderColor = [UIColor colorWithWhite:0.7 alpha:0.6].CGColor;

        anchorView.layer.borderWidth = 2.0;

        anchorView.layer.cornerRadius = 5.0;

        anchorView.center = CGPointMake(startPoint.x – i * (dx / len), startPoint.y – i * (dy / len));

        [self.view addSubview:anchorView];

        [self.anchorArray addObject:anchorView];

    }

}

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

    // 離すとボールを飛ばす

    UITouch *t = [touches anyObject];

    CGPoint p = [t locationInView:self.view];

    

    releasePoint = p;

    speed = hypotf(startPoint.x – p.x, startPoint.y – p.y);

    status = BallRelease;

    

    for (UIView *v in self.anchorArray) {

        [v removeFromSuperview];

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end