我正在尝试平移和缩放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
}
}
}
答案 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)
}
}