二分木のノードをタップすると、枝分かれが増えていくような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