iPhoneくねっとボーリング

くねくねしているピンを何個はじき飛ばせるか!というIPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SpriteKit;

@interface BowlingScene : SKScene <SKPhysicsContactDelegate>

@property (nonatomic) uint8_t move;

@property (nonatomic, weak) SKNode *selected;

@property (nonatomic) CGPoint start;

@end

@implementation BowlingScene

– (void)didMoveToView:(SKView *)view

{

    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

    self.physicsBody.categoryBitMask = 0x1 << 3;

    self.physicsWorld.gravity = CGVectorMake(0, 0);

    self.physicsWorld.contactDelegate = self;

    

    [self createLabel];

    [self createPin];

    [self createBall];

}

– (void)createPin

{

    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(-10, –4, 20, 8)];

    

    SKNode *tmp;

    

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

        float x = CGRectGetMidX(self.frame);

        float y = CGRectGetMaxY(self.frame) – i * 1530;

        

        SKShapeNode *p = [SKShapeNode node];

        p.name = (i == 0) ? @”topPin” : @”pin”;

        p.position = CGPointMake(x, y);

        p.path = path.CGPath;

        p.fillColor = [SKColor clearColor];

        p.strokeColor = [SKColor yellowColor];

        p.lineWidth = 3;

        [self addChild:p];

        

        p.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(20, 8)];

        p.physicsBody.density = 0.05;

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

        p.physicsBody.contactTestBitMask = 0x1 << 1;

        

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

        [self.physicsWorld addJoint:sl];

        

        if (tmp) {

            SKPhysicsJointSpring *spring = [SKPhysicsJointSpring jointWithBodyA:p.physicsBody bodyB:tmp.physicsBody anchorA:p.position anchorB:tmp.position];

            spring.frequency = 0.7;

            spring.damping = 1.0;

            [self.physicsWorld addJoint:spring];

        }

        

        tmp = p;

    }

}

– (void)createBall

{

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

    SKShapeNode *ball = [SKShapeNode node];

    ball.name = @”ball”;

    ball.path = path.CGPath;

    ball.position = CGPointMake(CGRectGetMidX(self.frame), 60);

    ball.lineWidth = 8;

    [self addChild:ball];

}

– (void)createLabel {

    SKLabelNode *score = [SKLabelNode node];

    score.name = @”score”;

    score.text = @”00″;

    score.fontColor = [[SKColor whiteColor] colorWithAlphaComponent:0.2];

    score.fontSize = 200;

    score.position = CGPointMake(160, 300);

    [self addChild:score];

}

– (void)update:(NSTimeInterval)currentTime

{

    SKNode *pin = [self childNodeWithName:@”topPin”];

    

    if (self.move == 1) {

        pin.physicsBody.velocity = CGVectorMake(60, 0);

        if (pin.position.x > 300) self.move = 0;

    } else {

        pin.physicsBody.velocity = CGVectorMake(-60, 0);

        if (pin.position.x < 20) self.move = 1;

    }

}

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

{

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

    SKNode *hit = [self nodeAtPoint:p];

    if ([hit.name isEqual:@”ball”]) {

        self.selected = hit;

        self.start = p;

    }

}

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

{

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

    self.selected.position = p;

    

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

    if (!guide) {

        guide = [SKShapeNode node];

        guide.name = @”guide”;

        guide.strokeColor = [SKColor purpleColor];

        guide.lineWidth = 2;

        [self addChild:guide];

    }

    

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.start radius:4 startAngle:0 endAngle:2.0*M_PI clockwise:YES];

    [path moveToPoint:self.start];

    [path addLineToPoint:p];

    guide.path = path.CGPath;

}

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

{

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

    CGVector v = CGVectorMake(self.start.x – p.x, self.start.y – p.y);

//    v = CGVectorMake(10.0 * v.dx, 10.0 * v.dy);

    

    // ball physicsBody

    self.selected.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13];

    self.selected.physicsBody.density = 10.0;

    self.selected.physicsBody.categoryBitMask = 0x1 << 2;

    self.selected.physicsBody.contactTestBitMask = 0x1 << 1;

    

    [self.selected.physicsBody applyImpulse:v];

    self.selected = nil;

}

– (void)didBeginContact:(SKPhysicsContact *)contact

{

    if ([contact.bodyA.node.name isEqualToString:@”pin”]) {

        [contact.bodyA.joints enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

            [self.physicsWorld removeJoint:obj];

        }];

        

        SKLabelNode *score = (SKLabelNode *)[self childNodeWithName:@”score”];

        score.text = [NSString stringWithFormat:@”%d”, [score.text intValue] + 1];

    }

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

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

    [self.view addSubview:spriteView];

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

    [spriteView presentScene:scene];

}

@end