羽子板でスカッシュするようなものを作る方法のメモ

(XcodeのiOS6 Simulatorで試しています。)

ポイント

・3次元座標で羽の位置を計算

・表示はx,y を投影、 zは影に(とてもアバウトに)

タッチで羽を壁打ちする

サンプルコード

[Kokinoko.h]

@interface Kokinoko : NSObject

@property (nonatomic, assign) float x;

@property (nonatomic, assign) float y;

@property (nonatomic, assign) float z;

@property (nonatomic, assign) float vx;

@property (nonatomic, assign) float vy;

@property (nonatomic, assign) float vz;

– (void)swing:(CGPoint)point;

– (void)updateWithDuration:(float)duration;

@end

[Kokinoko.m]

@implementation Kokinoko

@synthesize x,y,z, vx,vy,vz;

– (void)swing:(CGPoint)point

{

    float dx = abs(x-point.x);

    float dy = abs(y-point.y);

    

    if (dx < 50 && dy < 50 && z < 50) {

        // 打ち返す

        if (vz == 0) {

            vz = 200;

            vy = –100;

        } else {

            vz = – vz;

            vy = –100;

            vx = (arc4random() % 10) – 5.0;

        }

    }

}

– (void)updateWithDuration:(float)duration

{

    x = x + duration * vx;

    

    vy = vy + 20 * 9.8 * duration;

    y = y + duration * vy;

    

    z = z + duration * vz;

    

    if (z > 200) {

        vz = –vz;

        vy = – 100;

    }

}

@end

[ViewController.m]

#import <QuartzCore/QuartzCore.h>

#import “ViewController.h”

#import “Kokinoko.h”

@interface ViewController () {

    CADisplayLink *timer;

}

@property (nonatomic, strong) Kokinoko *hane;

@property (nonatomic, strong) UIView *haneView;

@property (nonatomic, strong) UIView *haneShadow;

@end

@implementation ViewController

@synthesize hane, haneView;

– (void)viewDidLoad

{

    [super viewDidLoad];

    // 羽子板の羽根を初期化

    self.hane = [[Kokinoko alloc] init];

    hane.x = 100;

    hane.y = 100;

    hane.z = 30.0;

    

    // コート 200 x 200 の正方形で考えてみる

    // 赤いライン

    UIView *line1 = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 320, 10)];

    line1.backgroundColor = [UIColor redColor];

    [self.view addSubview:line1];

    

    

    UIView *line2 = [[UIView alloc] initWithFrame:CGRectMake(0, 200, 320, 10)];

    line2.backgroundColor = [UIColor redColor];

    [self.view addSubview:line2];

    

    

    UIView *floor = [[UIView alloc] initWithFrame:CGRectMake(0, 280, 320, 480)];

    floor.backgroundColor = [UIColor brownColor];

    [self.view addSubview:floor];

    

    //羽の初期化

    self.haneView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];

    self.haneView.layer.cornerRadius = 10.0;

    self.haneView.backgroundColor = [UIColor blackColor];

    self.haneView.layer.zPosition = 100;

    [self.view addSubview:self.haneView];

    

//

    UIView *red = [[UIView alloc] initWithFrame:CGRectMake(-5, 0, 6, –20)];

    red.backgroundColor = [UIColor redColor];

    // 回転中心を変更してから回転する

    CGAffineTransform transform = CGAffineTransformMakeTranslation(-3, –10);

    transform = CGAffineTransformRotate(transform, –0.1 * M_PI);

    transform = CGAffineTransformTranslate(transform,3,10);

    red.transform = transform;

    [self.haneView addSubview:red];

    //

    UIView *yellow = [[UIView alloc] initWithFrame:CGRectMake(7, 0, 6, –20)];

    yellow.backgroundColor = [UIColor yellowColor];

    [self.haneView addSubview:yellow];

    //

    UIView *green = [[UIView alloc] initWithFrame:CGRectMake(20, 0, 6, –20)];

    green.backgroundColor = [UIColor greenColor];

    transform = CGAffineTransformMakeTranslation(-3, –10);

    transform = CGAffineTransformRotate(transform, 0.1 * M_PI);

    transform = CGAffineTransformTranslate(transform,3,10);

    green.transform = transform;

    [self.haneView addSubview:green];

    

    self.haneShadow = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];

    self.haneShadow.layer.cornerRadius = 10.0;

    self.haneShadow.backgroundColor = [UIColor blackColor];

    self.haneShadow.layer.transform = CATransform3DMakeRotation(M_PI * 0.3, 1.0, 0.0, 0.0);

    self.haneShadow.layer.zPosition = 10;

    [self.view addSubview:self.haneShadow];

    

    [self displayHaneAndShadow];

}

– (void)viewDidAppear:(BOOL)animated

{

    [self start];

}

– (void)start

{

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

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

}

– (void)updateDisp:(CADisplayLink*)sender

{

    [self.hane updateWithDuration:sender.duration];

    [self displayHaneAndShadow];

}

– (void)displayHaneAndShadow

{

    //

    float rate = 1.50.004 * hane.z;

    self.haneView.transform = CGAffineTransformMakeScale(rate, rate);

    self.haneView.center = CGPointMake(self.hane.x, self.hane.y);

    // 羽の傾き

    CATransform3D transform = CATransform3DIdentity;

    if (self.hane.vy > 0 && self.hane.vz != 0) {

        transform = CATransform3DRotate(transform, 0.3 * M_PI, 1.0, 0.0, 0);

    } else if (self.hane.vy < 0 && self.hane.vz != 0) {

        transform = CATransform3DRotate(transform, 0.6 * M_PI, 1.0, 0.0, 0);

    }

        

    self.haneView.layer.transform = transform;

    

    //

    self.haneShadow.center = CGPointMake(self.hane.x, 480self.hane.z);

}

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

{

    UITouch *touch = [touches anyObject];

    

    UIView *ita = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 60)];

    ita.backgroundColor = [UIColor blackColor];

    ita.alpha = 0.3;

    

    UIView *grip = [[UIView alloc] initWithFrame:CGRectMake(15, 60, 10, 20)];

    grip.backgroundColor = [UIColor blackColor];

    grip.alpha = 0.3;

    

    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 140)];

    v.center = [touch locationInView:self.view];

    

    [v addSubview:ita];

    [v addSubview:grip];

    

    [self.view addSubview:v];

    

    v.layer.transform = CATransform3DMakeRotation(-M_PI * 0.2, 1.0, 0.0, 0.0);

    

    [UIView animateWithDuration:0.3 animations:^{

        v.layer.transform = CATransform3DMakeRotation(M_PI * 0.5, 1.0, 0.0, 0.0);

    } completion:^(BOOL finished) {

        [v removeFromSuperview];

    }];

    

    [self.hane swing:v.center];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end