我们现在已经有一款可以正常工作的游戏,只是缺少了一些到目前为止尚未涉及的部分。 因此,本部分教程的目标是立即添加它们并对其进行一些润饰。

缺少的部分
声音
声音是游戏中最重要的部分,也是最被低估的部分之一。 您将看到并感觉到第5部分与第6部分的不同之处仅在于我们现在将具有声音效果。 SceneKit使集成它们变得非常容易,并且还支持空间声音(3D声音)。 因此,我们仅向给定节点添加声音效果,SceneKit自行进行所有处理。 这样,添加声音就很容易了,我还可以通过创建GameSound类以一种简单的方式在游戏中做到这一点,我为在游戏中使用的每种声音实现了它自己的功能。 有了这个小小的抽象,我就可以承担一个责任,因此很容易更改,并且也很重要,编译器能够检查是否存在声音效果。 但是自己看:
- [RR访谈]游戏公司中的游戏书呆子
- 当今的游戏行业正在发生变化。 – Scott Jorgensen –中
- 一年内开发42款游戏—疯狂的游戏开发
- DreamTeam CS:GO旅程地图已经到来
- 为什么HTML5开发人员应该对Kik上的机器人感到兴奋
import AudioToolbox.AudioServices
class GameSound {
private static let explosion = SCNAudioSource(fileNamed: "sounds/explosion.wav")
private static let fire = SCNAudioSource(fileNamed: "sounds/fire.wav")
private static let bonus = SCNAudioSource(fileNamed: "sounds/bonus.wav")
static func vibrate() {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
}
private static func play(_ name: String, source: SCNAudioSource, node: SCNNode) {
let _ = GameAudioPlayer(name: name, source: source, node: node)
}
static func explosion(_ node: SCNNode) {
guard explosion != nil else { return }
GameSound.play("explosion", source: GameSound.explosion!, node: node)
GameSound.vibrate()
}
static func fire(_ node: SCNNode) {
guard fire != nil else { return }
GameSound.play("fire", source: GameSound.fire!, node: node) GameSound.vibrate()
}
static func bonus(_ node: SCNNode) {
guard bonus != nil else { return }
GameSound.play("bonus", source: GameSound.bonus!, node: node)
}
这是将3D声音效果实现到基于SceneKit的游戏所需的全部。 不错,不是吗? 也许您已经注意到,我使用了一个名为GameAudioPlayer的类而不是SCNAudioPlayer 。 GameAudioPlayer是SCNAudioPlayer的子类, 它实现了一件重要的事情:完成播放后自动删除声音。 除此之外,其余所有操作均由SceneKit本身完成。
class GameAudioPlayer : SCNAudioPlayer {
private var _node: SCNNode!
init(name: String, source: SCNAudioSource, node: SCNNode) {
super.init(source: source)
node.addAudioPlayer(self)
_node = node
rbDebug("GameAudioPlayer: play \(name)")
self.didFinishPlayback = {
rbDebug("GameAudioPlayer: stopped \(name)")
self._node.removeAudioPlayer(self)
}
}
}
现在先尝试游戏,看看有声音时感觉如何。 要添加新效果,只需添加一个新功能和一个音频文件,您就可以立即使用它。
先进的HUD技术
我想提到的第二件事是一个好点系统和在HUD中使用的高级动画。 每当我们在游戏中碰到某些东西(例如环飞过槽)或射击飞机时,我们都会得到分数。 也许您已经在其他游戏中看到这些点在动画中被抵消了。 我还已经在HUD中实现了该功能(请参阅HUD.swift ),并且您可以看到它看起来要好得多,然后仅显示要点。 这些东西(当然还包括出色的游戏性)使游戏与最终的出色游戏有所不同,我们将在本教程的第10部分中看到更多这些技巧 。
private func changePoints(_ pointsToAdd: Int, total: Int, count: Int) {
_totalPoints += pointsToAdd
points = _totalPoints
let scaling: CGFloat = 1.5
let action = SKAction.zoomWithNode(_points, amount: CGPoint.make(scaling, scaling), oscillations: 1, duration: 0.01)
_points.run(action)
if count < total {
Run.after(0.01, {
self.changePoints(1, total: total, count: count+1)
})
}
}
子弹和敌机
但是,这部分最大的改进可能是这样一个事实,即我们现在拥有敌机,而且我们以及他们也可以发射子弹! 此附加功能需要对当前代码进行一些重构(经常执行某些操作)。 我添加了一个新的Plane类,并将Player类作为它的子类。 新的敌人职业也是如此。 然后,我将代码(对于Player飞机和敌人飞机)都相同的代码移到了plane类,并在其中加入了Player飞机特有的内容。 在GameLevel类( addEnemies )中,将创建飞机并向我们飞行。
但是我们不仅希望他们飞行,我们还希望我们能够发射子弹,而敌机也可以对付我们。
子弹班
您现在应该知道实现这种技术所需的所有技术。 是的,它也将是GameObject的子类,并且还使用碰撞检测来检查我们是否击中了物体或子弹击中了我们; Player对象。 我们也可以将所有创建的类添加到_gameObjects列表中。 但是我将使用项目符号来展示游戏开发技术的另一个方面:**重用*。 因为我们创建了很多项目符号,所以当状态不再* .alive时,再次使用此SceneKit节点是有意义的 。 为此,我们创建一个数组,其中包含我们在GameLevel中发射的所有子弹:
func fireBullet(enemy: Bool, position: SCNVector3, sideDistance: CGFloat = 0, fallDistance: CGFloat = 0) -> Bullet {
让方向:PlaneDirection =敌人? .down:.up
// Search in list if we have an unused bullet
for bullet in _bullets {
if (bullet.state == .died && bullet.enemy == enemy) {
// Ok, use this
bullet.isHidden = false
bullet.state = .initialized
bullet.position = position
bullet.fire(direction: direction, sideDistance: sideDistance, fallDistance: fallDistance, speed: 3.0)
rbDebug("Reuse bullet \(bullet)")
return bullet
}
}
// No bullets free, so create one
let bullet = Bullet(enemy: enemy)
bullet.position = position
_bullets.append(bullet)
self.rootNode.addChildNode(bullet)
bullet.fire(direction: direction, sideDistance: sideDistance, fallDistance: fallDistance, speed: 3.0)
return bullet
}
这样,我们可以节省很多子弹,并且可以通过在给定时间后将其从内存中删除来进一步改善。 练习:尝试完全实现!
我们从这里去哪里?
游戏从未真正完成过,您可以随时改进或添加新功能。 但请记住:
游戏开发(和一般软件开发)中最重要的是发布。
因此,首先要专注于游戏的主要(关键)游戏功能。 完成并使其有趣。 然后遍历您想让用户看到(甚至更好)的所有功能!
通常,您仍然可以学到很多有关游戏开发的知识,但是从第1到第6部分的所有内容中,您都有良好的基础开始自己的游戏。
接下来的三章将介绍如何在不同的(Apple)平台上使用SceneKit,以及在ARKit中使用增强现实。 作为奖励章节,第10章将介绍一些高级SceneKit功能,以进一步完善您的游戏。
教程章节:
–第1部分–建立地形
–第2部分–创建一个真实的玩家游戏对象
–第3部分–为您的地形增添生命
–第4部分–实施游戏循环
–第5部分–使用CoreMotion平稳地飞行
–第六部分–完成游戏(缺少的部分)
–第7部分– ARKit:在您的环境中玩
–第8部分–多平台:我们在macOS上的游戏
–第9部分– tvOS:出色的游戏平台
–第10部分-高级SceneKit(有待改进)
别忘了……再次链接到源代码