iPhone遊星歯車

遊星歯車というのがかっこ良かったので、iPhoneアプリのサンプルコードを描いてみました。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface GearScene : SKScene

@end

typedef enum : int8_t {

    CollideTypeTeeth = 0x1 << 1,

    CollideTypeGear = 0x1 << 2,

    CollideTypeBase = 0x1 << 3,

    CollideTypeNone = 0x1 << 4,

} CollideType;

@implementation GearScene

– (void)didMoveToView:(SKView *)view

{

    [self createBaseBody];

    [self createGear];

}

– (void)createBaseBody

{

    SKSpriteNode *base = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:self.frame.size];

    base.name = @”base”;

    base.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    [self addChild:base];

    

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

    base.physicsBody.categoryBitMask = CollideTypeBase;

    base.physicsBody.collisionBitMask = CollideTypeBase;

    base.physicsBody.dynamic = NO;

}

– (void)createGear

{

    CGPoint o = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    

    // sun gear

    UIBezierPath *sunpath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, –50, 100, 100)];

    SKShapeNode *sun = [SKShapeNode node];

    sun.name = @”sun”;

    sun.position = o;

    sun.path = sunpath.CGPath;

    [self addChild:sun];

    

    sun.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:50];

    sun.physicsBody.categoryBitMask = CollideTypeGear;

    sun.physicsBody.collisionBitMask = CollideTypeGear | CollideTypeTeeth;

    sun.physicsBody.restitution = 0;

    [self createTeeth:sun radius:53 number:20];

    

    // planet

    NSMutableArray *planets = [NSMutableArray array];

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

        float angle = 2.0 * M_PI / 3.0 * i;

        float x = 75 * cos(angle) + o.x;

        float y = 75 * sin(angle) + o.y;

        float r = 16;

        UIBezierPath *planetpath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-r, -r, r*2.0, r*2.0)];

        SKShapeNode *planet = [SKShapeNode node];

        planet.position = CGPointMake(x, y);

        planet.path = planetpath.CGPath;

        [self addChild:planet];

        

        planet.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:r];

        planet.physicsBody.categoryBitMask = CollideTypeGear;

        planet.physicsBody.collisionBitMask = CollideTypeGear | CollideTypeTeeth;

        planet.physicsBody.restitution = 0;

        [self createTeeth:planet radius:r+3 number:8];

        

        [planets addObject:planet];

    }

    

    

    // outer gear

    UIBezierPath *outerpath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-100, –100, 200, 200)];

    SKShapeNode *outer = [SKShapeNode node];

    outer.position = o;

    outer.path = outerpath.CGPath;

    [self addChild:outer];

    

    outer.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:100];

    outer.physicsBody.categoryBitMask = CollideTypeNone;

    outer.physicsBody.collisionBitMask = CollideTypeNone;

    outer.physicsBody.restitution = 0;

    [self createTeeth:outer radius:97 number:40];

    

    

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

    NSArray *gears = @[sun, planets[0], planets[1], planets[2], outer];

    for (SKNode *node in gears) {

        SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:node.physicsBody bodyB:base.physicsBody anchor:node.position];

        [self.physicsWorld addJoint:pin];

    }

    

}

– (void)createTeeth:(SKNode*)gear radius:(float)r number:(int)number

{

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

        float angle = 2.0 * M_PI / number * i;

        float x = cos(angle) * r + gear.position.x;

        float y = sin(angle) * r + gear.position.y;

        SKSpriteNode *node = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(4, 8)];

        node.position = CGPointMake(x, y);

        node.zRotation = angle + M_PI / 2.0;

        [self addChild:node];

        

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

        node.physicsBody.categoryBitMask = CollideTypeTeeth;

        node.physicsBody.collisionBitMask = CollideTypeGear | CollideTypeTeeth;

        

        SKPhysicsJointFixed *fixed = [SKPhysicsJointFixed jointWithBodyA:gear.physicsBody bodyB:node.physicsBody anchor:node.position];

        [self.physicsWorld addJoint:fixed];

    }

}

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

{

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

    [sun.physicsBody applyTorque:0.1];

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

 

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

    [self.view addSubview:spriteView];

    

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

    [spriteView presentScene:scene];

}

@end