iPhoneくるくる迷路

くるくる回してボールを迷路の奥まで運ぶiPhoneアプリのサンプルコードを描いてみます。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface MazeScene : SKScene

@property (nonatomic, strong) NSValue *selected;

@end

typedef enum : int8_t {

    CollideTypeBoard = 0x1 << 1,

    CollideTypeWall = 0x1 << 2,

    CollideTypeBall = 0x1 << 3,

} CollideType;

@implementation MazeScene

– (void)didMoveToView:(SKView *)view

{

    [self createSceneContents];

}

– (void)createSceneContents

{

    [self createBackBody];

    [self createBoard];

    [self createWall];

    [self createBall];

}

– (void)createBackBody

{

    SKSpriteNode *back = [SKSpriteNode spriteNodeWithColor:[self color:0] size:self.size];

    back.name = @”back”;

    back.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    [self addChild:back];

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

    back.physicsBody.dynamic = NO;

    back.physicsBody.categoryBitMask = CollideTypeBoard;

    back.physicsBody.collisionBitMask = 0x0;

}

– (void)createBoard

{

    SKSpriteNode *board = [SKSpriteNode spriteNodeWithColor:[self color:3] size:CGSizeMake(280, 280)];

    board.name = @”board”;

    board.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    [self addChild:board];

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

    board.physicsBody.categoryBitMask = CollideTypeBoard;

    board.physicsBody.collisionBitMask = 0x0;

    board.physicsBody.angularDamping = 1.0;

    

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

    SKPhysicsJointPin *pin = [SKPhysicsJointPin jointWithBodyA:board.physicsBody bodyB:back.physicsBody anchor:board.position];

    pin.shouldEnableLimits = YES;

    pin.upperAngleLimit = M_PI;

    pin.lowerAngleLimit = –M_PI;

    [self.physicsWorld addJoint:pin];

}

– (void)createWall

{

    // frame

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

    CGRect rect[] = {

        CGRectMake(o.x140, o.y, 10, 280),

        CGRectMake(o.x + 140, o.y, 10, 280),

        CGRectMake(o.x, o.y140, 280, 10),

        CGRectMake(o.x, o.y + 140, 280, 10),

        CGRectMake(o.x85, o.y85, 100, 100),

        CGRectMake(o.x + 10, o.y80, 40, 80),

        CGRectMake(o.x + 100, o.y75, 80, 80),

        CGRectMake(o.x + 50, o.y+40, 180, 20),

        CGRectMake(o.x + 100, o.y+80, 10, 60),

        CGRectMake(o.x + 40, o.y+80, 10, 60),

        CGRectMake(o.x + 70, o.y+110, 10, 60),

        CGRectMake(o.x20, o.y+80, 10, 60),

        CGRectMake(o.x + 10, o.y+110, 10, 60),

    };

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

        SKSpriteNode *wall = [SKSpriteNode spriteNodeWithColor:[self color:4] size:rect[i].size];

        wall.position = rect[i].origin;

        [self addChild:wall];

        

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

        wall.physicsBody.categoryBitMask = CollideTypeWall;

        wall.physicsBody.collisionBitMask = CollideTypeBall;

        wall.physicsBody.density = 0.1;

        

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

        SKPhysicsJointFixed *fixed = [SKPhysicsJointFixed jointWithBodyA:wall.physicsBody bodyB:board.physicsBody anchor:wall.position];

        [self.physicsWorld addJoint:fixed];

    }

}

– (void)createBall

{

    UIBezierPath *ballPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-10, –10, 20, 20)];

    SKShapeNode *ball = [SKShapeNode node];

    ball.path = ballPath.CGPath;

    ball.position = CGPointMake(100, 300);

    ball.fillColor = [self color:2];

    [self addChild:ball];

    

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:8];

    ball.physicsBody.categoryBitMask = CollideTypeBall;

    ball.physicsBody.collisionBitMask = CollideTypeWall;

    ball.physicsBody.mass = 0.1;

}

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

{

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

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

    if ([board containsPoint:p]) {

        self.selected = [NSValue valueWithCGPoint:p];

    }

}

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

{

    if (self.selected) {

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

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

        if (p.x > [self.selected CGPointValue].x) {

            [board.physicsBody applyTorque:5];

        } else if (p.x < [self.selected CGPointValue].x) {

            [board.physicsBody applyTorque:-5];

        }

    }

}

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

{

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

    board.physicsBody.angularVelocity = 0;

    self.selected = nil;

}

#define ColorHex(rgbValue) [SKColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1]

– (SKColor*)color:(int)i

{

    switch (i) {

        case 0:

            return ColorHex(0x191919);

        case 1:

            return ColorHex(0x696969);

        case 2:

            return ColorHex(0xC3C3C3);

        case 3:

            return ColorHex(0xEBCDB4);

        case 4:

            return ColorHex(0x96734B);

        default:

            break;

    }

    return nil;

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

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

    [self.view addSubview:spriteView];

    

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

    [spriteView presentScene:scene];

}

@end