iPhoneジャンプパネル

棒の端っこにジャンプするパネルをつけてボールを上に飛ばしていくiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SpriteKit;

@interface ViewController () <SKPhysicsContactDelegate>

@property (nonatomic) SKScene *scene;

@property (nonatomic) BOOL jumping;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createBar];

    [self createBall];

}

– (void)setupScene {

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

    SKScene *s = [SKScene sceneWithSize:sv.frame.size];

    s.physicsWorld.contactDelegate = self;

    s.backgroundColor = [UIColor colorWithHue:0 saturation:0.1 brightness:1 alpha:1];

    [sv presentScene:s];

    

    [self.view addSubview:sv];

    self.scene = s;

}

– (void)createBar {

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

        SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[UIColor brownColor] size:CGSizeMake(CGRectGetMaxX(self.view.bounds) * 0.7, 10)];

        bar.position = CGPointMake(CGRectGetMidX(self.view.bounds) + ((i%2 == 0) ? 50 : –50), i * 80 + 20);

        bar.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bar.frame.size];

        bar.physicsBody.dynamic = NO;

        [self.scene addChild:bar];

        

        SKSpriteNode *jumpPanel = [SKSpriteNode spriteNodeWithColor:[UIColor grayColor] size:CGSizeMake(40, 20)];

        jumpPanel.name = [NSString stringWithFormat:@”jump %d”, i];

        jumpPanel.anchorPoint = CGPointMake((i%2) ? 1 : 0, 1);

        jumpPanel.position = CGPointMake((i%2) ? CGRectGetMinX(bar.frame) + 40 : CGRectGetMaxX(bar.frame) – 40, bar.position.y + 5.01);

        jumpPanel.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:jumpPanel.frame.size center:CGPointMake((i%2) ? –20 : 20, –10)];

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

        jumpPanel.physicsBody.contactTestBitMask = 0x1 << 2;

        

        [self.scene addChild:jumpPanel];

        

        SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:jumpPanel.physicsBody bodyB:bar.physicsBody anchor:jumpPanel.position];

        if (i % 2 == 0) {

            pin.lowerAngleLimit = –0.3;

            pin.upperAngleLimit = 0;

        } else {

            pin.lowerAngleLimit = 0;

            pin.upperAngleLimit = 0.3;

        }

        pin.shouldEnableLimits = YES;

        [self.scene.physicsWorld addJoint:pin];

    }

}

– (void)createBall {

    SKShapeNode *ball = [SKShapeNode shapeNodeWithCircleOfRadius:10];

    ball.name = @”ball”;

    ball.fillColor = [UIColor redColor];

    ball.position = CGPointMake(CGRectGetMidX(self.view.bounds), 50);

    [self.scene addChild:ball];

    

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    ball.physicsBody.density = 3.0;

    ball.physicsBody.categoryBitMask = 0x1 << 2;

    ball.physicsBody.friction = 0;

}

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

{

    SKNode *ball = [self.scene childNodeWithName:@”ball”];

    [ball.physicsBody applyForce:CGVectorMake(200, 0)];

    

}

– (void)didBeginContact:(SKPhysicsContact *)contact {

    if (self.jumping) {

        return;

    }

    self.jumping = YES;

    

    SKPhysicsBody *jumppanel;

    SKPhysicsBody *ball;

    if ([contact.bodyA.node.name hasPrefix:@”jump”]) {

        jumppanel = contact.bodyA;

        ball = contact.bodyB;

    } else if ([contact.bodyB.node.name hasPrefix:@”jump”]) {

        jumppanel = contact.bodyB;

        ball = contact.bodyA;

    }

    

    if (jumppanel != nil) {

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            int num = [[jumppanel.node.name componentsSeparatedByString:@” “][1] intValue];

            if (num % 2 == 0) {

                [ball applyImpulse:CGVectorMake(-25, 30)];

                [jumppanel applyImpulse:CGVectorMake(0, –5) atPoint:CGPointMake(10, 0)];

            } else {

                [ball applyImpulse:CGVectorMake(25, 30)];

                [jumppanel applyImpulse:CGVectorMake(0, 5) atPoint:CGPointMake(-10, 0)];

            }

        });

    }

    

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        self.jumping = NO;

    });

}

@end