I am trying to use SceneKit to develop a game for tvOS and I have a problem. When I install node eulerAngle, before applying the impulse to the physical device, the node will reset to its original position.
I expected to see the nodes moving along the floor plane, but at each touch the nodes move to their original position before applying the impulse.
I am new to using this structure, so I wonder where the error is. I am using the new AppleTV with tvOS 9.0 and Xcode 7.1.1
To play it, you can create a new xcode project (Game for tvOS) and replace GameViewController.m with this code:
#import "GameViewController.h"
SCNNode *ship;
SCNNode *node;
SCNNode *ground;
@implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
SCNScene *scene = [[SCNScene alloc] init];
scene.physicsWorld.gravity = SCNVector3Make(0, -800, 0);
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.zFar = 10000;
[scene.rootNode addChildNode:cameraNode];
cameraNode.position = SCNVector3Make(0, 64, 64);
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeOmni;
lightNode.position = SCNVector3Make(0, 10, 10);
[scene.rootNode addChildNode:lightNode];
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor darkGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
SCNGeometry *geometry;
SCNMaterial *material;
SCNNode *tempNode;
SCNPhysicsShape* shape;
SCNPhysicsBody* body;
SCNScene *loaded = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];
tempNode = [loaded.rootNode childNodeWithName:@"ship" recursively:YES];
geometry = [SCNCylinder cylinderWithRadius:16 height:8];
shape = [SCNPhysicsShape shapeWithGeometry:geometry options:nil];
tempNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];
tempNode.physicsBody.restitution = 1;
tempNode.physicsBody.friction = 0.25;
tempNode.physicsBody.categoryBitMask = 2;
tempNode.physicsBody.collisionBitMask = 1;
tempNode.position = SCNVector3Make(32, 32, 0);
[scene.rootNode addChildNode:tempNode];
ship = tempNode;
geometry = [SCNCylinder cylinderWithRadius:16 height:8];
material = [[SCNMaterial alloc] init];
material.diffuse.contents = UIColor.yellowColor;
geometry.materials = @[material];
shape = [SCNPhysicsShape shapeWithGeometry:geometry options:nil];
body = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];
tempNode = [SCNNode nodeWithGeometry: geometry];
tempNode.physicsBody = body;
tempNode.physicsBody.restitution = 1;
tempNode.physicsBody.friction = 0.25;
tempNode.physicsBody.categoryBitMask = 2;
tempNode.physicsBody.collisionBitMask = 1;
tempNode.position = SCNVector3Make(0, 32, 0);
[scene.rootNode addChildNode:tempNode];
node = tempNode;
geometry = [[SCNFloor alloc] init];
material = [[SCNMaterial alloc] init];
material.diffuse.contents = UIColor.blueColor;
geometry.materials = @[material];
shape = [SCNPhysicsShape shapeWithGeometry:geometry options:nil];
body = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic shape:shape];
tempNode = [SCNNode nodeWithGeometry: geometry];
tempNode.physicsBody = body;
tempNode.physicsBody.categoryBitMask = 1;
[scene.rootNode addChildNode:tempNode];
ground = tempNode;
SCNLookAtConstraint * constraint = [SCNLookAtConstraint lookAtConstraintWithTarget: ground];
constraint.gimbalLockEnabled = YES;
cameraNode.constraints = @[constraint];
SCNView *scnView = (SCNView *)self.view;
scnView.scene = scene;
scnView.allowsCameraControl = NO;
scnView.debugOptions = SCNDebugOptionShowPhysicsShapes;
scnView.showsStatistics = YES;
scnView.backgroundColor = [UIColor blackColor];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
NSMutableArray *gestureRecognizers = [NSMutableArray array];
[gestureRecognizers addObject:tapGesture];
[gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers];
scnView.gestureRecognizers = gestureRecognizers;
}
- (void) handleTap:(UIGestureRecognizer*)gestureRecognize
{
float x = (rand() / (float)RAND_MAX) - 0.5f;
float y = (rand() / (float)RAND_MAX) - 0.5f;
float speed = (rand() / (float)RAND_MAX) * 300;
CGPoint velocity = CGPointMake(x, y);
float angle = [self AngleBetween:velocity And:CGPointMake(1, 0)] + M_PI_2;
[node.physicsBody applyForce:SCNVector3Make(velocity.x*speed, 0, velocity.y*speed) impulse:YES];
[ship.physicsBody applyForce:SCNVector3Make(velocity.x*speed, 0, velocity.y*speed) impulse:YES];
node.eulerAngles = SCNVector3Make(0, angle, 0);
ship.eulerAngles = SCNVector3Make(0, angle, 0);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (float) AngleBetween:(CGPoint)_origin And:(CGPoint)_destination
{
float dotProduct = (_origin.x * _destination.x) + (_origin.y * _destination.y);
float perpDotProduct = (_origin.x * _destination.y) - (_origin.y * _destination.x);
return -atan2f(-perpDotProduct, dotProduct);
}
@end
If you comment on the lines where the Euler angles are set (with the handleTap method), the problem does not occur.