iPhoneカエルピョコ

カエルが葉っぱにジャンプするiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController () <SCNSceneRendererDelegate, SCNPhysicsContactDelegate>

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic, strong) NSMutableArray *leaves;

@property (nonatomic, weak) SCNNode *flog;

@property (nonatomic, weak) SCNNode *contactLeaf;

@property (nonatomic) NSTimeInterval start;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createPool];

    [self createLeaf];

    [self createFlog];

    [self createCamera];

}

– (void)setupScene {

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

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

    sv.delegate = self;

    sv.scene = [SCNScene scene];

    sv.scene.physicsWorld.contactDelegate = self;

    sv.autoenablesDefaultLighting = YES;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)createPool {

    SCNBox *pool = [SCNBox boxWithWidth:12 height:1 length:10 chamferRadius:0];

    pool.firstMaterial.diffuse.contents = [UIColor colorWithHue:0.5 saturation:0.6 brightness:1 alpha:0.7];

    SCNNode *poolNode = [SCNNode nodeWithGeometry:pool];

    poolNode.position = SCNVector3Make(0, –0.5, 0);

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

}

– (void)createLeaf {

    self.leaves = [NSMutableArray array];

    

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

        SCNCylinder *leaf = [SCNCylinder cylinderWithRadius:1 height:0.1];

        leaf.firstMaterial.diffuse.contents = [UIColor colorWithHue:0.3 saturation:0.7 brightness:1 alpha:1];

        SCNNode *leafNode = [SCNNode nodeWithGeometry:leaf];

        leafNode.position = SCNVector3Make(0, 0, 4 – i * 2);

        leafNode.physicsBody = [SCNPhysicsBody staticBody];

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

        [self.leaves addObject:leafNode];

    }

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, 10, 20);

    camera.rotation = SCNVector4Make(1, 0, 0, –0.5);

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

}

– (void)createFlog {

    SCNNode *flog = [SCNNode node];

    flog.name = @”flog”;

    flog.position = SCNVector3Make(0, 1, 5.5);

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

    

    SCNBox *body = [SCNBox boxWithWidth:1 height:0.4 length:1.2 chamferRadius:0];

    body.firstMaterial.diffuse.contents = [UIColor colorWithHue:0.25 saturation:0.9 brightness:0.8 alpha:1];

    SCNNode *bodyNode = [SCNNode nodeWithGeometry:body];

    [flog addChildNode:bodyNode];

    

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

        SCNBox *f = [SCNBox boxWithWidth:0.2 height:0.4 length:0.2 chamferRadius:0];

        f.firstMaterial.diffuse.contents = [UIColor colorWithHue:0.25 saturation:0.9 brightness:0.8 alpha:1];

        SCNNode *fNode = [SCNNode nodeWithGeometry:f];

        float x = (i % 2) * 1.20.6;

        float z = (i / 2) * 1.00.5;

        fNode.position = SCNVector3Make(x, –0.3, z);

        [flog addChildNode:fNode];

    }

    

    flog.physicsBody = [SCNPhysicsBody dynamicBody];

    flog.physicsBody.allowsResting = NO;

    flog.physicsBody.type = SCNPhysicsBodyTypeStatic;

    flog.physicsBody.angularVelocityFactor = SCNVector3Make(0, 0, 0);

    self.flog = flog;

}

– (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact {

    if (contact.nodeA == self.flog) {

        self.contactLeaf = contact.nodeB;

    } else if (contact.nodeB == self.flog) {

        self.contactLeaf = contact.nodeA;

    }

    self.flog.physicsBody.type = SCNPhysicsBodyTypeStatic;

}

– (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time {

    

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        self.start = time – 0.001;

    });

    

    for (int i=0; i<self.leaves.count; i++) {

        float dt = time – self.start + 5 * i;

        float x = dt – 20 * ((int)dt / 20); // 0 ~ 20

        if (x < 10) {

            x = x – 5;

        } else {

            x = 15 – x;

        }

        SCNNode *n = self.leaves[i];

        n.position = SCNVector3Make(x, 0, n.position.z);

        self.sceneView.playing = YES;

    }

    

    if (self.contactLeaf) {

        self.flog.position = SCNVector3Make(self.contactLeaf.position.x, 0.5, self.contactLeaf.position.z);

    }

}

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

{

    self.contactLeaf.physicsBody = nil;

    self.contactLeaf = nil;

    

    self.flog.physicsBody.type = SCNPhysicsBodyTypeDynamic;

    [self.flog.physicsBody applyForce:SCNVector3Make(0, 6, –2) impulse:YES];

}

@end