iPhoneホイール

ホイールを高速回転させるiPhoneアプリのサンプルコードを描いてみます。



#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface WheelScene : SKScene

@end

@implementation WheelScene

– (void)didMoveToView:(SKView *)view

{

    self.backgroundColor = [SKColor colorWithRed:0.8 green:0 blue:0 alpha:1.0];

    [self createShaft];

    [self createWheel];

    [self createSpeedMeter];

}

– (void)createShaft

{

    SKSpriteNode *shaft = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(20, 20)];

    shaft.position = CGPointMake(200, CGRectGetMidY(self.frame));

    shaft.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    shaft.physicsBody.dynamic = NO;

    shaft.zPosition = 10;

    shaft.physicsBody.restitution = 0.1;

    shaft.physicsBody.friction = 0;

    [self addChild:shaft];

}

– (void)createWheel

{

    SKNode *wheel = [SKNode node];

    wheel.name = @”wheel”;

    wheel.position = CGPointMake(200, CGRectGetMidY(self.frame));

    [self addChild:wheel];

    float r = 100;

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

        SKSpriteNode *spoke = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(20, r)];

        spoke.anchorPoint = CGPointMake(0.5, 0.25);

        spoke.zRotation = i * (2.0 * M_PI / 5.0);

        [wheel addChild:spoke];

    }

    

    UIBezierPath *pathA = [UIBezierPath bezierPathWithArcCenter:CGPointZero radius:r startAngle:0 endAngle:2.0*M_PI clockwise:YES];

    SKShapeNode *tire = [SKShapeNode node];

    tire.path = pathA.CGPath;

    tire.strokeColor = [SKColor colorWithWhite:0.2 alpha:1.0];

    tire.lineWidth = 40;

    [wheel addChild:tire];

    

    NSMutableArray *bodies = [NSMutableArray array];

    float dAngle = 2.0 * M_PI / 20.0;

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

        float x = 20 * cos(dAngle * i);

        float y = 20 * sin(dAngle * i);

        SKPhysicsBody *b = [SKPhysicsBody bodyWithCircleOfRadius:1 center:CGPointMake(x, y)];

        b.dynamic = NO;

        [bodies addObject:b];

    }

    wheel.physicsBody = [SKPhysicsBody bodyWithBodies:bodies];

    wheel.physicsBody.friction = 0;

    wheel.physicsBody.restitution = 0;

    

    SKSpriteNode *n = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10, 10)];

    n.position = CGPointMake(wheel.position.x + 100, wheel.position.y);

    n.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    [self addChild:n];

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:n.physicsBody bodyB:wheel.physicsBody anchor:n.position];

    [self.physicsWorld addJoint:pin];

}

– (void)createSpeedMeter

{

    SKSpriteNode *meter = [SKSpriteNode spriteNodeWithColor:[SKColor lightGrayColor] size:CGSizeMake(20, 160)];

    meter.name = @”meter”;

    meter.position = CGPointMake(CGRectGetMaxX(self.frame) – 50, CGRectGetMidY(self.frame));

    [self addChild:meter];

    

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

    bar.name = @”bar”;

    float speed = meter.position.y100;

    bar.userData = [@{@”speed”: @(speed)} mutableCopy];

    bar.position = meter.position;

    [self addChild:bar];

}

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

{

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

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

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

    if ([meter containsPoint:p]) {

        bar.position = CGPointMake(bar.position.x, p.y);

        float speed = p.y100;

        [bar.userData setObject:@(speed) forKey:@”speed”];

    }

    

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

    UIBezierPath *wheelPath = [UIBezierPath bezierPathWithArcCenter:wheel.position radius:100 startAngle:0 endAngle:2.0*M_PI clockwise:YES];

    if ([wheelPath containsPoint:p]) {

        SKSpriteNode *n = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(10, 10)];

        n.position = p;

        n.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

        [self addChild:n];

        SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:n.physicsBody bodyB:wheel.physicsBody anchor:n.position];

        [self.physicsWorld addJoint:pin];

    }

}

– (void)update:(NSTimeInterval)currentTime

{

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

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

    NSNumber *speed = [bar valueForKeyPath:@”userData.speed”];

    wheel.physicsBody.angularVelocity = speed.floatValue;

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidAppear:(BOOL)animated

{

    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];

    [self.view addSubview:spriteView];

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

    [spriteView presentScene:scene];

}

@end