iPhoneねこのしっぽ

ネコのしっぽをふりふりするiPhoneアプリのサンプルを描いてみます。しっぽは、SpriteKitをつかって、小さな四角をJointで繋いだロープを使っています。

動作イメージ
XcodeからiOS7 iPhone Simulatorで動かすとこんな感じになります。

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface RopeScene : SKScene

@property BOOL contentCreated;

@end

#define SPACE_BETWEEN_SEGMENTS 10

@implementation RopeScene

– (void)didMoveToView:(SKView *)view

{

    if (!self.contentCreated) {

        [self createSceneContents];

        self.contentCreated = YES;

    }

}

– (void)createSceneContents

{

    self.backgroundColor = [SKColor lightGrayColor];

    

    SKSpriteNode *catShadow = [SKSpriteNode spriteNodeWithImageNamed:@”cat”];

    catShadow.position = CGPointMake(160, 300);

    [self addChild:catShadow];

    

    

    static const uint32_t boxCategory = 0x1 << 0;

    static const uint32_t ropeCategory = 0x1 << 1;

    

    SKNode *previous;

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

        float x = 160;

        float y = 200SPACE_BETWEEN_SEGMENTS * i;

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

        node.position = CGPointMake(x, y);

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

        node.physicsBody.categoryBitMask = ropeCategory;

        node.physicsBody.collisionBitMask = ropeCategory;

        [self addChild:node];

        

        if (i == 0) {

            SKSpriteNode *box = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(30, 30)];

            box.position = node.position;

            box.zPosition = –1;

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

            box.physicsBody.dynamic = NO;

            box.physicsBody.categoryBitMask = boxCategory;

            box.physicsBody.collisionBitMask = 0x0;

            node.name = @”zero”;

            [self addChild:box];

            

            SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:node.physicsBody bodyB:box.physicsBody anchor:box.position];

            [self.physicsWorld addJoint:joint];

            

        } else {

            SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:node.physicsBody bodyB:previous.physicsBody anchor:CGPointMake(x, y+SPACE_BETWEEN_SEGMENTS/2)];

            [self.physicsWorld addJoint:joint];

        }

        

        if (i == 9) {

            node.name = @”last”;

            // hold joint pin —- bug?

            SKNode *zeroNode = [self childNodeWithName:@”zero”];

            SKPhysicsJointLimit *joint = [SKPhysicsJointLimit jointWithBodyA:zeroNode.physicsBody bodyB:node.physicsBody anchorA:zeroNode.position anchorB:node.position];

            joint.maxLength = SPACE_BETWEEN_SEGMENTS * 10;

            [self.physicsWorld addJoint:joint];

        }

        

        previous = node;

    }

}

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

{

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

    [last.physicsBody applyImpulse:CGVectorMake(5, 0)];

}

– (void)update:(NSTimeInterval)currentTime

{

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

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

    [self.view addSubview:spriteView];

    

    SKScene *scene = [[RopeScene alloc] initWithSize:spriteView.bounds.size];

    [spriteView presentScene:scene];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end