iPhoneXYギア

X軸Y軸の2つの軸をギアで動かすiPhoneアプリのサンプルコードを描いてみます。

@import SpriteKit;

#import “ViewController.h”

@interface GearScene : SKScene

@property (nonatomic) BOOL moveV;

@property (nonatomic) BOOL moveH;

@end

@implementation GearScene

– (void)didMoveToView:(SKView *)view

{

    self.backgroundColor = [SKColor yellowColor];

    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(-300, 0, CGRectGetMaxX(self.frame) + 600, CGRectGetMaxY(self.frame))];

    [self createVerticalGear];

    [self createHorizontalGear];

}

– (void)createVerticalGear

{

    NSMutableArray *bodies = [NSMutableArray array];

    

    SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[SKColor darkGrayColor] size:CGSizeMake(20, 300)];

    bar.name = @”vBar”;

    bar.position = CGPointMake(76.5, CGRectGetMidX(self.frame) + 20);

    [self addChild:bar];

    [bodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:bar.size center:bar.position]];

    

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

        SKSpriteNode *t = [SKSpriteNode spriteNodeWithColor:[SKColor darkGrayColor] size:CGSizeMake(30, 5)];

        t.position = CGPointMake(0, i * 207.5 * 20);

        [bar addChild:t];

        [bodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:t.size center:t.position]];

    }

    

    bar.physicsBody = [SKPhysicsBody bodyWithBodies:bodies];

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

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

    bar.physicsBody.linearDamping = 1.0;

    

    SKPhysicsJointSliding *sl = [SKPhysicsJointSliding jointWithBodyA:bar.physicsBody bodyB:self.physicsBody anchor:bar.position axis:CGVectorMake(0, 1)];

    sl.shouldEnableLimits = YES;

    sl.upperDistanceLimit = 100;

    sl.lowerDistanceLimit = –100;

    [self.physicsWorld addJoint:sl];

    

    SKNode *gear = [self createGear:bar.physicsBody.categoryBitMask];

    gear.position = CGPointMake(40, 160);

    gear.name = @”gearV”;

    

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:gear.physicsBody bodyB:self.physicsBody anchor:gear.position];

    pin.frictionTorque = 0.8;

    [self.physicsWorld addJoint:pin];

}

– (void)createHorizontalGear

{

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

    

    NSMutableArray *bodies = [NSMutableArray array];

    

    SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[SKColor darkGrayColor] size:CGSizeMake(300, 20)];

    bar.name = @”hBar”;

    bar.position = CGPointMake(0, CGRectGetMaxY(vBar.frame) – 50);

    [self addChild:bar];

    [bodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:bar.size center:bar.position]];

    

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

        SKSpriteNode *t = [SKSpriteNode spriteNodeWithColor:[SKColor darkGrayColor] size:CGSizeMake(5, 30)];

        t.position = CGPointMake(i * 207.5 * 20, 0);

        [bar addChild:t];

        [bodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:t.size center:t.position]];

    }

    

    bar.physicsBody = [SKPhysicsBody bodyWithBodies:bodies];

    bar.physicsBody.affectedByGravity = NO;

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

    bar.physicsBody.collisionBitMask = 0x1 << 2 | 0x1 << 5;

    bar.physicsBody.allowsRotation = NO;

    bar.physicsBody.linearDamping = 1.0;

    

    SKNode *gear = [self createGear:bar.physicsBody.categoryBitMask];

    gear.position = CGPointMake(40, CGRectGetMaxY(vBar.frame) + 135);

    gear.name = @”gearH”;

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:gear.physicsBody bodyB:self.physicsBody anchor:gear.position];

    pin.frictionTorque = 0.8;

    [self.physicsWorld addJoint:pin];

}

– (SKNode *)createGear:(uint32_t)mask

{

    SKNode *gear = [SKNode node];

    [self addChild:gear];

    gear.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:15];

    

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

        SKSpriteNode *t = [SKSpriteNode spriteNodeWithColor:[SKColor darkGrayColor] size:CGSizeMake(48, 5)];

        t.position = gear.position;

        t.zRotation = i * M_PI / 4.0;

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

        t.physicsBody.categoryBitMask = 0x1 << 5;

        t.physicsBody.collisionBitMask = mask;

        [self addChild:t];

        

        SKPhysicsJointFixed *f = [SKPhysicsJointFixed jointWithBodyA:gear.physicsBody bodyB:t.physicsBody anchor:t.position];

        [self.physicsWorld addJoint:f];

    }

    

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointZero radius:15 startAngle:0 endAngle:2.0*M_PI clockwise:NO];

    SKShapeNode *circle = [SKShapeNode node];

    circle.fillColor = [SKColor lightGrayColor];

    circle.lineWidth = 5;

    circle.strokeColor = [SKColor darkGrayColor];

    circle.path = path.CGPath;

    [gear addChild:circle];

    

    return gear;

}

– (void)update:(NSTimeInterval)currentTime

{

    SKNode *barV = [self childNodeWithName:@”vBar”];

    SKNode *barH = [self childNodeWithName:@”hBar”];

    barH.position = CGPointMake(barH.position.x, CGRectGetMaxY(barV.frame));

    

    if (self.moveV) {

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

        [gearV.physicsBody applyTorque:2.5];

    } else if (self.moveH) {

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

        [gearH.physicsBody applyTorque:1];

    }

}

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

{

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

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

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

    if ([gearV containsPoint:p]) {

        self.moveV = YES;

    } else if ([gearH containsPoint:p])  {

        self.moveH = YES;

    }

}

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

{

    self.moveV = NO;

    self.moveH = NO;

}

@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:CGSizeMake(320, 568)];

    [spriteView presentScene:scene];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end