Swift - 一步步教你使用SpriteKit创建开发游戏项目

一,什么是SpriteKit
SpriteKit是苹果公司官方出品,用于制作2D游戏的框架。这个框架具备了图形渲染和动画的功能。可以使图像或者精灵(sprite)动 起来。SpriteKit的渲染方式是传统的环形渲染,允许在渲染前处理每一帧点的内容。例如定义场景中的元素,以及这些内容在每一帧中是如何变化的。尤 其重要的是,苹果官方出品的这个SpriteKit能够很有效地利用图形硬件来渲染。
除了图形渲染,SpriteKit还包括了声音播放和物理系统。在Xcode中,我们可以很轻易地创建复杂的特效和纹理集。

二,SpriteKit支持的内容
(1)无纹理或者有纹理的矩形
(2)文本
(3)基于CGPath的形状
(4)音频,视频
(5)动画特效
(6)物理系统

三,从零开始开发一个游戏项目
1,在Xcode中创建一个Game项目

2,当项目创建完毕后,系统会自动生成一个场景,叫GameScene.swift。我们不用它,使用自己新创建的场景。


3,将新创建的场景代替默认的GameScene
打开GameViewController.swift,将相关的地方进行替换
1
2
3
4
5
6
7
8
9
10
11
12
13
extension SKNode {
     class func unarchiveFromFile(file : NSString ) -> SKNode ? {
             .....
             let scene = archiver.decodeObjectForKey( NSKeyedArchiveRootObjectKey ) as FirstScene
 
class GameViewController : UIViewController {
 
     override func viewDidLoad() {
         super .viewDidLoad()
 
         if let scene = FirstScene .unarchiveFromFile( "GameScene" ) as ? FirstScene {
         
         .........

4,修改场景背景色,添加文本标签,点击屏幕给标签添加动画效果 
这里我们使用了SpriteKit的动作(Action)。当点击屏幕时,文字依次向上移动、放大、暂停并淡出屏幕,最后从场景中移除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import SpriteKit
 
class FirstScene : SKScene {
     //当切换到这个场景视图后后
     override func didMoveToView(view: SKView ) {
         createScene()
     }
     
     func createScene(){
         //改变背景颜色
         self .backgroundColor = SKColor .blueColor()
         //创建一个显示文本的节点
         let myLabel = SKLabelNode (fontNamed: "Chalkduster" )
         //添加name属性
         myLabel.name = "label"
         //设置文本内容
         myLabel.text = "Hello, hangge.com" ;
         //设置字体大小
         myLabel.fontSize = 46;
         //设置文本节点的位置
         myLabel.position = CGPoint (x: CGRectGetMidX ( self .frame), y: CGRectGetMidY ( self .frame));
         //将文本节点加入场景中
         self .addChild(myLabel)
     }
     
     //响应屏幕点击时间的方法
     override func touchesBegan(touches: NSSet , withEvent event: UIEvent ) {
         //获取文本节点
         let labelNode = self .childNodeWithName( "label" )
         //向上移动的动作
         let moveUp = SKAction .moveByX(0, y: 100, duration: 0.5)
         //放大动作
         let zoom = SKAction .scaleTo(2.0, duration: 0.25)
         //暂停的动作
         let pause = SKAction .waitForDuration(0.5)
         //淡出的动作
         let fadeAway = SKAction .fadeOutWithDuration(0.25)
         //从父对象移除的动作
         let remove = SKAction .removeFromParent()
         //动作序列
         let moveSequence = SKAction .sequence([moveUp,zoom,pause,fadeAway,remove])
         //文本节点执行动作序列
         labelNode?.runAction(moveSequence)       
     }
}

5,跳转到新场景
 对文本节点的动作序列做如下修改,当文本节点消失的时候,会创建一个新的场景SecondScene,并以开门的方式过渡到新场景,而之前的场景会被移除
1
2
3
4
5
6
7
8
9
//执行完动作序列之后调用闭包函数
labelNode?.runAction(moveSequence, completion: {
     //声明下一个场景的实例
     let secondScene = SecondScene (size: self .size)
     //场景过渡动画
     let doors = SKTransition .doorsOpenVerticalWithDuration(0.5)
     //带动画的场景跳转
     self .view?.presentScene(secondScene,transition:doors)
})

6,使用SKSpriteNode创建一个飞船 
下面通过创建一个椭圆充当飞船,飞船两侧还添加了忽明忽暗的灯光。同时,飞船设置了一个重复的动作序列自动进行移动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import SpriteKit
 
class SecondScene : SKScene {
     //当切换到这个场景视图后后
     override func didMoveToView(view: SKView ) {
         createScene()
     }
     
     func createScene(){
         let spaceship = newSpaceship()
         //设置飞船的位置
         spaceship.position = CGPointMake ( CGRectGetMidX ( self .frame), CGRectGetMidY ( self .frame)-150)
         //加入到场景中
         self .addChild(spaceship)
     }
     
     //创建飞创的类
     func newSpaceship()-> SKShapeNode {
         //创建一个椭圆,充当飞船
         let ship = SKShapeNode ()
         ship.path = CGPathCreateWithRoundedRect ( CGRectMake (-15, -15, 30, 30), 15, 15, nil )
         ship.strokeColor = SKColor .whiteColor()
         ship.fillColor = SKColor .grayColor()
         //创建一组动作,暂停1秒,位移,暂停1秒,位移
         let hover = SKAction .sequence([
             SKAction .waitForDuration(1.0),
             SKAction .moveByX(100, y: 50, duration: 1),
             SKAction .waitForDuration(1.0),
             SKAction .moveByX(-100, y: -50, duration: 1.0)
             ])
         //以重复的方式执行序列动作
         ship.runAction( SKAction .repeatActionForever(hover))
         //创建灯光
         let light1 = newLight()
         //设置灯光位置
         light1.position = CGPointMake (-28, 6.0)
         //加载灯光
         ship.addChild(light1)
         
         //创建灯光2,步骤同上
         let light2 = newLight()
         light2.position = CGPointMake (28, 6.0)
         ship.addChild(light2)
                 
         //物理系统
         ship.physicsBody = SKPhysicsBody (circleOfRadius: 15)
         ship.physicsBody?. dynamic = false
         
         //返回飞船
         return ship
     }
     
     //创建灯光方法
     func newLight()-> SKShapeNode {
         //创建一个黄色椭圆充当灯光
         let light = SKShapeNode ()
         light.path = CGPathCreateWithRoundedRect ( CGRectMake (-4, -4, 8, 8), 4, 4, nil )
         light.strokeColor = SKColor .whiteColor()
         light.fillColor = SKColor .yellowColor()
         //创建忽明忽暗的动作
         let blink = SKAction .sequence([
             SKAction .fadeOutWithDuration(0.25),
             SKAction .fadeInWithDuration(0.25)
             ])
         //创建一直重复的动作
         let blinkForever = SKAction .repeatActionForever(blink)
         //执行动作
         light.runAction(blinkForever)
         //返回灯光
         return light
     }
}

7,定时生成陨石(并设置物理碰撞)
下面代码会每隔0.1秒在屏幕上方随机的生成一个陨石。由于添加了物理体,所以陨石会做向下的自由落体运动。同时陨石砸在飞船上会停住,并像有弹性似的跳了跳,等飞船离开后才又落下来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import SpriteKit
 
class SecondScene : SKScene {
     //当切换到这个场景视图后后
     override func didMoveToView(view: SKView ) {
         createScene()
     }
     
     func createScene(){
         //.....
         //生成陨石(每隔 0.1秒生成1个)
         NSTimer .scheduledTimerWithTimeInterval(0.1, target: self , selector: "addRock" ,
             userInfo: nil , repeats: true )
     }
   
     //创建陨石的方法
     func addRock(){
         //小椭圆充当陨石
         let rock = SKShapeNode ()
         rock.path = CGPathCreateWithRoundedRect ( CGRectMake (-4, -4, 8, 8), 4, 4, nil )
         rock.strokeColor = SKColor .whiteColor()
         rock.fillColor = SKColor .brownColor()
         //获取场景宽,高
         let w = self .size.width
         let h = self .size.height
         //随机出现在场景的xy位置
         let x = CGFloat (arc4random())%w
         let y = CGFloat (arc4random())%h
         //设置陨石的位置
         rock.position = CGPointMake (x,y)
         //设置陨石的name属性
         rock.name = "rock"
         //给陨石设置物理体
         rock.physicsBody = SKPhysicsBody (circleOfRadius: 4)
         //物理体允许检测碰撞
         rock.physicsBody?.usesPreciseCollisionDetection = true
         //场景加入陨石
         self .addChild(rock)       
     }
}

四,最终完整的代码
--- FirstScene.swift ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import SpriteKit
 
class FirstScene : SKScene {
     //当切换到这个场景视图后后
     override func didMoveToView(view: SKView ) {
         createScene()
     }
     
     func createScene(){
         //改变背景颜色
         self .backgroundColor = SKColor .blueColor()
         //创建一个显示文本的节点
         let myLabel = SKLabelNode (fontNamed: "Chalkduster" )
         //添加name属性
         myLabel.name = "label"
         //设置文本内容
         myLabel.text = "Hello, hangge.com" ;
         //设置字体大小
         myLabel.fontSize = 46;
         //设置文本节点的位置
         myLabel.position = CGPoint (x: CGRectGetMidX ( self .frame), y: CGRectGetMidY ( self .frame));
         //将文本节点加入场景中
         self .addChild(myLabel)
     }
     
     //响应屏幕点击时间的方法
     override func touchesBegan(touches: NSSet , withEvent event: UIEvent ) {
         //获取文本节点
         let labelNode = self .childNodeWithName( "label" )
         //向上移动的动作
         let moveUp = SKAction .moveByX(0, y: 100, duration: 0.5)
         //放大动作
         let zoom = SKAction .scaleTo(2.0, duration: 0.25)
         //暂停的动作
         let pause = SKAction .waitForDuration(0.5)
         //淡出的动作
         let fadeAway = SKAction .fadeOutWithDuration(0.25)
         //从父对象移除的动作
         let remove = SKAction .removeFromParent()
         //动作序列
         let moveSequence = SKAction .sequence([moveUp,zoom,pause,fadeAway,remove])
         //执行完动作序列之后调用闭包函数
         labelNode?.runAction(moveSequence, completion: {
             //声明下一个场景的实例
             let secondScene = SecondScene (size: self .size)
             //场景过渡动画
             let doors = SKTransition .doorsOpenVerticalWithDuration(0.5)
             //带动画的场景跳转
             self .view?.presentScene(secondScene,transition:doors)
         })
     }
}

--- SecondScene.swift ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import SpriteKit
 
class SecondScene : SKScene {
     //当切换到这个场景视图后后
     override func didMoveToView(view: SKView ) {
         createScene()
     }
     
     func createScene(){
         let spaceship = newSpaceship()
         //设置飞船的位置
         spaceship.position = CGPointMake ( CGRectGetMidX ( self .frame), CGRectGetMidY ( self .frame)-150)
         //加入到场景中
         self .addChild(spaceship)
         
         //生成陨石(每隔 0.1秒生成1个)
         NSTimer .scheduledTimerWithTimeInterval(0.1, target: self , selector: "addRock" ,
             userInfo: nil , repeats: true )
     }
     
     //创建飞创的类
     func newSpaceship()-> SKShapeNode {
         //创建一个椭圆,充当飞船
         let ship = SKShapeNode ()
         ship.path = CGPathCreateWithRoundedRect ( CGRectMake (-15, -15, 30, 30), 15, 15, nil )
         ship.strokeColor = SKColor .whiteColor()
         ship.fillColor = SKColor .grayColor()
         //创建一组动作,暂停1秒,位移,暂停1秒,位移
         let hover = SKAction .sequence([
             SKAction .waitForDuration(1.0),
             SKAction .moveByX(100, y: 50, duration: 1),
             SKAction .waitForDuration(1.0),
             SKAction .moveByX(-100, y: -50, duration: 1.0)
             ])
         //以重复的方式执行序列动作
         ship.runAction( SKAction .repeatActionForever(hover))
         //创建灯光
         let light1 = newLight()
         //设置灯光位置
         light1.position = CGPointMake (-28, 6.0)
         //加载灯光
         ship.addChild(light1)
         
         //创建灯光2,步骤同上
         let light2 = newLight()
         light2.position = CGPointMake (28, 6.0)
         ship.addChild(light2)       
         
         //物理系统
         ship.physicsBody = SKPhysicsBody (circleOfRadius: 15)
         ship.physicsBody?. dynamic = false
         
         //返回飞船
         return ship
     }
     
     //创建灯光方法
     func newLight()-> SKShapeNode {
         //创建一个黄色椭圆充当灯光
         let light = SKShapeNode ()
         light.path = CGPathCreateWithRoundedRect ( CGRectMake (-4, -4, 8, 8), 4, 4, nil )
         light.strokeColor = SKColor .whiteColor()
         light.fillColor = SKColor .yellowColor()
         //创建忽明忽暗的动作
         let blink = SKAction .sequence([
             SKAction .fadeOutWithDuration(0.25),
             SKAction .fadeInWithDuration(0.25)
             ])
         //创建一直重复的动作
         let blinkForever = SKAction .repeatActionForever(blink)
         //执行动作
         light.runAction(blinkForever)
         //返回灯光
         return light
     }
     
     //创建陨石的方法
     func addRock(){
         //小椭圆充当陨石
         let rock = SKShapeNode ()
         rock.path = CGPathCreateWithRoundedRect ( CGRectMake (-4, -4, 8, 8), 4, 4, nil )
         rock.strokeColor = SKColor .whiteColor()
         rock.fillColor = SKColor .brownColor()
         //获取场景宽,高
         let w = self .size.width
         let h = self .size.height
         //随机出现在场景的xy位置
         let x = CGFloat (arc4random())%w
         let y = CGFloat (arc4random())%h
         //设置陨石的位置
         rock.position = CGPointMake (x,y)
         //设置陨石的name属性
         rock.name = "rock"
         //给陨石设置物理体
         rock.physicsBody = SKPhysicsBody (circleOfRadius: 4)
         //物理体允许检测碰撞
         rock.physicsBody?.usesPreciseCollisionDetection = true
         //场景加入陨石
         self .addChild(rock)       
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值