Определить границы карты и центр на узле игрока?

Я работаю над сайдскроллером со Spritekit и Swift. Я не понимаю, как определить игровую область больше экрана и центрировать камеру на плеере. Как это может быть сделано?

Это мой текущий код, я попытался создать "мировой узел", который я мог бы перемещать, чтобы имитировать камеру, однако он каким-то образом не связан с его формой, и я не смог получить внутри него плеер.

override func didMoveToView(view: SKView) {
    self.anchorPoint = CGPointMake(0.5, 0.5)
    self.physicsWorld.contactDelegate = self
    self.size = CGSizeMake(view.bounds.size.width, view.bounds.size.height)

    // Add world
    let r : CGRect = CGRectMake(0, 0, 500, 500)
    world = SKShapeNode(rectOfSize: r.size)
    world.physicsBody = SKPhysicsBody(edgeLoopFromRect: r)
    world.strokeColor = SKColor.blackColor()
    world.position = CGPointMake(0, 0)
    self.addChild(world)

    // Add player
    player = SKShapeNode(rectOfSize: CGSize(width: 50, height: 50))
    player.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 50, height: 50))
    player.fillColor = SKColor.blackColor()
    player.position = CGPointMake(0, 0)
    world.addChild(player)

    // Accelerometer updates
    motionManager.startAccelerometerUpdates()
}

2 ответа

Решение

Пример в документации Apple находится в разделе " Расширенная обработка сцены". Apple предлагает создать "Мир" SKNode как дитя Сцены и "Камера" SKNode как дитя мира.

Они предлагают постоянно перемещать мир так, чтобы он центрировался на Камере во время шага didSimulatePhysics. Этот метод позволяет вам выполнять действия или моделировать физику на самой камере, если вы того пожелаете. Если вы центрируете камеру до этого шага, вы не сможете использовать физику для воздействия на узел камеры.

Если вам нужна прокрутка влево и вправо, просто ограничьте движение по оси X.

Редактировать: текущая проблема из-за вашего создания мира и физики тела из Rect, чья позиция предопределена. Это вызывает проблемы с настройкой anchorPoint (мир и физика создаются с нижним левым углом, начиная с точки привязки сцены).

Это можно исправить, создав Мир и Игрока без использования Rect с установленной позицией. SKShapeNode-х shapeNodeWithRectOfSize работает, как и SKSpriteNode's spriteNodeWithColor:size: PhysicsBody немного сложнее, и, вероятно, следует использовать bodyWithEdgeLoopFromPath: world.path

РЕДАКТИРОВАТЬ: Для будущих людей, заинтересованных в создании боковой скроллер с камерой, всегда ориентированной на игрока, это, вероятно, самый простой способ заставить его работать:

var player = SKShapeNode()
var world = SKShapeNode()

override func didMoveToView(view: SKView) {
    self.anchorPoint = CGPointMake(0.5, 0.5)
    self.size = CGSizeMake(view.bounds.size.width, view.bounds.size.height)

    // Add world
    world = SKShapeNode(rectOfSize: CGSizeMake(300, 300))
    world.physicsBody = SKPhysicsBody(edgeLoopFromPath: world.path)
    world.fillColor = SKColor.blackColor()
    self.addChild(world)

    // Add player
    player = SKShapeNode(rectOfSize: CGSize(width: 50, height: 50))
    player.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 50, height: 50))
    player.fillColor = SKColor.blackColor()
    world.addChild(player)
}

override func update(currentTime: CFTimeInterval) {
    world.position.x = -player.position.x
    world.position.y = -player.position.y
}

Я следовал за обучением Рэя Вендерлиха в игре Super Koalio (или что-то в этом роде). Эта игра представляет собой боковой скроллер, где игровая карта больше по бокам, чем экран. Следующий код предназначен для моей игры с вертикальной прокруткой.

В методе обновления я вызываю метод с именем setViewPointCenter.

-(void)update:(CFTimeInterval)currentTime
  {
    // Other things are called too
    [self setViewPointCenter:self.player.position];
  }

Затем в этом методе вы просто обновите представление

- (void)setViewPointCenter:(CGPoint)position
{
  NSInteger x = MAX(position.x, self.size.width / 2);
  NSInteger y = MAX(position.y, self.size.height /2);
  x = MIN(x, (self.map.mapSize.width * self.map.tileSize.width) - self.size.width / 2);
  y = MIN(y, (self.map.mapSize.height * self.map.tileSize.height) - self.size.height / 2);
  CGPoint actualPostion = CGPointMake(x, y);
  CGPoint centerOfView = CGPointMake(self.size.width/2, self.size.height/2);
  CGPoint viewPoint = CGPointSubtract(centerOfView, actualPostion);
  self.map.position = viewPoint;
}

Теперь мой персонаж всегда в центре экрана. Я изменил некоторые пункты с горизонтального на вертикальный, но, по крайней мере, вы поняли. Также я использовал карту тайла, поэтому вы видите mapSize и tileSize. Возможно, вы захотите взглянуть на учебник Рэя. И, конечно, вам нужно будет преобразовать методы в Swift!

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