我可以想到两种方法。
1) 弯道法
您可以使用 SKWarpGeometry 弯曲您的场景。从语义上讲,您会在游戏场景中设想一个 2 x 2 象限网格,由 3 x 3 点数据结构描述。你会稍微移动左右边缘,并使它们更小。而且你会让中心垂直边缘更长一点。
Apple 的文档还提到,基本上任何类型的节点(包括 SKEmitterNode)都可以通过将其放入 SKEffectNode 并对其应用扭曲来进行扭曲。见:https://developer.apple.com/documentation/spritekit/skwarpgeometrygrid/animate_the_warping_of_a_sprite?language=objc。
我们所要做的就是让一个效果节点成为一切的根节点,并对其应用扭曲。现在,这行得通,但只要其中有一个发射器,经线就会开始像癫痫一样抽搐。我认为这是一个错误。无论如何,我都会包含代码,以防它稍后修复,因为它应该根据文档工作。
let sourcePoints = [
// bottom row: left, center, right
vector_float2(0.0, 0.0),
vector_float2(0.5, 0.0),
vector_float2(1.0, 0.0),
// middle row: left, center, right
vector_float2(0.0, 0.5),
vector_float2(0.5, 0.5),
vector_float2(1.0, 0.5),
// top row: left, center, right
vector_float2(0.0, 1.0),
vector_float2(0.5, 1.0),
vector_float2(1.0, 1.0)
]
var destinationPoints = sourcePoints
// Bring lefts in, and make the edge shorter
destinationPoints[0] = vector_float2(0.1, 0.1)
destinationPoints[3] = vector_float2(0.1, 0.4)
destinationPoints[6] = vector_float2(0.1, 0.9)
// Bring rights in, and make the edge shorter
destinationPoints[2] = vector_float2(0.9, 0.1)
destinationPoints[5] = vector_float2(0.9, 0.4)
destinationPoints[8] = vector_float2(0.9, 0.9)
// Make the center edge longer
destinationPoints[1] = vector_float2(0.5, -0.2)
destinationPoints[4] = vector_float2(0.5, 0.7)
destinationPoints[7] = vector_float2(0.5, 1.2)
// Need to set the no warp geometry first
effectNode.warpGeometry = SKWarpGeometryGrid(columns: 2, rows: 2)
let newGeometry = SKWarpGeometryGrid(columns: 2, rows: 2,
sourcePositions: sourcePoints,
destinationPositions: destinationPoints)
effectNode.run(SKAction.warp(to: newGeometry, duration: 1.0)!)
使用的来源:
https://www.hackingwithswift.com/example-code/games/how-to-warp-a-sprite-using-skwarpgeometrygrid
http://sound-of-silence.com/?page=blog&sort=recent&count=0
2) Live Copy 方法
这更简单,代码更少,用途更广泛;你可以在这个雷曼传奇关卡https://youtu.be/7m5YQrucis8?t=1226 中做类似的事情。此外,它还有效。
基本上,我们的主 SKView 显示主场景。我们将添加一个显示复制场景的副本 SKView。复制场景中只有一个精灵节点。
在主场景的更新循环中,我们将抓取场景的扁平纹理并将其分配给复制场景中的精灵节点。作为场景委托的对象可以进入这个更新循环,因此我们将使视图控制器符合 SKSceneDelegate。
class Playground_VC: UIViewController, SKSceneDelegate {
var sprite: SKSpriteNode?
override func loadView() {
self.view = SKView()
}
var skView: SKView {
return self.view as! SKView
}
override func viewWillAppear(_ animated: Bool) {
let scene = SKScene(size: self.skView.bounds.size)
scene.backgroundColor = UIColor.clear
scene.delegate = self
self.skView.presentScene(scene)
let e = newEmitter()
scene.addChild(e)
e.position = self.skView.midPoint
self.createCopy()
}
func update(_ currentTime: TimeInterval, for scene: SKScene) {
// Grab the root texture and assign to the sprite that's in the copy scene
let t = self.skView.texture(from: self.skView.scene!)
self.sprite?.texture = t
}
func createCopy() {
// Make a new SKView that's 4 times smaller
var f = self.skView.bounds
f.size.height *= 0.4
f.size.width *= 0.4
let copy = SKView(frame: f)
copy.presentScene(SKScene(size: f.size))
self.view.addSubview(copy)
let sprite = SKSpriteNode(texture: nil, size: f.size)
copy.scene?.addChild(sprite)
self.sprite = sprite
sprite.position = CGPoint(x: f.size.width / 2, y: f.size.height / 2)
}
func newEmitter() -> SKEmitterNode {
return SKEmitterNode(fileNamed: "Particle.sks")!
}
}
您在主 SKView 上执行的任何操作,例如在 3D 空间中倾斜它,都不应影响副本的外观,因为游戏场景不受这些操作的影响。