iPhone縦横回転

ボールを当ててZ軸回転させる板、とY軸回転のViewをシンクロさせて遊ぶiPhoneアプリのサンプルコードを描いてみます。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface WheelScene : SKScene

@end

@implementation WheelScene

– (void)didMoveToView:(SKView *)view

{

    [self createSceneContents];

}

– (void)createSceneContents

{

    [self createWheel];

}

– (void)createWheel

{

    SKSpriteNode *board = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(80, 80)];

    board.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 100);

    [self addChild:board];

    board.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:board.size];

    board.physicsBody.dynamic = NO;

    board.physicsBody.categoryBitMask = 0x1 << 4;

    board.physicsBody.collisionBitMask = 0x1 << 4;

    

    SKNode *preBar = nil;

    float angle = 0;

    SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[SKColor lightGrayColor] size:CGSizeMake(80, 10)];

    bar.name = @”bar”;

    bar.position = board.position;

    bar.zRotation = angle;

    [self addChild:bar];

    

    bar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bar.size];

    bar.physicsBody.categoryBitMask = 0x1 << 2;

    bar.physicsBody.collisionBitMask = 0x1 << 1;

    bar.physicsBody.angularDamping = 1.0;

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:board.physicsBody bodyB:bar.physicsBody anchor:bar.position];

    [self.physicsWorld addJoint:pin];

    

    if (preBar) {

        SKPhysicsJointFixed *fix = [SKPhysicsJointFixed jointWithBodyA:preBar.physicsBody bodyB:bar.physicsBody anchor:bar.position];

        [self.physicsWorld addJoint:fix];

    }

    preBar = bar;

    

}

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

{

    CGPoint p = [[touches anyObject] locationInNode:self];

    UIBezierPath *ballPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-10, –10, 20, 20)];

    SKShapeNode *ball = [SKShapeNode node];

    ball.name = @”ball”;

    ball.position = p;

    ball.path = ballPath.CGPath;

    ball.fillColor = [SKColor whiteColor];

    [self addChild:ball];

}

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

{

    CGPoint p = [[touches anyObject] locationInNode:self];

    

    SKNode *ball = [self childNodeWithName:@”ball”];

    ball.name = @”released”;

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    ball.physicsBody.categoryBitMask = 0x1 << 1;

    ball.physicsBody.collisionBitMask = 0x1 << 2;

    ball.physicsBody.density = 0.3;

    float dx = ball.position.x – p.x;

    float dy = ball.position.y – p.y;

    CGVector v = CGVectorMake(dx * 10.0, dy * 10.0);

    [ball.physicsBody applyForce:v];

}

– (void)didSimulatePhysics

{

    SKNode *bar0 = [self childNodeWithName:@”bar”];

    [[NSNotificationCenter defaultCenter] postNotificationName:@”update angle”

                                                        object:@(bar0.zRotation)];

    

    [self enumerateChildNodesWithName:@”released” usingBlock:^(SKNode *node, BOOL *stop) {

        if (node.position.y < 0) {

            [node removeFromParent];

        }

    }];

}

@end

@interface ViewController ()

@property (nonatomic) float angel;

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    [self createNumbers];

    

    [self createWheelScene];

    

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateAngle:) name:@”update angle” object:nil];

}

– (void)dealloc

{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

– (void)createNumbers

{

    self.angel = 0;

    for (int i=0; i<20; i++) {

        float x = 160;

        float y = 80;

        UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];

        l.tag = i + 1;

        l.center = CGPointMake(x, y);

        l.font = [UIFont systemFontOfSize:30];

        l.text = [@(i) stringValue];

        l.textAlignment = NSTextAlignmentCenter;

        l.backgroundColor = [UIColor grayColor];

        [self.view addSubview:l];

        

        float r = 150;

        float angle = (M_PI / 10.0) * (float)i;

        CATransform3D t = CATransform3DIdentity;

        t.m34 = 1.0 / –850;

        t = CATransform3DRotate(t, angle, 0, 1, 0);

        l.layer.transform = CATransform3DTranslate(t, 0, 0, r);

    }

}

– (void)createWheelScene

{

    SKView *spriteView = [[SKView alloc] initWithFrame:CGRectMake(0, 100, CGRectGetMaxX(self.view.frame), CGRectGetMaxY(self.view.frame) – 100)];

    [self.view addSubview:spriteView];

    

    SKScene *scene = [[WheelScene alloc] initWithSize:spriteView.frame.size];

    [spriteView presentScene:scene];

}

– (void)setAngel:(float)angle

{

    _angel = angle;

    for (int i=0; i<20; i++) {

        UIView *l = [self.view viewWithTag:i + 1];

        float r = 150;

        float a = (M_PI / 10.0) * (float)i + angle;

        CATransform3D t = CATransform3DIdentity;

        t.m34 = 1.0 / –850;

        t = CATransform3DRotate(t, a, 0, 1, 0);

        l.layer.transform = CATransform3DTranslate(t, 0, 0, r);

    }

}

– (void)updateAngle:(NSNotification *)sender

{

    if ([sender.name isEqualToString:@”update angle”]) {

        float angle = [sender.object floatValue];

        self.angel = angle;

    }

}

@end