iPhone吊り玉

上から吊った玉の中に、カラフルな四角をいれてブラブラさせるiPhoneアプリのサンプルコードを描いてみます。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface BallScene : SKScene

@end

@implementation BallScene

– (void)didMoveToView:(SKView *)view

{

    self.backgroundColor = [self color:0];

    [self createBalls];

}

– (void)createBalls

{

    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-30, –30, 60, 60)];

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

        SKShapeNode *node = [SKShapeNode node];

        node.name = @”ball”;

        node.position = CGPointMake(i * 80 + 40, 200 + i * 50);

        node.fillColor = [SKColor clearColor];

        node.lineWidth = 5;

        node.strokeColor = [SKColor whiteColor];

        node.path = path.CGPath;

        [self addChild:node];

        

        NSMutableArray *bodies = [NSMutableArray array];

        int cnt = 90;

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

            float x = 30 * cos(2.0*M_PI/cnt * i);

            float y = 30 * sin(2.0*M_PI/cnt * i);

            [bodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1, 1) center:CGPointMake(x, y)]];

        }

        node.physicsBody = [SKPhysicsBody bodyWithBodies:bodies];

        node.physicsBody.friction = 0;

        

        SKSpriteNode *small = [SKSpriteNode spriteNodeWithColor:[self color:i + 1] size:CGSizeMake(20, 20)];

        small.position = node.position;

        [self addChild:small];

        small.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:15];

        small.physicsBody.density = 0.01;

        

        

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

        top.position = CGPointMake(node.position.x, CGRectGetMaxY(self.frame) – 50);

        [self addChild:top];

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

        top.physicsBody.dynamic = NO;

        

        SKPhysicsJointLimit *joint = [SKPhysicsJointLimit jointWithBodyA:node.physicsBody bodyB:top.physicsBody anchorA:CGPointMake(node.position.x, CGRectGetMaxY(node.frame) – 2) anchorB:top.position];

        [self.physicsWorld addJoint:joint];

    }

}

– (void)didSimulatePhysics

{

    SKNode *node = [self childNodeWithName:@”line”];

    [node removeFromParent];

    

    SKShapeNode *lineNode = [SKShapeNode node];

    lineNode.name = @”line”;

    lineNode.strokeColor = [SKColor whiteColor];

    

    UIBezierPath *path = [UIBezierPath bezierPath];

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

        [node.physicsBody.joints enumerateObjectsUsingBlock:^(SKPhysicsJoint *j, NSUInteger idx, BOOL *stop) {

            [path moveToPoint:CGPointMake(j.bodyA.node.position.x, j.bodyA.node.position.y + 29)];

            [path addLineToPoint:j.bodyB.node.position];

        }];

    }];

    

    lineNode.path = path.CGPath;

    [self addChild:lineNode];

}

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

{

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

    

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

        if ([node containsPoint:p]) {

            [node.physicsBody applyImpulse:CGVectorMake(1, 0)];

        }

    }];

}

#define ColorHex(rgbValue) [SKColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

– (SKColor*)color:(int)i

{

    switch (i) {

        case 0:

            return ColorHex(0xAFD6B6);

        case 1:

            return ColorHex(0x8EC275);

        case 2:

            return ColorHex(0xF3F1E2);

        case 3:

            return ColorHex(0xFCDD76);

        case 4:

            return ColorHex(0xF6856F);

        default:

            break;

    }

    return nil;

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

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

    [self.view addSubview:spriteView];

    

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

    [spriteView presentScene:scene];

}

@end