SceneKit 中的反重力物理
Anti-gravity physics in SceneKit
我正在尝试制作一个简单的应用程序,如果您点击屏幕,一个框就会从浮动切换到受重力影响。不过,我似乎找不到让盒子漂浮在空中的方法。
这段代码解决了一半问题:
boxNode.physicsBody = [SCNPhysicsBody dynamicBody];
这会导致盒子从空中掉落并撞到我创建的地板上。 SCNPhysicsBody 中有什么东西可以做相反的事情吗?比如说,也许让物体漂浮或只是朝天花板航行?
另外,我写了这段代码:
- (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];
}
}
我不确定为什么 while 循环不起作用。我以为它会检测到 myBool 已被更改并改变 boxNode 的物理特性,但它没有。
viewDidLoad
方法仅在加载视图时调用一次。如果您的应用程序使用 myBool = false
初始化,则 while 循环永远不会是 运行。但是,在这种情况下,如果 myBool
为真,则 while 循环将永远不会停止执行,从而阻止加载视图,从而阻止用户点击视图来触发您的手势识别器。
我没有测试下面的内容,但它至少应该给你一个起点。场景是根据您的代码在 viewDidLoad
中创建的,重要的是场景的 physicsWorld
的重力设置为零(默认情况下为 -9.8)。稍后当用户点击我们将重力重置为默认值的视图时,这应该会导致盒子掉落。
头文件GameViewController.h
#import <UIKit/UIKit.h>
#import <SceneKit/SceneKit.h>
@interface GameViewController : UIViewController {
SCNScene *myScene;
}
@end
和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
我正在尝试制作一个简单的应用程序,如果您点击屏幕,一个框就会从浮动切换到受重力影响。不过,我似乎找不到让盒子漂浮在空中的方法。
这段代码解决了一半问题:
boxNode.physicsBody = [SCNPhysicsBody dynamicBody];
这会导致盒子从空中掉落并撞到我创建的地板上。 SCNPhysicsBody 中有什么东西可以做相反的事情吗?比如说,也许让物体漂浮或只是朝天花板航行?
另外,我写了这段代码:
- (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];
}
}
我不确定为什么 while 循环不起作用。我以为它会检测到 myBool 已被更改并改变 boxNode 的物理特性,但它没有。
viewDidLoad
方法仅在加载视图时调用一次。如果您的应用程序使用 myBool = false
初始化,则 while 循环永远不会是 运行。但是,在这种情况下,如果 myBool
为真,则 while 循环将永远不会停止执行,从而阻止加载视图,从而阻止用户点击视图来触发您的手势识别器。
我没有测试下面的内容,但它至少应该给你一个起点。场景是根据您的代码在 viewDidLoad
中创建的,重要的是场景的 physicsWorld
的重力设置为零(默认情况下为 -9.8)。稍后当用户点击我们将重力重置为默认值的视图时,这应该会导致盒子掉落。
头文件GameViewController.h
#import <UIKit/UIKit.h>
#import <SceneKit/SceneKit.h>
@interface GameViewController : UIViewController {
SCNScene *myScene;
}
@end
和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