これらのフレームで構成されたアトラス アニメーションがある「Hello World」スプライト キット テンプレートを使用して、小さなテスト プロジェクトを実行しました。
-
この騎士を見せたいのですが、それはアニメーションです。
DYNAMIC物理体を設定したい。
したがって、ツールを使用して単一のフレームを分離し、atlasc
フォルダーを作成したので、コードは次のようになります。
import SpriteKit
class GameScene: SKScene {
var knight: SKSpriteNode!
var textures : [SKTexture] = [SKTexture]()
override func didMove(to view: SKView) {
self.physicsWorld.gravity = CGVector(dx:0, dy:-2)
let plist = "knight.plist"
let genericAtlas = SKTextureAtlas(named:plist)
let filename : String! = NSURL(fileURLWithPath: plist).deletingPathExtension!.lastPathComponent
for i in 0 ..< genericAtlas.textureNames.count
{
let textureName = (String(format:"%@%02d",filename,i))
textures.append(genericAtlas.textureNamed(textureName))
}
if textures.count>0 {
knight = SKSpriteNode(texture:textures.first)
knight.zPosition = 2
addChild(knight)
knight.position = CGPoint(x:self.frame.midX,y:self.frame.midY)
}
//
self.setPhysics()
let animation = SKAction.animate(with: textures, timePerFrame: 0.15, resize: true, restore: false)
knight.run(animation, withKey:"knight")
}
func setPhysics() {
knight.physicsBody = SKPhysicsBody.init(rectangleOf: knight.size)
knight.physicsBody?.isDynamic = false
}
}
出力は次のとおりです。
ご覧のとおり、physicsBody
は STATICです。アニメーションを尊重しません。アニメーション中にテクスチャの寸法/サイズが変化しphysicsBody
、アクション中に同じままである を変更しないため、これは正常です。
SKAction.animate
ソースに続いて、 中に を変更できるメソッドはありませんphysicsBody
。
私たちは使用しますが:
/**
Creates an compound body that is the union of the bodies used to create it.
*/
public /*not inherited*/ init(bodies: [SKPhysicsBody])
アニメーションの各フレームのボディを作成するために、これらのボディはシーン内にすべて一緒に残り、この写真のような醜い奇妙な状況を作り出します:
したがって、それを行う正しい方法は、アニメーション中にフレームをインターセプトし、その場で変更physicsBody
することです。update()
の方法も使えますSKScene
が、拡張を考えていました。
animation
私の考えは、アクションを と組み合わせて、最初のアクションの実行をチェックする別のカスタム アクションを作成し、現在のフレームと配列にSKAction.group
一致するフレームをインターセプトし、外部メソッドの起動を変更することです。この場合は.knight.texture
textures
physicsBody
setPhysicsBody
それから、私はこれを書きました:
extension SKAction {
class func animateWithDynamicPhysicsBody(animate:SKAction, key:String, textures:[SKTexture], duration: TimeInterval, launchMethod: @escaping ()->()) ->SKAction {
let interceptor = SKAction.customAction(withDuration: duration) { node, _ in
if node is SKSpriteNode {
let n = node as! SKSpriteNode
guard n.action(forKey: key) != nil else { return }
if textures.contains(n.texture!) {
let frameNum = textures.index(of: n.texture!)
print("frame number: \(frameNum)")
// Launch a method to change physicBody or do other things with frameNum
launchMethod()
}
}
}
return SKAction.group([animate,interceptor])
}
}
この拡張機能を追加して、コードのアニメーション部分を次のように変更します。
//
self.setPhysics()
let animation = SKAction.animate(with: textures, timePerFrame: 0.15, resize: true, restore: false)
let interceptor = SKAction.animateWithDynamicPhysicsBody(animate: animation, key: "knight", textures: textures, duration: 60.0, launchMethod: self.setPhysics)
knight.run(interceptor,withKey:"knight")
}
func setPhysics() {
knight.physicsBody = SKPhysicsBody.init(rectangleOf: knight.size)
knight.physicsBody?.isDynamic = false
}
これは最終的に機能し、出力は次のとおりです。
この結果を得るためのより良い方法、またはより洗練された方法を知っていますか?