基于SpriteKit+Swift开发打竹块游戏(上篇)

[中文教程]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看311 回复回复3 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 311|回复: 3
收起左侧

[中文教程] 基于SpriteKit+Swift开发打竹块游戏(上篇)

[复制链接]
swifter 发表于 2016-6-19 17:43:20 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
本帖最后由 swifter 于 2016-6-19 17:49 编辑

在本系列教程(两部分)中,你将要学习如何使用SpriteKit来开发一款Breakout游戏。其中,加入了完整的碰撞检测技术,使用物理效果控制小球弹跳,通过触摸来拖动挡板,游戏状态控制等。

基于SpriteKit+Swift开发打竹块游戏(上篇)
基于SpriteKit+Swift开发打竹块游戏(下篇)




1、简介

SpriteKit是苹果公司推出的跑在iOS和OS X上的游戏开发框架。这个工具不仅提供了强有力的图形功能,而且还包括一个易于使用的物理引擎。最重要的是,你可以使用你熟悉的工具 ——Swift,Xcode和Interface Builder完成所有的工作!你可以用SpriteKit做很多的事情;但是,想了解它是如何工作的最佳方法就是使用它开发一个简单的游戏。

在本系列教程(两部分)中,你将要学习如何使用SpriteKit来开发一款Breakout游戏。其中,加入了完整的碰撞检测技术,使用物理效果控制小球弹跳,通过触摸来拖动挡板,游戏状态控制等。




2、开始

作为初始准备,建议你一定要先下载本教程对应的初始项目。此项目是使用标准的Xcode游戏模板创建的。所有的资源和状态类都已经被导入到项目中,这样可以节省您的一点时间。随着进一步阅读,你会了解更多的游戏状态。

你不妨先花点时间来熟悉一下整个项目。为此运行命令“Build”和”Run“,你会看到一个横向模式的灰色屏幕。请参考下图。

基于SpriteKit+Swift开发打竹块游戏(上篇) 1

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 1





3、Sprite Kit Visual Editor简介

让我们从配置场景文件开始工作吧。为此,请打开GameScene.sks文件。这是一个已链接到你的Sprite Kit场景的可视化编辑器,你可以从游戏的 GameScene.swift文件中访问其中已有的每一个元素。

首先,你将调整场景的大小,使其适合您在本教程中介绍的目标屏幕:一个iPhone 6屏幕。为此,你可以在位于Xcode窗口右上角的Attributes inspector的Scene部分完成这一操作。如果你看不到Attributes inspector,您可以通过 View\Utilities\Show Attributes inspector来访问它。请将场景的大小设置为 568 × 320,如下面的屏幕快照所示。

基于SpriteKit+Swift开发打竹块游戏(上篇) 2

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 2


[注意]如果您的资源库中包含了为适应多屏幕缩放因子(即 1 x,2x,3 x等)准备的图片等资源的话,Sprite Kit将自动在当前运行的设备使用正确的资源文件。

现在,我们来考虑游戏的背景。如下面的屏幕快照所示,从Xcode窗口的右下角的对象库面板上拖出一个Color Sprite。如果你看不到对象库面板,那么可以从菜单栏选择View\Utilities\Show Object Library。

基于SpriteKit+Swift开发打竹块游戏(上篇) 3

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 3


请使用属性检查器将位置更改为284,160,把它的纹理设置为bg。

现在,你可以生成并运行一下游戏工程,欣赏一下你的游戏的背景显示情况。

基于SpriteKit+Swift开发打竹块游戏(上篇) 4

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 4


一旦你建立了拥有背景的横屏场景,那么接下来就可以往其中添加小球了!仍然在GameScene.sks文件中,将一个新的Color Sprite拖动到场景中。然后,把它的名称改为ball,纹理设置为ball,位置修改为284,220。然后,再把它的Z位置属性值也设置为2,以确保小球出现在背景上。

现在,生成和运行你的项目,你会看到小球已经出现在屏幕上,如图所示。

基于SpriteKit+Swift开发打竹块游戏(上篇) 5

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 5


然而,到目前为止,我们的游戏还不能动起来,这是因为我们还没有添加物理部分呢。




4、物理引擎

在Sprite Kit中,你需要工作在两种环境中:你在屏幕上看到的图形世界和物理世界,这决定了对象的移动和交互的方式。

在使用Sprite Kit物理引擎时,你需要做的第一件事是根据你的游戏的需要改变世界。世界对象是在使用Sprite Kit时管理所有的对象和物理模拟的主要对象。它还设置了物理机构加入到世界对象中需要的重力属性。默认的重力值是-9.81,因此类似于地球的实际重力值。所以,只要你在世界中添加一个物体,它就会往下落。

一旦配置了世界对象,你就可以往此世界对象中添加根据物理原则与它进行交互的东西。为此,最通常的方法是创建一个精灵 (图形) 并设置它的物理body。物体的body属性与世界决定了物体的移动方式。

Body可以是受物理力量影响的动态对象(如球,星星,小鸟......),或者是不受物理力量影响的静态对象(平台、墙......)。当创建一个Body时,你可以设置各种属性,如形状、密度、摩擦力,等等。这些属性将严重影响Body在世界范围内的行为。

当定义一个Body时,你可能会担心其大小和密度的单位。在内部,Sprite Kit使用公制(SI单位)。但是,在你的游戏中你通常不需要担心实际的力量和质量,只要你使用一致的值就行。
一旦你在世界中添加了所有的Body,Sprite Kit就会接管过控制权,并进行仿真。

为了设置第一个物理Body,你需要选择刚刚添加的小球节点并从属性检查器的Physics Definition一节中选择Body Type下的Bounding Circle并设置以下属性值︰

  • 取消勾选“Allows Rotation”
  • 设置Friction为0
  • 设置Restitution为1
  • 将linear Damping(线性阻尼)设置为0
  • 设置角阻尼(Angular Damping)为0


基于SpriteKit+Swift开发打竹块游戏(上篇) 6

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 6

给小球添加物理特性

在这里,你创建了一个基于体积的物理Body,其形式为圆圈,具有与小球精灵完全相同的尺寸。这个物理Body受外力或冲动的影响,并能够与其他物体发生碰撞。

下面具体介绍一下它的属性。

  • Allows Rotation:指定是否允许旋转。在本例中,你不希望小球旋转。
  • Friction:这个属性也很简单,在我们的例子中要除去所有的摩擦。
  • Restitution:是指对象的弹力。其值设置为1意味着,当小球与物体碰撞时将保持原来完整的弹性。简言之,这意味着:小球会以与最初同等的作用力弹回来。
  • Linear Damping(线性阻尼):通过减少物体的线性速度来模拟流体或空气摩擦。在本例游戏中,小球移动时不应该减速。所以,在上面你需要设置阻尼为0。
  • Angular Damping(角阻尼):除了角速度外,它与线性阻尼是相同的。当你不允许球旋转时将此值设置为可选的。


[注意]通常情况下,最好是让物理Body与玩家看到的极其相似。对于小球来说,我们已经做到完美的匹配。然而,当你需要使用更复杂的形状时,要格外小心,因为很复杂的Body意味着高性能的系统资源消耗。自从IOS 8和Xcode 6以来,Sprite Kit支持alpha蒙版Body类型(alpha masks body types),这将自动地把精灵的形状用作其物理Body的形状,但仍然要小心使用,因为这也可以降低系统性能。

现在,我们再一遍生成并运行工程。如果你反应足够迅速,你应该看到小球从场景中落下,最后消失在屏幕的底部,如图所示。

基于SpriteKit+Swift开发打竹块游戏(上篇) 7

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 7


这种现象的出现存在两个原因︰首先,场景的默认重力模拟了地球重力——沿x轴方向值为0而沿y轴方向是-9.8。第二,你的场景的物理世界是没有界限的,尚无法用作封闭小球的笼子。现在,让我们着手解决这个问题!




5、把小球关起来

基于SpriteKit+Swift开发打竹块游戏(上篇) 8

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 8

把小球关起来的效果

现在,请打开文件GameScene.swift并把以下代码行添加到didMoveToView(_方法的最后,用来创建一种围绕屏幕的无形的障碍︰

[Swift] 纯文本查看 复制代码
// 1 
 
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
 
// 2 
 
borderBody.friction = 0 
 
// 3 
 
self.physicsBody = borderBody 


让我们分析一下这行代码︰

(1)创建一个基于边缘(edge-based)的Body。与你添加到小球上的基于体积(volume-based)的Body相比,基于边缘的Body并没有质量或体积,并且不受外力或冲量的影响。

(2)我们把摩擦力设置为0,这样,小球与边界障碍发生碰撞时其运动就不会减慢。相反,你想产生一种完美的效果,此时小球沿着它撞击的屏障以相同的角度离开。

(3)你可以设置为每个节点设置一个物理Body。然后,将它添加到场景中。注︰SKPhysicsBody的坐标是相对于节点位置的。

再次运行你的项目,你现在应该看到像以前一样的小球下落情景,但是现在当它降落到笼子的底部边缘时它会回弹回来。因为你从与笼子和环境的接触(Contact)中去除了摩擦力,并且设置小球的变形为完全弹性形变,因此,小球会永远地那样反弹运动下去。

基于SpriteKit+Swift开发打竹块游戏(上篇) 9

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 9


为了让小球运动效果更为圆满,让我们删除重力并施加单脉冲,这样它就会沿着屏幕永远弹起弹落并运动下去。




6、永久性弹性运动

现在,我们让小球滚动起来(实际上还是弹起)。在文件GameScene.swift中在紧邻上面添加的代码行的后面添加以下代码:

[Swift] 纯文本查看 复制代码
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0) 
 
let ball = childNodeWithName(BallCategoryName) as! SKSpriteNode 
 
ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0)) 


这段新代码首先从场景中删除所有的重力,然后从场景的子节点上检索到小球并应用脉冲效果。脉冲能够把一种立即生效的力施加到物理Body上,从而让它朝着一个特定的方向(在本例中,沿对角线方向向右)运动。一旦小球设置为运动,它会简单地在屏幕上反弹起来,这是因为您刚添加了屏障部分!

现在,是时候再去试试了!当你编译并运行该项目时,您应该看到一个小球不断跳跃在屏幕上——酷极了!

基于SpriteKit+Swift开发打竹块游戏(上篇) 10

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 10





7、添加挡板

如果没有挡板,则不能称其为一款打竹块游戏,是不是?

现在,打开GameScene.sks文件来使用Visual Editor生成挡板(还有它的同伴物理Body),方式差不多就像你在场景的底部中间位置放置一个Color Sprite一样,然后设置下列属性值:

  • Name = paddle
  • Texture = paddle.png
  • Position = 284,30
  • Z Position = 3
  • Body Type > Bounding rectangle
  • 取消勾选Dynamic
  • Friction: 0
  • Restitution: 1


显然,这里大部分的选项与前面创建小球时使用的选项是类似的。然而,这一次你使用了Bounding rectangle来形成物理Body,因而它将更好地匹配矩形的挡板。

这里通过关闭Dynamic选项,设置挡板是静态的。这将确保挡板不会受外力和冲量的影响。你很快会看到为什么这很重要。

如果现在你生成和运行一下项目,你会看到挡板出现在场景中,而小球在碰到挡板时会弹起(如果你能等待一段足够长时间的话)。请参考下图。

基于SpriteKit+Swift开发打竹块游戏(上篇) 11

基于SpriteKit+Swift开发打竹块游戏(上篇) - 敏捷大拇指 - 基于SpriteKit+Swift开发打竹块游戏(上篇) 11


到目前为止,一切比较顺利!接下来,我们要使玩家能够移动挡板。




8、移动挡板

移动挡板需要检测接触相关信息。为此,我们在GameScene类中执行下面的触摸处理方法︰

[Swift] 纯文本查看 复制代码
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
 
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) 
 
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) 


但是,在此之前,你还需要添加一个属性。转到GameScene.swift文件,然后向类中添加以下属性︰

[Swift] 纯文本查看 复制代码
var isFingerOnPaddle = false 


这个属性负责存储是否玩家点按了挡板这一信息。你会需要它来执行拖动挡板相关操作。

现在,请在GameScene.swift文件的touchesBegan(_:withEvent: )方法中添加如下代码︰