(斯威夫特)潘&缩放约束到特定大小的图像

时间:2017-06-08 10:35:39

标签: swift sprite-kit

我正在尝试平移和缩放spritekit中的图像背景,我已设法让缩放工作正常并手动输入一些限制你可以平移图像的距离,但问题是当你平移屏幕时到图像边缘然后缩小背景显示。 我希望相机仅限制在屏幕上的图像而不是任何空白背景。关于我应该如何做或任何更好的解决方案的任何想法? 这是我到目前为止所得到的

class GameScene:SKScene{
 var cam: SKCameraNode!
 var scaleNum:CGFloat=1

 override func didMove(to view: SKView){
    cam=SKCameraNode()
    cam.setScale(CGFloat(scaleNum))
    self.camera=cam
    self.addChild(cam)  
    let gesture=UIPinchGestureRecognizer(target: self, action: #selector(zoomIn(recognizer:)))
    self.view!.addGestureRecognizer(gesture)
}

func zoomIn(recognizer: UIPinchGestureRecognizer){
    if recognizer.state == .changed{
        cam.setScale(recognizer.scale)
        scaleNum=recognizer.scale
        if cam.xScale<1 || cam.yScale<1{
            cam.setScale(1)
        }
        if cam.xScale>3 || cam.yScale > 3{
            cam.setScale(3)
       }
       // recognizer.scale=1
       test()
    }
}

 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
   let firstTouch=touches.first
        let location=(firstTouch?.location(in: self))!
        let previousLocation=firstTouch?.previousLocation(in: self)
        cam?.position.x -= location.x - (previousLocation?.x)!
        cam?.position.y -= location.y - (previousLocation?.y)!
        test()
}

func test(){
    if cam.position.x < 1000*scaleNum{
        cam.position.x=1000*scaleNum
    }
    if cam.position.x > 9200*scaleNum{
        cam.position.x=9200*scaleNum
    }
    if cam.position.y<617*scaleNum{
        cam.position.y=617*scaleNum
    }
    if cam.position.y>4476*scaleNum{
        cam.position.y=4476*scaleNum
    }
  }
}

2 个答案:

答案 0 :(得分:0)

首先,我会将您的zoomIn功能更改为:

func zoomIn(recognizer: UIPinchGestureRecognizer){
   if recognizer.state == .changed {
       scaleNum = recognizer.scale
       if scaleNum < 1 { scaleNum = 1 }
       if scaleNum > 3 { scaleNum = 3 }
       cam.setScale(scaleNum)
       test()
   }
}

更容易理解,您没有设置两次相机比例,最重要的是,当您锁定相机比例时,scaleNum反映了该限幅值。事实并非如此,事实上,小的改变可能是你的整个问题。

现在我对UIPinchGestureRecognizer没有多少经验,但我认为缩放手势有效的原因&#34;确定&#34;是因为您直接从recognizer.scale分配到cam比例。如果我错了,请纠正我,但我认为UIGestureRecognizer总是以每个新手势的1开始,但你的相机比例保持其最后一个值。

例如,假设您的相机的比例为1.用户放大到2的比例,场景完美放大。用户举起手指结束手势。然后用户尝试放大更多,所以他们开始一个新的手势,从1开始,但你的场景仍然是2的比例。你不能直接分配手势比例或图像比例将&#39;跳&#39;每个新手势回到1。您必须从手势刻度空间转换为相机刻度空间。

您是如何做到这一点的是设计和感觉选择。没有经验,我的建议是改变zoomIn函数中的行

`scaleNum = recognizer.scale'

`scaleNum *= recognizer.scale`

尝试两个版本,让我知道它们是如何工作的。如果仍有问题,则很可能存在于您的test()功能中。如果是这样,我会尝试根据需要提供帮助。

答案 1 :(得分:0)

感谢上面的回答,我设法让它工作,代码如下。仍需要稍微调整,但您可以在背景图像上的任何位置进行平移和缩放,但视图应限制在背景图像中,而不是移动到图像之外的空白区域

import SpriteKit
import GameplayKit

class GameScene: SKScene {
var cam: SKCameraNode!
var scaleNum: CGFloat=1
var background: SKSpriteNode!
var playableRect: CGRect!

override func didMove(to view: SKView) {
    background=self.childNode(withName: "clouds") as! SKSpriteNode
    cam=SKCameraNode()
    cam.setScale(CGFloat(scaleNum))
    self.camera=cam
    self.addChild(cam)
    self.isUserInteractionEnabled=true
    let gesture=UIPinchGestureRecognizer(target: self, action: #selector(zoomIn(recognizer:)))
    self.view!.addGestureRecognizer(gesture)
   let maxAspectRatio:CGFloat=16.0/9.0
    let playableHeight=size.width/maxAspectRatio
    let playableMargin=(size.height-playableHeight)/2.0
    playableRect=CGRect(x:0, y: playableMargin, width: size.width, height: playableHeight)
}

func zoomIn(recognizer: UIPinchGestureRecognizer){
    if recognizer.state == .changed{
        let savedScale=scaleNum
        scaleNum=recognizer.scale
        if scaleNum<1{
            scaleNum=1
        }
        else if scaleNum>3{
            scaleNum=3
        }
        if testcamera(posX: cam.position.x, posY: cam.position.y){
            cam.setScale(scaleNum)
        }
        else{
            scaleNum=savedScale
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
   let firstTouch=touches.first
    let location=(firstTouch?.location(in: self))!
    var posX=cam.position.x
    var posY=cam.position.y
    let previousLocation=firstTouch?.previousLocation(in: self)
    posX -= location.x - (previousLocation?.x)!
    posY -= location.y - (previousLocation?.y)!
    if testcamera(posX: posX, posY: posY){
        cam.position.x=posX
        cam.position.y=posY
    }

}

func testcamera(posX: CGFloat, posY: CGFloat)->Bool{
    var cameraRect : CGRect {
    let xx = posX - size.width/2*scaleNum
    let yy = posY - playableRect.height/2*scaleNum
        return CGRect(x: xx, y: yy, width: size.width*scaleNum, height: playableRect.height*scaleNum)
    }
    let backGroundRect=CGRect(x: background.position.x-background.frame.width/2, y: background.position.y-background.frame.height/2, width: background.frame.width, height: background.frame.height)
    return backGroundRect.contains(cameraRect)
}

}