ネコのしっぽをふりふりする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 = 200 – SPACE_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