Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving Camera in SpriteKit Swift

I am creating a game in sprite kit using swift, and I am trying to be able to move the SKScene around with a finger because not all of the nodes fit within the scene. I have already created world, overlay, and camera nodes with this code.

        override func didMoveToView(view: SKView) {
    world = self.childNodeWithName("world")!

    if !isCreated {
        isCreated = true

        // Camera setup
        self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        self.world = SKNode()
        self.world.name = "world"
        addChild(self.world)

        self.cam = SKNode()
        self.cam.name = "camera"
        self.world.addChild(self.cam)

        // UI setup
        self.overlay = SKNode()
        self.overlay.zPosition = 10
        self.overlay.name = "overlay"
        addChild(self.overlay)
    }

I would like to be able to move the camera around by using a pan gesture with a single finger. How would I do this? Any help would be appreciated.

like image 509
Aidan Kaiser Avatar asked Aug 10 '16 06:08

Aidan Kaiser


People also ask

How to create a game scene in SwiftUI using spriteview?

Create a variable that will initialize and host the Game Scene var scene: SKScene { let scene = GameScene() scene.size = CGSize(width: 216, height: 216) scene.scaleMode = .fill return scene } var body: some View { // 3. Using the SpriteView, show the game scene in your SwiftUI view // You can even use modifiers!

How to host a gamescene object in SwiftUI?

Create a variable to host your GameScene object, which will be where your game is in the future. Use the SpriteView (scene:) view to host your GameScene object and show it in your application. import SwiftUI // 1. Import the SpriteKit framework import SpriteKit struct ContentView: View { // 2.

Is it possible to create a SpriteKit game in Xcode?

Even though the default Game Xcode Template creates the project based on a UIKit application, you can create a SwiftUI app and put your SpriteKit game inside it without any hustle thanks to the SpriteView view! The documentation page for the SpriteView SwiftUI view.

Why import the SpriteKit framework?

Import the SpriteKit framework, so you have access to everything it has to offer. Without it you won’t be able to have access to the SKScene class, for example, and you wouldn’t be able to create your GameScene object. Create a variable to host your GameScene object, which will be where your game is in the future.


2 Answers

If anybody needs it, here is an all-in-one solution:

class GameScene: SKScene {

  var previousCameraPoint = CGPoint.zero

  override func didMove(to view: SKView) {
    let panGesture = UIPanGestureRecognizer()
    panGesture.addTarget(self, action: #selector(panGestureAction(_:)))
    view?.addGestureRecognizer(panGesture)
  }

  @objc func panGestureAction(_ sender: UIPanGestureRecognizer) {
    // The camera has a weak reference, so test it
    guard let camera = self.camera else {
      return
    }
    // If the movement just began, save the first camera position
    if sender.state == .began {
      previousCameraPoint = camera.position
    }
    // Perform the translation
    let translation = sender.translation(in: self.view)
    let newPosition = CGPoint(
      x: previousCameraPoint.x + translation.x * -1,
      y: previousCameraPoint.y + translation.y
    )
    camera.position = newPosition
  }

}
like image 122
Steve G. Avatar answered Sep 21 '22 06:09

Steve G.


As an alternative to @Kris's solution (which is based in UIKit), you can also monitor touches in Sprite Kit with your SKScene subclass. I wrote a small sample which should point you in the right direction.

class YourSceneSubclass : SKScene
{  
  override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    guard let touch = touches.first else {
      return
    }

    let location = touch.locationInNode(self)
    let previousLocation = touch.previousLocationInNode(self)

    camera?.position.x += location.x - previousLocation.x
    camera?.position.y += location.y - previousLocation.y
  }
}

I didn't run this, just wrote it in a playground. Also note that if you want to handle other taps/gestures as well you will have to write additional code making sure the recognition works well for all your intended scenarios.

like image 20
CloakedEddy Avatar answered Sep 24 '22 06:09

CloakedEddy