Движущаяся платформа с игровым комплектом

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

Пример:

Подвижная платформа
Я хочу, чтобы эта платформа двигалась по часовой стрелке, также, когда она достигает вершины и дна, я хочу, чтобы она вращалась соответствующим образом, как если бы она смотрела в направлении, в котором она движется (поэтому платформа, по существу, поворачивается на 180 градусов, когда она изгибается сверху и снизу).

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

Моя идея заключается в том, что я могу использовать агента с поведением и целями для этого. Не уверен, что мне понадобится поиск пути.

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

Заранее спасибо!

1 ответ

Использование SKActions или ручная регулировка положения будет недостаточным для того, чтобы работать так, как вы хотите, НО всегда стоит попробовать, потому что на его макет уйдет 2 минуты, и вы увидите...

Я бы предложил сделать что-то вроде Path класс, который отправляет команды скорости на платформу каждый кадр...

На самом деле, это может быть хорошим упражнением в изучении конечного автомата..

MOVE RIGHT STATE: если позиция X> начальная позиция X + 200, войдите в состояние "двигаться вниз"

MOWE DOWN STATE: если позиция Y <начальная позиция Y - 200, войдите в состояние "двигаться влево"

ПЕРЕМЕСТИТЬ ВЛЕВОЕ СОСТОЯНИЕ: если позиция X <начальная позиция X, введите состояние "двигаться вверх"

MOVE UP STATE: если позиция Y> начальная позиция Y, введите состояние "двигаться вправо"

.. есть способы, которые вы могли бы придать большей кривизне, а не просто под прямым углом (при изменении направления)

В противном случае вам придется перевести это в класс / структуру / компонент и дать каждой платформе свой собственный экземпляр.

///

Другой вариант - вывести физику из уравнения и создать playerIsOnPlatform свойство... тогда вы вручную настраиваете положение игрока в каждом кадре... (или, возможно, SKConstraint)

Это потребует больше кода для прыжков и тому подобного, и довольно быстро превращает вещи в спагетти (когда я в последний раз пробовал)

Но я смог успешно клонировать это, используя правильное обнаружение попадания по этому пути:

https://www.youtube.com/watch?v=cnhlFZeIR7Q

ОБНОВИТЬ:

Вот рабочий проект:
https://github.com/fluidityt/exo2/tree/master

Быстрая посылка:

import SpriteKit
import GameplayKit


// Workaround to not having any references to the scene off top my head..
// Simply add `gScene = self` in your didMoveToViews... or add a base scene and `super.didMoveToView()`
var gScene = GameScene()

class GameScene: SKScene {

  override func didMove(to view: SKView) {
    gScene = self
  }

  var entities = [GKEntity]()
  var graphs = [String : GKGraph]()

  private var lastUpdateTime : TimeInterval = 0

  func gkUpdate(_ currentTime: TimeInterval) -> TimeInterval {
    if (self.lastUpdateTime == 0) {
      self.lastUpdateTime = currentTime
    }

    let dt = currentTime - self.lastUpdateTime

    for entity in self.entities {
      entity.update(deltaTime: dt)
    }

    return currentTime
  }

  override func update(_ currentTime: TimeInterval) {
    self.lastUpdateTime = gkUpdate(currentTime)
  }
}

Вот самый базовый компонент:

class Platforms_BoxPathComponent: GKComponent {

  private enum MovingDirection: String { case up, down, left, right }

  private var node: SKSpriteNode!

  private var state: MovingDirection = .right

  private lazy var startingPos: CGPoint = { self.node.position }()

  @GKInspectable var startingDirection: String = "down"
  @GKInspectable var uniqueName: String = "platform"
  @GKInspectable var xPathSize: CGFloat = 400
  @GKInspectable var yPathSize: CGFloat = 400

  // Moves in clockwise:
  private var isTooFarRight: Bool { return self.node.position.x > (self.startingPos.x + self.xPathSize) }
  private var isTooFarDown:  Bool { return self.node.position.y < (self.startingPos.y - self.yPathSize) }
  private var isTooFarLeft:  Bool { return self.node.position.x < self.startingPos.x }
  private var isTooFarUp:    Bool { return self.node.position.y > self.startingPos.y }

  override func didAddToEntity() {
    print("adding component")
    // can't add node here because nodes aren't part of scene yet :(
    // possibly do a thread?
  }

  override func update(deltaTime seconds: TimeInterval) {
    if node == nil {
      node = gScene.childNode(withName: uniqueName) as! SKSpriteNode

      // for some reason this is glitching out and needed to be redeclared..
      // showing 0 despite clearly not being 0, both here and in the SKS editor:
      xPathSize = 300
    }

    let amount: CGFloat = 2 // Amount to move platform (could also be for for velocity)

    // Moves in clockwise:
    switch state {

    case .up:
      if isTooFarUp {
        state = .right
        fallthrough
      } else { node.position.y += amount }

    case .right:
      if isTooFarRight {
        state = .down
        fallthrough
      } else { node.position.x += amount }

    case .down:
      if isTooFarDown {
        state = .left
        fallthrough
      } else { node.position.y -= amount }

    case .left:
      if isTooFarLeft {
        state = .up
        fallthrough
      } else { node.position.x -= amount }

    default:
      print("this is not really a default, just a restarting of the loop :)")
      node.position.y += amount
    }
  }
}

А вот что вы делаете в редакторе sks:

Другие вопросы по тегам