iPhone二分木みぎひだり

二分木のノードをタップすると、枝分かれが増えていくようなiPhoneアプリのサンプルコードを描いてみます。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

#import <SpriteKit/SpriteKit.h>

@interface BitLRScene : SKScene

@end

@implementation BitLRScene

– (void)didMoveToView:(SKView *)view

{

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

    [self createSceneContents];

}

– (void)createSceneContents

{

    [self createFirstNode];

}

#define RootSize 40

– (void)createFirstNode

{

    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-RootSize/2.0, –RootSize/2.0, RootSize, RootSize)];

    SKShapeNode *node = [SKShapeNode node];

    node.name = @”1″;

    node.path = path.CGPath;

    node.fillColor = [SKColor orangeColor];

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

    [self addChild:node];

    

    SKLabelNode *l = [SKLabelNode node];

    l.text = node.name;

    l.fontColor = [SKColor whiteColor];

    l.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;

    l.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;

    [node addChild:l];

    

    node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:RootSize/2.0];

    node.physicsBody.dynamic = NO;

    

}

– (void)createLeft:(SKNode*)parent

{

    int num = [parent.name intValue] * 2;

    

    float s = RootSize;

    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-s/2.0, -s/2.0, s, s)];

    SKShapeNode *node = [SKShapeNode node];

    node.name = [@(num) stringValue];

    node.path = path.CGPath;

    node.fillColor = [SKColor orangeColor];

    node.position = CGPointMake(CGRectGetMidX(parent.frame) – 30, CGRectGetMidY(parent.frame) – s * 1.5);

    [self addChild:node];

    

    SKLabelNode *l = [SKLabelNode node];

    l.text = node.name;

    l.fontColor = [SKColor whiteColor];

    l.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;

    l.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;

    [node addChild:l];

    

    node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:s/2.0];

    node.physicsBody.restitution = 1.0;

    SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:parent.physicsBody bodyB:node.physicsBody anchor:parent.position];

    [self.physicsWorld addJoint:joint];

    [node.physicsBody applyImpulse:CGVectorMake(-10, 0)];

}

– (void)createRight:(SKNode*)parent

{

    int num = [parent.name intValue] * 2 + 1;

    

    float s = RootSize;

    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-s/2.0, -s/2.0, s, s)];

    SKShapeNode *node = [SKShapeNode node];

    node.name = [@(num) stringValue];

    node.path = path.CGPath;

    node.fillColor = [SKColor orangeColor];

    node.position = CGPointMake(CGRectGetMidX(parent.frame) + 30, CGRectGetMidY(parent.frame) – s * 1.5);

    [self addChild:node];

    

    SKLabelNode *l = [SKLabelNode node];

    l.text = node.name;

    l.fontColor = [SKColor whiteColor];

    l.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;

    l.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;

    [node addChild:l];

    

    node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:s/2.0];

    node.physicsBody.restitution = 1.0;

    SKPhysicsJointPin *joint = [SKPhysicsJointPin jointWithBodyA:parent.physicsBody bodyB:node.physicsBody anchor:parent.position];

    [self.physicsWorld addJoint:joint];

}

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

{

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

    [self.children enumerateObjectsUsingBlock:^(SKNode *obj, NSUInteger idx, BOOL *stop) {

        if ([obj containsPoint:p] && ![obj.name isEqualToString:@”line”]) {

            [self createLeft:obj];

            [self createRight:obj];

        }

    }];

}

-(void)didSimulatePhysics

{

    SKNode *node = (SKShapeNode *)[self childNodeWithName:@”line”];

    [node removeFromParent];

    UIBezierPath *linePath = [UIBezierPath bezierPath];

    for (SKNode *n in self.children) {

        if ([n.name intValue] > 1) {

            int pNo = [n.name intValue] / 2;

            SKNode *parent = [self childNodeWithName:[@(pNo) stringValue]];

            [linePath moveToPoint:n.position];

            [linePath addLineToPoint:parent.position];

        }

    }

    

    SKShapeNode *line = [SKShapeNode node];

    line.name = @”line”;

    line.path = linePath.CGPath;

    line.zPosition = –1;

    [self addChild:line];

}

@end

@interface ViewController ()

@end

@implementation ViewController

– (void)viewDidAppear:(BOOL)animated

{

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

    [self.view addSubview:spriteView];

    

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

    [spriteView presentScene:scene];

}

@end