iPhone10まで足し算3つのまとまり

10までの足し算を3つずつの塊を意識しながら答えていくiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController ()

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic, strong) NSMutableArray *questions;

@property (nonatomic, strong) NSArray *currentAB;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createCover];

    [self createNumber];

    [self createThreeEachButton];

    [self setupQuestion];

    [self nextQuestion];

}

– (void)setupScene {

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

    sv.backgroundColor = [UIColor colorWithHue:0.6 saturation:0.5 brightness:0.7 alpha:1];

    sv.scene = [SCNScene scene];

    sv.autoenablesDefaultLighting = YES;

    sv.allowsCameraControl = YES;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)setupQuestion {

    self.questions = [NSMutableArray array];

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

        for (int j=1; i + j <= 10; j++) {

            [self.questions addObject:@[@(i), @(j)]];

        }

    }

    [self.questions sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {

        return (arc4random() % 2) == 0;

    }];

}

– (void)createCover {

    SCNBox *top = [SCNBox boxWithWidth:10 height:2 length:0.1 chamferRadius:0];

    top.firstMaterial.diffuse.contents = [UIColor lightGrayColor];

    SCNNode *topNode = [SCNNode nodeWithGeometry:top];

    topNode.position = SCNVector3Make(0, 3.45, 0);

    [self.sceneView.scene.rootNode addChildNode:topNode];

    

    SCNBox *bottom = [SCNBox boxWithWidth:10 height:5 length:0.1 chamferRadius:0];

    bottom.firstMaterial.diffuse.contents = [UIColor lightGrayColor];

    SCNNode *bottomNode = [SCNNode nodeWithGeometry:bottom];

    bottomNode.position = SCNVector3Make(0, –0.95, 0);

    [self.sceneView.scene.rootNode addChildNode:bottomNode];

    

}

– (void)createNumber {

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

        SCNNode *dial = [self createNumberDial];

        dial.position = SCNVector3Make(i==0 ? 1.5 : –1.5, 2, –1.2);

        dial.name = [NSString stringWithFormat:@”dial%d”, i];

    }

    

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

        SCNBox *bar = [SCNBox boxWithWidth:0.2 height:0.8 length:0.2 chamferRadius:0];

        bar.firstMaterial.diffuse.contents = [UIColor purpleColor];

        SCNNode *barNode = [SCNNode nodeWithGeometry:bar];

        barNode.position = SCNVector3Make(0, 2, 0);

        if (i==0) barNode.rotation = SCNVector4Make(0, 0, 1, M_PI * 0.5);

        [self.sceneView.scene.rootNode addChildNode:barNode];

    }

}

– (SCNNode *)createNumberDial {

    

    float r = 1.2;

    

    SCNNode *dial = [SCNNode node];

    [self.sceneView.scene.rootNode addChildNode:dial];

    

    float dw = M_PI / 5.5;

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

        SCNBox *plate = [SCNBox boxWithWidth:1.2 height:0.8 length:0.1 chamferRadius:0];

        plate.firstMaterial.diffuse.contents = [UIColor purpleColor];

        SCNNode *plateNode = [SCNNode nodeWithGeometry:plate];

        plateNode.pivot = SCNMatrix4MakeTranslation(0, 0, -r);

        plateNode.rotation = SCNVector4Make(1, 0, 0, dw * i);

        

        SCNText *n = [SCNText textWithString:[NSString stringWithFormat:@”%d”, i] extrusionDepth:0.12];

        n.font = [UIFont systemFontOfSize:0.7];

        n.alignmentMode = kCAAlignmentRight;

        n.firstMaterial.diffuse.contents = [UIColor whiteColor];

        SCNNode *nNode = [SCNNode nodeWithGeometry:n];

        SCNVector3 p = SCNVector3Zero;

        CGFloat r = 0;

        [nNode getBoundingSphereCenter:&p radius:&r];

        nNode.pivot = SCNMatrix4MakeTranslation(p.x, p.y, 0);

        [plateNode addChildNode:nNode];

        

        

        [dial addChildNode:plateNode];

    }

    

    return dial;

}

– (void)createThreeEachButton {

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

        float x = (i % 3) * 11;

        float y = 0.5 – (i / 3) * 1 ;

        SCNSphere *btn = [SCNSphere sphereWithRadius:0.4];

        btn.firstMaterial.diffuse.contents = [UIColor lightGrayColor];

        SCNNode *btnNode = [SCNNode nodeWithGeometry:btn];

        btnNode.name = [NSString stringWithFormat:@”btn %d”, i + 1];

        btnNode.position = SCNVector3Make(x, y, 0);

        [self.sceneView.scene.rootNode addChildNode:btnNode];

    }

}

– (void)nextQuestion {

    NSArray *q = [self.questions lastObject];

    [self.questions removeLastObject];

    

    SCNNode *dialR = [self.sceneView.scene.rootNode childNodeWithName:@”dial0″ recursively:NO];

    SCNNode *dialL = [self.sceneView.scene.rootNode childNodeWithName:@”dial1″ recursively:NO];

    

    float dw = M_PI / 5.5;

    int a = [q[0] intValue];

    int b = [q[1] intValue];

    [dialR runAction:[SCNAction rotateToX:dw * (11 – a) y:0 z:0 duration:0.6]];

    [dialL runAction:[SCNAction rotateToX:dw * (11 – b) y:0 z:0 duration:0.6]];

    

    self.currentAB = q;

}

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

    CGPoint p = [[touches anyObject] locationInView:self.sceneView];

    SCNNode *hit = [[self.sceneView hitTest:p options:@{SCNHitTestSortResultsKey : @YES}].firstObject node];

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

        

        int input = [[hit.name componentsSeparatedByString:@” “][1] intValue];

        [self.sceneView.scene.rootNode.childNodes enumerateObjectsUsingBlock:^(SCNNode *b, NSUInteger idx, BOOL *stop) {

            if ([b.name hasPrefix:@”btn”]) {

                int n = [[b.name componentsSeparatedByString:@” “][1] intValue];

                if (n <= input) {

                    b.geometry.firstMaterial.diffuse.contents = [UIColor orangeColor];

                } else {

                    b.geometry.firstMaterial.diffuse.contents = [UIColor lightGrayColor];

                }

            }

        }];

        

        int ans = [self.currentAB[0] intValue] + [self.currentAB[1] intValue];

        if (input == ans) {

            [self nextQuestion];

        }

    }

    

}

@end