先放最终效果图:
更新01/20/2017:由Kevin Colligan更新为iOS 10,Xcode 8和Swift 3。原文由Tammy Coron发表,最近由Nick Lockwood更新。原文链接
Cut The Rope是一种受欢迎的物理驱动游戏,玩家通过剪切挂起糖果的绳索喂养一只名叫Om Nom的怪兽。在正确的时间和地点切断绳索,Om Nom将获得美味佳肴。
在对Om Nom充分尊重的情况下,游戏的真正主角是模拟物理学:绳索摆动,重力拉动,让糖果按照您在现实生活中期望那样下落。
您可以使用Apple的2D游戏框架SpriteKit的物理引擎构建类似的体验。在本教程中,您将会做一个名为Snip The Vine的游戏。
注意:本教程假设您有一些SpriteKit的经验。如果您是SpriteKit的新手,请查看我们的SpriteKit Swift初学者教程。
入门
在Snip The Vine,您可以将菠萝喂给鳄鱼。在开始之前,请下载启动项目。在Xcode中打开项目,以便快速查看它的结构。
项目文件分割在多个文件夹中。在本教程中,您可以使用包含主代码文件的Classes文件夹。随便浏览其他文件夹,如下所示:
设定常数
常数通过避免重复使用含义不明确的字符串或数字,使您的代码更易于阅读和维护。
打开Constants.swift并添加以下代码:
struct ImageName {
static let Background = “Background”
static let Ground = “Ground”
static let Water = “Water”
static let VineTexture = “VineTexture”
static let VineHolder = “VineHolder”
static let CrocMouthClosed = “CrocMouthClosed”
static let CrocMouthOpen = “ CrocMouthOpen“
static let CrocMask = ”CrocMask”
static let Prize = “Pineapple”
static let PrizeMask = “PineappleMask”
}
struct SoundFile {
static let BackgroundMusic = “CheeZeeJungle.caf”
static let Slice = “Slice.caf”
static let Splash = “Splash.caf”
static let NomNom = “NomNom.caf”
}
使用以上代码,您定义了一些常量保存sprite图像名称和声音文件名称。
在下面添加以下内容:
struct Layer {
static let Background: CGFloat = 0
static let Crocodile: CGFloat = 1
static let Vine: CGFloat = 1
static let Prize: CGFloat = 2
static let Foreground: CGFloat = 3
}
struct PhysicsCategory {
static let Crocodile: UInt32 = 1
static let VineHolder: UInt32 = 2
static let Vine: UInt32 = 4
static let Prize: UInt32 = 8
}
上面的代码声明了两个结构体:Layer
和PhysicsCategory
,它们分别包含一些static
CGFloat
和UInt32
的属性。当您将它们添加到场景中时,将使来指定精灵的zPosition和物理学属性。
最后再添加一个struct
:
struct GameConfiguration {
static let VineDataFile = “VineData.plist”
static let CanCutMultipleVinesAtOnce = false
}
VineDataFile
指定了葡萄藤所在位置文件的名称。
CanCutMultipleVinesAtOnce
允许通过简单的方式修改游戏参数。怎样的游戏决策会使游戏更有趣,这总是并不明确的。这样的常数提供了一种简单的开关方式,让你可以稍后改变你的游戏。
现在,您可以开始向场景添加节点。
向场景添加背景Sprite
打开GameScene.swift并将以下内容添加到setUpScenery()
:
let background = SKSpriteNode(imageNamed: ImageName.Background)
background.anchorPoint = CGPoint(x: 0, y: 0)
background.position = CGPoint(x: 0, y: 0)
background.zPosition = Layer.Background
background.size = CGSize(width: size.width, height: size.height)
addChild(background)
let water = SKSpriteNode(imageNamed: ImageName.Water)
water.anchorPoint = CGPoint(x: 0, y: 0)
water.position = CGPoint(x: 0, y: 0)
water.zPosition = Layer.Foreground
water.size = CGSize(width: size.width, height: size.height * 0.2139)
addChild(water)
setUpScenery()
在didMove()
方法中被调用。在这个方法中,创建一些SKSpriteNode
实例,并调用SKSpriteNode(imageNamed:)
进行初始化。为了处理多个屏幕尺寸,您需要显式设置背景图像的大小。
您将节点的anchorPoint
从默认值(0.5,0.5)更改为(0,0)。这意味着节点从原本的相对于中心定位变成了相对于左下角定位,这使您可以轻松地将background
和water
与场景底部对齐。
注意:anchorPoint
属性使用单位坐标系,其中(0,0)表示图像的左下角,(1,1)表示右上角。因为它的值总是从0到1,所以这些坐标与图像尺寸和宽高比无关。
您还可以设置Sprite的zPosition
,控制节点在屏幕上的绘制顺序。
回想一下,在Constants.swift中,您指定了一些用于zPosition
的值。这里使用其中的:Layer.Background
和Layer.Foreground
,确保背景总是落在另外的Sprite之后,前景将始终画在最前面。
编译并运行您的项目。如果您做的一切正确,您应该看到以下效果:
下一篇文章将开始在项目中添加游戏的主角——鳄鱼。