Значение гравитации на игровой сцене SpriteKit - PullRequest
0 голосов
/ 17 января 2020

Я пытаюсь создать игру, используя игровой движок Apple SpriteKit.

При реализации некоторых физических вычислений в игре я заметил, что вычисленные результаты отличаются от того, что эффективно происходит с объектами.

Пример: вычисление траектории тела посредством движения снаряда * Уравнения 1006 * заставляют тело фактически падать гораздо быстрее / быстрее, чем рассчитывается.

Как я могу сделать физику двигатель соответствует реальной физике l aws при расчете чего-то, связанного с гравитацией?

Ответы [ 2 ]

4 голосов
/ 17 января 2020

Мне кажется, я знаю, что происходит с примером кода, который вы предоставили на 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)
        }

    }

}

То, что вы сделали, это to:

  1. Создание объекта под названием subject с PhysicsBody и размещение его на экране с начальной скоростью.
  2. Построение прогнозируемых положений для объекта с такой скоростью под действием силы тяжести через inaccuratePosition узел, используя l aws движения Ньютона (v = ut + 1 / 2at²)
  3. Построение прогнозируемых положений для объекта с такой скоростью под действием силы тяжести * 150 через узел accuratePosition, используя ньютоновский aws движения

Все это didMoveTo. Когда симуляция запускается, путь узла subject точно следует по пути accuratePosition.

I думаю , что происходит, когда вы вычисляете предсказанную позицию, используя физику тела субъекта velocity, который выражается в м / с, но позиция в точках, поэтому вам нужно сначала преобразовать м / с в точку / с.

Так, каков масштабный коэффициент? Ну из документации Apple здесь ; это .... 150, что слишком много совпадений ?, поэтому я думаю, что это проблема.

Имейте в виду, что вы устанавливаете вертикальную скорость вашего объекта на 700 м / с - это 1500 миль в час или 105000 SK точки. Вы бы ожидали , что он просто исчезнет через верхнюю часть экрана на высокой скорости, как предсказывает ваш красный путь. Экран находится где-то между 1000 и 2000 точек.

1 голос
/ 17 января 2020

Редактировать - Я создал пример проекта для демонстрации рассчитанных путей с множителем и без него.

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. Я начал думать, что, возможно, физика, основанная на реальных условиях, l aws не может быть применена на сцене.

Однако я наткнулся на другую страницу документации о линейное гравитационное поле, которое правильно сообщило, что гравитация измеряется в m/s^2 в SpriteKit.

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

Затем я настраиваю простую свободную падающую сцену, где я применил начальная скорость к физическому телу, а затем вычислила ожидаемую траекторию, сравнивая ее с фактической траекторией.

Вычисления по оси X были точными с самого начала, предполагая, что единственная проблема была со значением гравитации.

Затем я попытался вручную изменить гравитацию в сцене, пока фактическая траектория не совпала с предсказанной.

Что я нашел и заключается в том, что существует значение "magi c" ~ 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)

привели к точным вычислениям.

Я надеюсь, что это полезно для тех, кто может столкнуться с той же проблемой в будущем.

...