Reputation: 293
I am trying to make a simple app where if you tap the screen a box is switched from floating to affected by gravity. I can't seem to find a way to make the box float in the air though.
This code here takes care of half the problem:
boxNode.physicsBody = [SCNPhysicsBody dynamicBody];
This causes the box to drop out of the air and hit a floor I created. Is there anything in SCNPhysicsBody that would do the opposite of this? Say, perhaps, cause objects to float or just sail off toward a ceiling?
Also, I've written this code:
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
if (myBool == false) {
myBool = true;
NSLog(@"true");
} else {
myBool = false;
NSLog(@"false");
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// touch recognizer
UITapGestureRecognizer *screenTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:screenTap];
// create box
SCNBox *myBox = [SCNBox boxWithWidth:1.0 height:1.0 length:1.0 chamferRadius:0.1];
SCNNode *boxNode = [SCNNode nodeWithGeometry:myBox];
boxNode.position = SCNVector3Make(0.0, 0.0, 4.0);
[myScene.rootNode addChildNode:boxNode];
while (myBool == true) {
boxNode.physicsBody = [SCNPhysicsBody dynamicBody];
}
}
I'm not sure why the while loop doesn't work though. I was thinking it would detect that myBool has been changed and alter the physics of the boxNode, but it doesn't.
Upvotes: 0
Views: 961
Reputation: 2897
The viewDidLoad
method is only called once when the view is loaded. If your app is initialised with myBool = false
, then the while loop will never be run. However in this case if myBool
was true the while loop would never stop executing, preventing the view from loading, and therefore preventing the user from tapping the view to trigger your gesture recogniser.
I haven't tested the below, but it should at least give you a starting point. The scene is created in the viewDidLoad
as per your code, importantly the scene's physicsWorld
has its gravity set to zero (this is -9.8 by default). Later on when the user taps the view we reset the gravity to its default value, this should cause the box to fall.
The header file GameViewController.h
#import <UIKit/UIKit.h>
#import <SceneKit/SceneKit.h>
@interface GameViewController : UIViewController {
SCNScene *myScene;
}
@end
and GameViewController.m
#import "GameViewController.h"
@implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// create a new scene
myScene = [SCNScene scene];
// create box
SCNBox *myBox = [SCNBox boxWithWidth:1.0 height:1.0 length:1.0 chamferRadius:0.1];
SCNNode *boxNode = [SCNNode nodeWithGeometry:myBox];
boxNode.position = SCNVector3Make(0.0, 0.0, 4.0);
[myScene.rootNode addChildNode:boxNode];
boxNode.physicsBody = [SCNPhysicsBody dynamicBody];
//'disable' scene gravity
myScene.physicsWorld.gravity = SCNVector3Make(0, 0, 0);
SCNView *scnView = (SCNView *)self.view;
scnView.scene = myScene;
scnView.allowsCameraControl = YES;
scnView.autoenablesDefaultLighting = YES;
scnView.backgroundColor = [UIColor blackColor];
// add a tap gesture recognizer
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
NSMutableArray *gestureRecognizers = [NSMutableArray array];
[gestureRecognizers addObject:tapGesture];
[gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers];
scnView.gestureRecognizers = gestureRecognizers;
}
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
myScene.physicsWorld.gravity = SCNVector3Make(0, -9.8, 0);
}
@end
Upvotes: 1