物理行为

本节学习任务

掌握SceneKit游戏框架中的物理行为。

物理行为的定义

定义一个或多个物理组织的高级行为,行为包括连接多个物体的关节,可以让他们一起移动,也可以定义车轮这种行为,让身体想骑车一样滚动。

相关的类(SCNPhysicsBehavior)

你不会直接使用这个类,你实例化这个类的一个子类,定义你想要的行为,并且添加到物理世界去。我去在文档中找,有这样一句话 SCNPhysicsBehavior is an abstract class that represents a behavior in the physics world.

看来这个类是物理行为的一个基类,这个类是一个抽象的类,我们没法设置它的属性,但是它有四个子类,我们就从它的四个子类入手,去发掘子类的作用。

SCNPhaysicBehavior 子类的介绍

a.SCNPhysicsHingeJoint

作用:连接两个物体,并允许他们在一个单一的轴上围绕对方转动

b.SCNPhysicsBallSocketJoint

作用:连接两个物体,并允许他们在任何方向上围绕对方转动

c.SCNPhysicsSliderJoint

作用:连接两个物体,并允许他们彼此之间滑动或旋转。滑块关节像电机一样工作,在两个物理身体之间施加力或转矩。

d.SCNPhysicsVehicle

作用:组合物理身体成为类似汽车底盘的东西,你可以控制汽车的驾驶,刹车和加速。使用SCNPhysicsVehicleWheel 对象定义车轮的外观和物理属性。

使用步骤

  1. 创建一个或者多个SCNPhysicsBody 绑定他们到每个节点上,作为物理行为的执行者。
  2. 创建配置上面列表中的行为
  3. 使用物理世界(SCNPhysicsWorld)的方法addBehavior: 添加到行为到物理世界中去。

在进入下一个话题,有必要介绍一个方法

@interface SCNPhysicsHingeJoint : SCNPhysicsBehavior
+ (instancetype)jointWithBodyA:(SCNPhysicsBody *)bodyA axisA:(SCNVector3)axisA anchorA:(SCNVector3)anchorA bodyB:(SCNPhysicsBody *)bodyB axisB:(SCNVector3)axisB anchorB:(SCNVector3)anchorB;

参数: bodyA bodyB 物理身体没啥好说的. axisA axisB 沿着哪个轴转动,比如(1,0,0)沿着X轴转动 anchorA anchorB 锚点A,锚点B。有些几何体的锚点不在几何体的中心,比如字体的这样几何体,它的锚点在左下角,使用时请注意一下。

import UIKit
import SceneKit

class Test13VC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let scnView = SCNView(frame: view.bounds)
        scnView.backgroundColor = UIColor.black
        scnView.allowsCameraControl = true
        scnView.scene = SCNScene()
        view.addSubview(scnView)

        let camera = SCNCamera()
        let cameraNode = SCNNode()
        cameraNode.camera = camera
        camera.automaticallyAdjustsZRange = true
        cameraNode.position = SCNVector3Make(0, 10, 20)
        scnView.scene?.rootNode.addChildNode(cameraNode)

        let floor = SCNFloor()
        floor.firstMaterial?.diffuse.contents = UIColor.brown
        let floorNode = SCNNode(geometry: floor)
        floorNode.physicsBody = SCNPhysicsBody(type: .static, shape: nil)
        scnView.scene?.rootNode.addChildNode(floorNode)

        let box = SCNBox(width: 3, height: 3, length: 3, chamferRadius: 0)
        box.firstMaterial?.diffuse.contents = "art.scnassets/2.jpg"
        let boxNode = SCNNode(geometry: box)
        boxNode.position = SCNVector3Make(0, 50, 0)
        boxNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape.init(geometry: SCNBox.init(width: 3, height: 3, length: 3, chamferRadius: 0), options: nil))
        scnView.scene?.rootNode.addChildNode(boxNode)

        let ball = SCNSphere(radius: 1.5)
        ball.firstMaterial?.diffuse.contents = "art.scnassets/earth/earth1.jpg"
        let ballNode = SCNNode(geometry: ball)
        ballNode.position = SCNVector3Make(0, 45, 0)
        ballNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape.init(geometry: SCNSphere.init(radius: 1.5), options: nil))
        scnView.scene?.rootNode.addChildNode(ballNode)

        let cylinder = SCNCylinder(radius: 1.5, height: 3)
        cylinder.firstMaterial?.diffuse.contents = "art.scnassets/1.jpg"
        let cylinderNode = SCNNode(geometry: cylinder)
        cylinderNode.position = SCNVector3Make(0, 40, 0)
        cylinderNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape.init(geometry: SCNCylinder(radius: 1.5, height: 3), options: nil))
        scnView.scene?.rootNode.addChildNode(cylinderNode)

        //创建物理身体之前的物理行为
        let joint1 = SCNPhysicsHingeJoint(bodyA: boxNode.physicsBody!, axisA: SCNVector3Make(0, 1, 0), anchorA: SCNVector3Make(0, -0.5, 0), bodyB: ballNode.physicsBody!, axisB: SCNVector3Make(0, 1, 0), anchorB: SCNVector3Make(0, 0.5, 0))
        // 将物理行为添加物理世界中去
        scnView.scene?.physicsWorld.addBehavior(joint1)

        let joint2 = SCNPhysicsHingeJoint(bodyA: ballNode.physicsBody!, axisA: SCNVector3Make(0, 1, 0), anchorA: SCNVector3Make(0, -0.5, 0), bodyB: cylinderNode.physicsBody!, axisB: SCNVector3Make(0, 1, 0), anchorB: SCNVector3Make(0, 0.5, 0))
        scnView.scene?.physicsWorld.addBehavior(joint2)
    }

}

results matching ""

    No results matching ""