我有一个表视图,在其中一个单元格中有一个UIView,它承载一个SKScene,它有几个云从右到左以不同的速度浮动。 FPS:60,屏幕上总是出现不超过5个节点。 但CPU使用率仍然很高。我该怎么办呢?
import UIKit
import SpriteKit
class AnimationView: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = CloudsScene(size: view.bounds.size)
let skView = view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
skView.ignoresSiblingOrder = true
scene.scaleMode = .resizeFill
skView.presentScene(scene)
}
}
SKScene课程:
import SpriteKit
func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)}
func - (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y)}
func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x * scalar, y: point.y * scalar)}
func / (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x / scalar, y: point.y / scalar)}
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
extension CGPoint {
func length() -> CGFloat {
return sqrt(x*x + y*y)
}
func normalized() -> CGPoint {
return self / length()
}
}
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Cloud : UInt32 = 0b1 // 1
static let Projectile: UInt32 = 0b10 // 2
}
class CloudsScene: SKScene, SKPhysicsContactDelegate {
// 1
let sun = SKSpriteNode(imageNamed: "Sun")
var cloudsDestroyed = 0
var background = SKSpriteNode(imageNamed: "Mountains_Bkgd")
override func didMove(to view: SKView) {
backgroundColor = SKColor.white
background.zPosition = 0
background.size = CGSize(width: frame.size.width, height: frame.size.height)
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
sun.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
sun.zPosition = 1
addChild(sun)
physicsWorld.speed = 0.9999
physicsWorld.gravity = CGVector.zero
physicsWorld.contactDelegate = self
run(SKAction.repeatForever(
SKAction.sequence([
SKAction.run(addCloud),
SKAction.wait(forDuration: 6)
])
))
}
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
func addCloud() {
//print("add cloud")
//Choose random cloud out of 6 images
let randomNumber = arc4random_uniform(5)
let imageName = "Cloud\(randomNumber)"
// Create sprite
let cloud = SKSpriteNode(imageNamed: imageName)
cloud.physicsBody = SKPhysicsBody(rectangleOf: cloud.size) // 1
cloud.physicsBody?.isDynamic = true // 2
cloud.physicsBody?.categoryBitMask = PhysicsCategory.Cloud // 3
cloud.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
cloud.physicsBody?.collisionBitMask = PhysicsCategory.None // 5
// Determine where to spawn the cloud along the Y axis
let actualY = random(min: size.height/2, max: size.height - cloud.size.height/2)
//print(actualY)
// Position the cloud slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
cloud.position = CGPoint(x: size.width + cloud.size.width/2, y: actualY)
cloud.zPosition = 2
// Add the cloud to the scene
addChild(cloud)
// Determine speed of the cloud
let actualDuration = random(min: CGFloat(12.0), max: CGFloat(24.0))
// Create the actions
let actionMove = SKAction.move(to: CGPoint(x: -cloud.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
let loseAction = SKAction.run() {
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
}
cloud.run(SKAction.sequence([actionMove, loseAction, actionMoveDone]))
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touches Ended")
//run(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))
// 1 - Choose one of the touches to work with
guard let touch = touches.first else {
return
}
let touchLocation = touch.location(in: self)
// 2 - Set up initial location of projectile
let projectile = SKSpriteNode(imageNamed: "location")
projectile.position = sun.position
projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.isDynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Cloud
projectile.physicsBody?.collisionBitMask = PhysicsCategory.None
projectile.physicsBody?.usesPreciseCollisionDetection = true
// 3 - Determine offset of location to projectile
let offset = touchLocation - projectile.position
// 4 - Bail out if you are shooting down or backwards
if (offset.x < 0) { return }
// 5 - OK to add now - you've double checked position
addChild(projectile)
// 6 - Get the direction of where to shoot
let direction = offset.normalized()
// 7 - Make it shoot far enough to be guaranteed off screen
let shootAmount = direction * 1000
// 8 - Add the shoot amount to the current position
let realDest = shootAmount + projectile.position
// 9 - Create the actions
let actionMove = SKAction.move(to: realDest, duration: 2.0)
let actionMoveDone = SKAction.removeFromParent()
projectile.run(SKAction.sequence([actionMove, actionMoveDone]))
}
func projectileDidCollideWithCloud(projectile: SKSpriteNode, cloud: SKSpriteNode) {
print("Hit")
projectile.removeFromParent()
cloud.removeFromParent()
cloudsDestroyed += 1
if (cloudsDestroyed > 30) {
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("did Begin")
// 1
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 2
if ((firstBody.categoryBitMask & PhysicsCategory.Cloud != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) {
if let cloud = firstBody.node as? SKSpriteNode, let
projectile = secondBody.node as? SKSpriteNode {
projectileDidCollideWithCloud(projectile: projectile, cloud: cloud)
}
}
}
}