iPhoneダウンヒル

指で描いた線の上をチャリンコが駆け下りていくようなiPhoneアプリを描いてみます。

動作イメージ

XcodeからiOS7 iPhone Simulatorで動かすとこんな感じになります。

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface BicycleLine : SKScene

@property BOOL contentCreated;

@property UIBezierPath *path;

@end

@implementation BicycleLine

– (void)didMoveToView:(SKView *)view

{

    if (!self.contentCreated) {

        [self createSceneContents];

        self.contentCreated = YES;

    }

}

– (void)createSceneContents

{

    self.backgroundColor = [SKColor purpleColor];

    

    [self createBicycleNode];

    

    [self updateGround];

    

    SKLabelNode *start = [SKLabelNode node];

    start.name = @”startBtn”;

    start.text = @”Go!”;

    start.position = CGPointMake(280, 20);

    [self addChild:start];

}

– (void)createBicycleNode

{

    SKSpriteNode *bicycleFrame = [SKSpriteNode spriteNodeWithImageNamed:@”bicycleframe”];

    bicycleFrame.position = CGPointMake(260, 450);

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

    bicycleFrame.physicsBody.linearDamping = 5.0; // move slow

    bicycleFrame.physicsBody.dynamic = NO;

    bicycleFrame.name = @”bicycle”;

    [self addChild:bicycleFrame];

    

    CGPoint center[] = {

        CGPointMake(bicycleFrame.position.x – bicycleFrame.size.width/2.0,

                    bicycleFrame.position.y – bicycleFrame.size.height/2.0),

        CGPointMake(bicycleFrame.position.x + bicycleFrame.size.width/2.0,

                    bicycleFrame.position.y – bicycleFrame.size.height/2.0)

    };

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

        SKSpriteNode *tire = [SKSpriteNode spriteNodeWithImageNamed:@”tire”];

        tire.position = CGPointMake(center[i].x, center[i].y);

        tire.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:tire.size.width/2.0];

        [self addChild:tire];

        

        SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:bicycleFrame.physicsBody bodyB:tire.physicsBody anchor:center[i]];

        [self.physicsWorld addJoint:pin];

    }

}

– (void)updateGround

{

    SKShapeNode *ground = (SKShapeNode*)[self childNodeWithName:@”ground”];

    if (!ground) {

        ground = [SKShapeNode node];

        ground.name = @”ground”;

        ground.physicsBody.dynamic = NO;

        [self addChild:ground];

    }

    if (!self.path) {

        self.path = [UIBezierPath bezierPath];

    }

    ground.path = self.path.CGPath;

}

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

{

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

    if ([[self childNodeWithName:@”startBtn”] containsPoint:p]) {

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

        node.physicsBody.dynamic = YES;

        SKShapeNode *ground = (SKShapeNode*)[self childNodeWithName:@”ground”];

        ground.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:self.path.CGPath];

    } else {

        self.path = [UIBezierPath bezierPath];

        [self.path moveToPoint:p];

    }

}

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

{

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

    [self.path addLineToPoint:p];

    [self updateGround];

}

– (void)didSimulatePhysics

{

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

    if (node.position.x < 0 || node.position.x > 320 || node.position.y < 0) {

        [node removeFromParent];

        [self createBicycleNode];

        self.path = nil;

        [self updateGround];

    }

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

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

    [self.view addSubview:spriteView];

    

    SKScene *scene = [[BicycleLine alloc] initWithSize:self.view.bounds.size];

    [spriteView presentScene:scene];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end