iPhoneフレキシブル箱

縦横の長さを変えられる箱を表示するiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SpriteKit;

@interface ViewController () <SKSceneDelegate>

@property (nonatomic, weak) SKScene *scene;

@property (nonatomic, weak) SKNode *selected;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createFlexBox];

    [self createBall];

}

– (void)setupScene {

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

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

    s.delegate = self;

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

    s.backgroundColor = [UIColor blackColor];

    [sv presentScene:s];

    [self.view addSubview:sv];

    self.scene = s;

}

#define dw CGRectGetMaxX(self.view.bounds) * 0.3

#define dh CGRectGetMaxY(self.view.bounds) * 0.3

#define top [self.scene childNodeWithName:@“t”]

#define bottom [self.scene childNodeWithName:@“b”]

#define right [self.scene childNodeWithName:@“r”]

#define left [self.scene childNodeWithName:@“l”]

#define dottop [self.scene childNodeWithName:@“dot t”]

#define dotbottom [self.scene childNodeWithName:@“dot b”]

#define dotright [self.scene childNodeWithName:@“dot r”]

#define dotleft [self.scene childNodeWithName:@“dot l”]

– (void)createFlexBox {

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

    

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

        SKShapeNode *dot = [SKShapeNode shapeNodeWithCircleOfRadius:8];

        dot.name = [NSString stringWithFormat:@”dot %@”, @[@”t”, @”b”, @”r”, @”l”][i]];

        dot.fillColor = [UIColor whiteColor];

        dot.position = (CGPoint[]){

            CGPointMake(o.x, o.y + dh),

            CGPointMake(o.x, o.ydh),

            CGPointMake(o.x + dw, o.y),

            CGPointMake(o.xdw, o.y)

        }[i];

        dot.zPosition = 2;

        [self.scene addChild:dot];

    }

    

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

        SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:

                             (CGSize[]){CGSizeMake(2.0 * dw, 10), CGSizeMake(10, 2.0 * dh)}[i / 2]];

        bar.position = (CGPoint[]){

            CGPointMake(o.x, o.y + dh),

            CGPointMake(o.x, o.ydh),

            CGPointMake(o.x + dw, o.y),

            CGPointMake(o.xdw, o.y),

        }[i];

        bar.zPosition = 1;

        bar.name = @[@”t”, @”b”, @”r”, @”l”][i];

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

        bar.physicsBody.dynamic = YES;

        bar.physicsBody.restitution = 1.0;

        bar.physicsBody.friction = 0;

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

        bar.physicsBody.collisionBitMask = 0x1;

        bar.physicsBody.allowsRotation = NO;

        [self.scene addChild:bar];

    }

}

– (void)createBall {

    SKShapeNode *ball = [SKShapeNode shapeNodeWithCircleOfRadius:10];

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

    ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10];

    ball.physicsBody.dynamic = YES;

    ball.physicsBody.friction = 0;

    ball.physicsBody.restitution = 0;

    [self.scene addChild:ball];

    

    [ball.physicsBody applyImpulse:CGVectorMake(1, 1)];

}

– (void)update:(NSTimeInterval)currentTime forScene:(SKScene *)scene

{

    float dtop = top.position.ydottop.position.y;

    if(abs(dtop) > 0.1) {

        top.physicsBody.velocity = CGVectorMake(0, -(dtop / abs(dtop)) * sqrt(abs(dtop)) * 100.0);

    } else {

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

    }

    

    float dbottom = bottom.position.ydotbottom.position.y;

    if(abs(dbottom) > 0.1) {

        bottom.physicsBody.velocity = CGVectorMake(0, -(dbottom / abs(dbottom)) * sqrt(abs(dbottom)) * 100.0);

    } else {

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

    }

    

    float dright = right.position.xdotright.position.x;

    if(abs(dright) > 0.1) {

        right.physicsBody.velocity = CGVectorMake(-(dright / abs(dright)) * sqrt(abs(dright)) * 100.0, 0);

    } else {

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

    }

    

    float dleft = left.position.xdotleft.position.x;

    if(abs(dleft) > 0.1) {

        left.physicsBody.velocity = CGVectorMake(-(dleft / abs(dleft)) * sqrt(abs(dleft)) * 100.0, 0);

    } else {

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

    }

    

    top.xScale = (right.position.xleft.position.x)  / (2.0 * dw);

    bottom.xScale = top.xScale;

    right.yScale = (top.position.ybottom.position.y) / (2.0 * dh);

    left.yScale = right.yScale;

}

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

{

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

    SKNode *hit = [self.scene nodeAtPoint:p];

    if ([hit.name hasPrefix:@”dot”]) {

        self.selected = hit;

    }

}

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

{

    if (self.selected) {

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

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

        

        SKNode *pair = self.selected == dottop ? dotbottom

                        : self.selected ==  dotbottom ? dottop

                        : self.selected ==  dotright ? dotleft

                        : dotright;

        

        if (self.selected == dottop || self.selected == dotbottom) {

            self.selected.position = CGPointMake(self.selected.position.x, p.y);

            pair.position = CGPointMake(self.selected.position.x, o.y + (o.y – p.y));

        } else {

            self.selected.position = CGPointMake(p.x, self.selected.position.y);

            pair.position = CGPointMake(o.x + (o.x – p.x), self.selected.position.y);

        }

    }

}

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

{

    self.selected = nil;

}

@end