iPhoneロボットゴール

二本爪のロボットがボールをゴールまで運ぶようなiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface RoboScene : SKScene

@property BOOL state;

@end

@implementation RoboScene

– (void)didMoveToView:(SKView *)view

{

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

    [self createGoal];

    [self createRobo];

}

– (void)createGoal

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(-20, –40)];

    [path addLineToPoint:CGPointMake(20, –40)];

    [path addLineToPoint:CGPointMake(20, 40)];

    [path addLineToPoint:CGPointMake(-20, 40)];

    

    SKShapeNode *goal = [SKShapeNode node];

    goal.name = @”goal”;

    goal.path = path.CGPath;

    goal.strokeColor = [SKColor whiteColor];

    goal.lineWidth = 4;

    goal.position = CGPointMake(270, CGRectGetMidY(self.frame));

    [self addChild:goal];

    

    goal.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:path.CGPath];

}

– (void)createRobo

{

    SKNode *robo = [SKNode node];

    robo.name = @”robo”;

    robo.position = CGPointMake(50, CGRectGetMidY(self.frame));

    [self addChild:robo];

    

    NSMutableArray *pBodies = [NSMutableArray array];

    

    SKSpriteNode *body = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(20, 50)];

    body.position = CGPointMake(-10, body.position.y);

    [robo addChild:body];

    

    [pBodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:body.size center:body.position]];

    

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

        float x = 20;

        float y = i * 4020;

        SKSpriteNode *arm = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(20, 5)];

        arm.position = CGPointMake(x, y);

        [robo addChild:arm];

        

        [pBodies addObject:[SKPhysicsBody bodyWithRectangleOfSize:arm.size center:arm.position]];

    }

    

    robo.physicsBody = [SKPhysicsBody bodyWithBodies:pBodies];

    robo.physicsBody.angularDamping = 1.0;

    robo.physicsBody.density = 5.0;

    robo.physicsBody.restitution = 0;

}

– (void)createBall:(CGPoint)p

{

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

    SKShapeNode *ball = [SKShapeNode node];

    ball.name = @”ball”;

    ball.position = p;

    ball.path = path.CGPath;

    ball.fillColor = [SKColor orangeColor];

    ball.lineWidth = 0;

    [self addChild:ball];

    

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    ball.physicsBody.restitution = 0;

    ball.physicsBody.linearDamping = 1.0;

}

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

{

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

    [self createBall:p];

}

– (void)update:(NSTimeInterval)currentTime

{

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

    if (ball) {

        switch (self.state) {

            case 0:

                [self rotateA];

                break;

            case 1:

                [self moveA];

                break;

            case 2:

                [self rotateB];

                break;

            case 3:

                [self moveB];

                break;

            case 4:

                [self rotateC];

                break;

            case 5:

                [self moveC];

                break;

            default:

                break;

        }

    }

}

– (void)rotateA

{

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

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

    float angle = atan2f(ball.position.x – robo.position.x, robo.position.y – ball.position.y) – M_PI_2;

    if (fabs(robo.zRotation – angle) < 0.05) {

        self.state = 1;

    } else {

        robo.zRotation += M_PI * 0.01;

    }

}

– (void)moveA

{

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

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

    float l = hypot(ball.position.x – robo.position.x, ball.position.y – robo.position.y);

    if (l < 15) {

        self.state = 2;

        robo.physicsBody.velocity = CGVectorMake(0, 0);

    } else {

        robo.physicsBody.velocity = CGVectorMake(ball.position.x – robo.position.x , ball.position.y – robo.position.y);

    }

}

– (void)rotateB

{

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

    CGPoint o = CGPointMake(160, CGRectGetMidY(self.frame));

    float angle = atan2f(o.x – robo.position.x, robo.position.y – o.y) – M_PI_2;

    if (fabs(robo.zRotation – angle) < 0.05) {

        self.state = 3;

    } else {

        robo.zRotation += M_PI * 0.01;

    }

}

– (void)moveB

{

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

    CGPoint o = CGPointMake(160, CGRectGetMidY(self.frame));

    float l = hypot(o.x – robo.position.x, o.y – robo.position.y);

    if (l < 15) {

        self.state = 4;

        robo.physicsBody.velocity = CGVectorMake(0, 0);

    } else {

        robo.physicsBody.velocity = CGVectorMake(o.x – robo.position.x , o.y – robo.position.y);

    }

}

– (void)rotateC

{

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

    float angle = 0;

    if (fabs(robo.zRotation – angle) < 0.05) {

        self.state = 5;

    } else {

        robo.zRotation += M_PI * 0.01;

    }

}

– (void)moveC

{

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

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

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

    

    float l = hypot(goal.position.x – robo.position.x, goal.position.y – robo.position.y);

    if (l < 30) {

        robo.physicsBody.velocity = CGVectorMake(0, 0);

        ball.name = @””;

        [robo removeFromParent];

        [self createRobo];

        self.state = 0;

    } else {

        robo.physicsBody.velocity = CGVectorMake(goal.position.x – robo.position.x , goal.position.y – robo.position.y);

    }

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

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

    [self.view addSubview:spriteView];

    

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

    [spriteView presentScene:scene];

}

@end