我正在SceneKit制作一款即将完成的3D游戏。该应用程序包含一个视图,其中包含一个SCNView和两个带按钮的小视图。
我发现当我启动游戏时,在启动画面消失后大约需要两到三秒才能在SCNView中显示场景。我在同一时间看到一个带有按钮的白色屏幕。我从COLLADA文件中将主场景加载到SCNView中,并从另一个Collade文件中添加两个节点。我还以编程方式添加一些节点并将物理添加到某些节点。所有这些都发生在我的viewDidLoad方法中。
我使用的代码:
@IBOutlet var scnView: SCNView!
@IBOutlet var soundButton: UIButton!
@IBOutlet var statsButton: UIButton!
var radAngle:Float = 0.0 // Angle of number
var maxAngle:Float = (120)/180 * Float(M_PI) // Angle of open numbers (up)
let dice1: SCNNode // die 1
let dice2: SCNNode // die 2
let leftCameraNode:SCNNode // Camera for rules
let rightCameraNode:SCNNode // Camera for box
let scoreCameraNode = SCNNode() // Camera for the statistics
var gameEndedNode: SCNNode = SCNNode() // Node when game ended game
var dices:[SCNNode] // The two dice nodes
var dicePreviousTotal:Int = 0 // thrown number (total)
var diceCurrentTotal:Int = 0 // compare with previous
var numberNames:[String] = ["numberBlock_1", "numberBlock_2", "numberBlock_3", "numberBlock_4", "numberBlock_5", "numberBlock_6", "numberBlock_7", "numberBlock_8", "numberBlock_9"] // Names of all NumberBlocks
var numbersUp:[Int] = [] // Indicate for every numbers if it is up (open)
var numbersRound:[Int] = [] // numbers from up to down this round
var longPressLocation:CGPoint = CGPointMake(0.0, 0.0) //location of long press
var gameState = 0 // 0:Ended, 1:Throwing, 2:Flipping
var soundMute = false // If sound is muted
var timesPlayed:Int = 0 // Times played the game
var timesShut:Int = 0 // Times that the box has been shut
var shutPercentage:Float = 0.0 // Percentage of above
let scene = SCNScene(named: "ShutTheBox.scnassets/ShutTheBox.dae")! // Scene of the box
let noteScene = SCNScene(named: "bladpotlood.scnassets/blad.dae")! // Scene of the rules note
var soundManager = SoundManager() // The class that manages the sound
var soundPlayed1 = false // Indicate if sound has been played this round for die 1
var soundPlayed2 = false // Indicate if sound has been played this round for die 2
let flickSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Flick", ofType: "m4a")!) // Flick sound
let diceSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Two Dice", ofType: "wav")!) // Diceroll sound
var timer: NSTimer = NSTimer() // Timer to check if the dice stopped rolling
var throwDuration:Float = 0.0 // Duration of one throw to prevent wrong throw
var gameEndedText:String = "" // String of text shown at game and
var scoreText:String = "" // String of text with the statistics
var scoreTextGeometry: SCNText = SCNText() // Geometry of above
var timesPlayedNode:SCNNode = SCNNode() // Node for above
let myGray = SCNMaterial() // Material Gray
let myWood = SCNMaterial() // Material Wood
required init(coder aDecoder: NSCoder) {
dice1 = scene.rootNode.childNodeWithName("Dice1", recursively: false)!
dice2 = scene.rootNode.childNodeWithName("Dice2", recursively: false)!
dices = [dice1,dice2]
leftCameraNode = noteScene.rootNode.childNodeWithName("Camera", recursively: false)!
rightCameraNode = scene.rootNode.childNodeWithName("Camera", recursively: false)!
myGray.diffuse.contents = UIColor.darkGrayColor()
myWood.diffuse.contents = UIImage(named: "LightWoodTexture.jpg")
super.init(coder:aDecoder)
}
func initGame() {
// -- Start a new game -- //
gameState = 1
numbersUp = [1,1,1,1,1,1,1,1,1]
dicePreviousTotal = 0
for number in numberNames {
scene.rootNode.childNodeWithName(number, recursively: false)!.eulerAngles = SCNVector3Make(-maxAngle, 0.0, 0.0)
}
}
override func viewDidLoad() {
super.viewDidLoad()
retreiveScore()
// Setup of scene
scnView.scene = scene
scnView.allowsCameraControl = false
scnView.showsStatistics = false
scnView.backgroundColor = UIColor.blackColor()
scene.physicsWorld.gravity = SCNVector3Make(0.0, -9.8, 0.0)
scene.physicsWorld.contactDelegate = self
// Setup camera to see statistics
scoreCameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(scoreCameraNode)
scoreCameraNode.position = SCNVector3Make(18.5, 9, 5)
scoreCameraNode.rotation = SCNVector4Make(-1.0, 0.0, 0.0, 1.00)
// create and add a light to the scene, remove existing
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 15, z: 10)
scene.rootNode.addChildNode(lightNode)
scene.rootNode.childNodeWithName("Lamp", recursively: false)?.removeFromParentNode()
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.blackColor()
scene.rootNode.addChildNode(ambientLightNode)
// add gamerules note and camera
let noteNode = SCNNode()
noteNode.addChildNode(noteScene.rootNode.childNodeWithName("Plane", recursively: false)!)
noteNode.addChildNode(leftCameraNode)
noteNode.position = SCNVector3Make(-12, 0.02, 0)
noteNode.rotation = SCNVector4Make(0.0, 1.0, 0.0, 0.2)
scene.rootNode.addChildNode(noteNode)
// create score text and node
if timesShut != 0 {
shutPercentage = Float(timesShut/timesPlayed * 100)
}
scoreText = "Times played:\t\(timesPlayed) \nShut the Box:\t\(shutPercentage)%"
scoreTextGeometry = SCNText(string: scoreText, extrusionDepth: 5)
scoreTextGeometry.font = UIFont(name: "Futura-CondensedExtraBold", size: 20)
scoreTextGeometry.chamferRadius = 0.8
scoreTextGeometry.materials = [myWood, myGray, myGray]
timesPlayedNode = SCNNode(geometry: scoreTextGeometry)
timesPlayedNode.scale = SCNVector3Make(0.05, 0.05, 0.05)
timesPlayedNode.rotation = SCNVector4Make(-1.0, 0.0, 0.0, Float(M_PI_4))
timesPlayedNode.position = SCNVector3Make(14.0, 0.0, 0.0)
timesPlayedNode.name = "timesPlayed"
scene.rootNode.addChildNode(timesPlayedNode)
// create boundary box
let floorBorderGeometry = SCNBox(width: 100, height: 4.0, length: 100, chamferRadius: 0.0)
let floorPhysicsShape = SCNPhysicsShape(geometry: floorBorderGeometry, options: nil)
let floorNode = SCNNode()
floorNode.position = SCNVector3Make(0.0, -1.85, 0.0)
floorNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: floorPhysicsShape)
scene.rootNode.addChildNode(floorNode)
floorNode.physicsBody!.friction = 0.8
floorNode.physicsBody!.categoryBitMask = 0b010
floorNode.physicsBody!.collisionBitMask = 0b100
let leftBorderGeometry = SCNBox(width: 4, height: 100, length: 100, chamferRadius: 0.0)
let leftBorderPhysicsShape = SCNPhysicsShape(geometry: leftBorderGeometry, options: nil)
let leftBorderNode = SCNNode()
leftBorderNode.position = SCNVector3Make(-9.32, 0, 0)
leftBorderNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: leftBorderPhysicsShape)
scene.rootNode.addChildNode(leftBorderNode)
leftBorderNode.physicsBody!.categoryBitMask = 0b001
leftBorderNode.physicsBody!.collisionBitMask = 0b100
let rightBorderNode = SCNNode()
rightBorderNode.position = SCNVector3Make(9.32, 0, 0)
rightBorderNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: leftBorderPhysicsShape)
scene.rootNode.addChildNode(rightBorderNode)
rightBorderNode.physicsBody!.categoryBitMask = 0b001
rightBorderNode.physicsBody!.collisionBitMask = 0b100
let frontBorderGeometry = SCNBox(width: 100, height: 100, length: 4, chamferRadius: 0.0)
let frontBorderPhysicsShape = SCNPhysicsShape(geometry: frontBorderGeometry, options: nil)
let frontBorderNode = SCNNode()
frontBorderNode.position = SCNVector3Make(0, 0, 7.85)
frontBorderNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: frontBorderPhysicsShape)
scene.rootNode.addChildNode(frontBorderNode)
frontBorderNode.physicsBody!.categoryBitMask = 0b001
frontBorderNode.physicsBody!.collisionBitMask = 0b100
let backBorderNode = SCNNode()
backBorderNode.position = SCNVector3Make(0, 0, -4.35)
backBorderNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: frontBorderPhysicsShape)
scene.rootNode.addChildNode(backBorderNode)
backBorderNode.physicsBody!.categoryBitMask = 0b001
backBorderNode.physicsBody!.collisionBitMask = 0b100
let topBorderNode = SCNNode()
topBorderNode.position = SCNVector3Make(0.0, 50.0, 0.0)
topBorderNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: floorPhysicsShape)
scene.rootNode.addChildNode(topBorderNode)
topBorderNode.physicsBody!.categoryBitMask = 0b001
topBorderNode.physicsBody!.collisionBitMask = 0b100
// Add physics to the dice
for dice in dices {
dice.physicsBody = SCNPhysicsBody.dynamicBody()
dice.physicsBody!.mass = 1.5
dice.physicsBody!.restitution = 0.0
dice.physicsBody!.friction = 0.8
dice.physicsBody!.damping = 0.1
dice.physicsBody!.categoryBitMask = 0b100
dice.physicsBody!.collisionBitMask = 0b001 | 0b010 | 0b100
}
// Add body to the numbertiles
for name in numberNames {
var numberNode = scene.rootNode.childNodeWithName(name, recursively: false)!
numberNode.physicsBody = SCNPhysicsBody.kinematicBody()
numberNode.physicsBody!.categoryBitMask = 0b001
numberNode.physicsBody!.collisionBitMask = 0b100
}
// add a tap, pan and longPress gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap:")
let panGesture = UIPanGestureRecognizer(target: self, action: "handlePan:")
let longPressGesture = UILongPressGestureRecognizer(target: self, action:"handleLongPress:")
var gestureRecognizers = [AnyObject]()
gestureRecognizers.append(tapGesture)
gestureRecognizers.append(panGesture)
gestureRecognizers.append(longPressGesture)
if let existingGestureRecognizers = scnView.gestureRecognizers {
gestureRecognizers.extend(existingGestureRecognizers)
}
scnView.gestureRecognizers = gestureRecognizers
// initialize game
initGame()
}
正如您所见,我创建了35个全局变量,并且viewDidLoad中有许多行(130!)代码。我想这就是加载这么长时间的原因。我稍后需要在多个方法中使用变量,因此不能将它们更改为局部变量。
我知道这可能是糟糕的编码,但这是我第一次尝试创建一个完整的工作游戏,这与我所遵循的许多教程和课程完全不同且更大。我还在学习..
你能否就如何在游戏开启时缩短SCNView的渲染时间给出一些建议?
非常感谢所有帮助!