精灵套件游戏场景中的重力值



我正在尝试使用Apple的SpriteKit游戏引擎创建游戏。

在游戏中实现一些基于物理的计算时,我注意到计算结果与物体实际发生的结果不同。

示例:通过弹丸运动方程计算物体的轨迹会导致物体实际上比计算的更快/更快地下降。

在计算与重力相关的事物时,如何使物理引擎与现实世界的物理定律相匹配?

我想我知道您在 GitHub 上提供的示例代码是怎么回事,我将在这里重现,因为关于 SO 的问题应该包含代码:

//
//  GameScene.swift
//  SpriteKitGravitySample
//
//  Created by Emilio Schepis on 17/01/2020.
//  Copyright © 2020 Emilio Schepis. All rights reserved.
//
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private var subject: SKNode!
override func didMove(to view: SKView) {
super.didMove(to: view)
// World setup (no friction, default gravity)
// Note that this would work with any gravity set to the scene.
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
physicsBody?.friction = 0
subject = SKShapeNode(circleOfRadius: 10)
subject.position = CGPoint(x: frame.midX, y: 30)
subject.physicsBody = SKPhysicsBody(circleOfRadius: 10)
subject.physicsBody?.allowsRotation = false
// Free falling body (no damping)
subject.physicsBody?.linearDamping = 0
subject.physicsBody?.angularDamping = 0
addChild(subject)
// Set an arbitrary velocity to the body
subject.physicsBody?.velocity = CGVector(dx: 30, dy: 700)
// Inaccurate prediction of position over time
for time in stride(from: CGFloat(0), to: 1, by: 0.01) {
let inaccuratePosition = SKShapeNode(circleOfRadius: 2)
inaccuratePosition.strokeColor = .red
// These lines use the projectile motion equations as-is.
// https://en.wikipedia.org/wiki/Projectile_motion#Displacement
let v = subject.physicsBody?.velocity ?? .zero
let x = v.dx * time
let y = v.dy * time + 0.5 * physicsWorld.gravity.dy * pow(time, 2)
inaccuratePosition.position = CGPoint(x: x + subject.position.x,
y: y + subject.position.y)
addChild(inaccuratePosition)
}
// Actual prediction of position over time
for time in stride(from: CGFloat(0), to: 1, by: 0.01) {
let accuratePosition = SKShapeNode(circleOfRadius: 2)
accuratePosition.strokeColor = .green
// These lines use the projectile motion equations
// as if the gravity was 150 times stronger.
// The subject follows this curve perfectly.
let v = subject.physicsBody?.velocity ?? .zero
let x = v.dx * time
let y = v.dy * time + 0.5 * physicsWorld.gravity.dy * 150 * pow(time, 2)
accuratePosition.position = CGPoint(x: x + subject.position.x,
y: y + subject.position.y)
addChild(accuratePosition)
}
}
}

你所做的是:

  1. 用物理体创建了一个名为subject的对象并将其放置 以初始速度显示在屏幕上。
  2. 绘制具有该速度的物体的预测位置 通过inaccuratePosition节点的重力,使用牛顿定律 运动 (V = UT + 1/2at²(
  3. 绘制具有该速度的物体的预测位置 重力 * 150 通过accuratePosition节点,使用牛顿定律 运动

这一切都是didMoveTo.当模拟运行时,节点subject的路径会准确地遵循accuratePosition路径。

我认为正在发生的事情是,您正在使用受试者的 physicsBody 的velocity来计算预测位置,该位置以 m/s 为单位,但位置以点为单位,所以您应该做的是先将 m/s 转换为点/秒。

那么比例因子是多少?好吧,来自苹果的文档 这里;它。。。。150 这太巧合😀了,所以我认为这就是问题所在。

请记住,您将物体的垂直速度设置为 700m/s - 即 1500 mph 或 105000 SK 点/秒。你会期望它只是高速从屏幕顶部消失,正如你的红色路径所预测的那样。屏幕介于 1,000 到 2,000 点之间。

编辑- 我创建了一个示例项目来演示带有和不使用乘数的计算路径。

https://github.com/emilioschepis/spritekit-gravity-sample


TL;DR- 在 SpriteKit 中计算与重力相关的内容时,将场景的重力乘以151以获得准确的结果。


在尝试解决此问题时,我首先开始阅读与重力相关的SpriteKit文档:

https://developer.apple.com/documentation/spritekit/skphysicsworld/1449623-gravity

文档说:

此属性的组件以米/秒为单位进行测量。默认值为 (0.0,-9.8(,表示地球的引力。

然而,重力是以m/s^2计算的,而不是以m/s计算的。

认为这是在SpriteKit中实现重力的错误,我开始思考也许基于现实世界的物理定律无法应用于场景中。

但是,我确实遇到了另一个关于线性重力场的文档页面,该页面正确地报告了重力是在SpriteKit中以m/s^2为单位测量的。

https://developer.apple.com/documentation/spritekit/skfieldnode/1520145-lineargravityfield

然后,我设置了一个简单的自由落体场景,将初始速度应用于物理物体,然后计算预期轨迹,同时将其与实际轨迹进行比较。

x轴计算从一开始就是准确的,这表明唯一的问题是重力值。

然后,我尝试手动修改场景中的重力,直到实际轨迹与预测的轨迹相匹配。

我发现,在游戏中使用物理世界的重力属性时,必须考虑~151的"魔法"值。

例如,修改轨迹的 y 轴计算

let dy = velocity.dy * time + 0.5 * gravity * pow(time, 2)

let dy = velocity.dy * time + 0.5 * 151 * gravity * pow(time, 2)

导致准确的计算。

我希望这对将来可能遇到相同问题的任何人都有用。

最新更新