用Swift做个游戏Lecture01 —— 初窥游戏场景

作者:PMST
VERSION:V1.0
NOTICE:目前第一版以叙述内容为主,之后对其中一些细节知识点进行讲解。
更新时间:每周日

本教程参考自RayWenderlich的视频教程How To Make a Game Like Flappy Bird Series (Swift)。本教程中,你将从无到有亲自开发一个基于SpriteKit框架的Flappy bird小游戏。总体难度不大,但要求你掌握Swift基础语法与SpriteKit框架知识。此外,教程中所有素材均来自Raywenderlich,鼓励学习交流,但请勿用于商业用途。

友情帮助: 为了方便大家快速上手项目,我在github中上传了起始项目文件供大家下载,请点击这里下载。

01.项目文件介绍

首先请打开项目,先介绍项目已有文件,你将看到如下目录:

L01-Dir
L01-Dir

主要讲解以下一些重要的文件:

  • Resource文件夹:资源文件放置处

    • Art:以atlas图册方式管理素材文件。

    • SKTUtiles:采用Extension对一些类进行拓展,添加一些有用的方法或属性。

    • Sounds:游戏声音素材

  • GameScene.swift:Flappy游戏比较简单,因此一个游戏场景足以,有关于场景内容设置、交互等均在该场景中设置。

  • GameViewController.swift:视图控制器,包含一个视图view,当然这个视图比较特殊:为SKView,用于呈现场景Scene

02.呈现视图

选中GameViewController.swift文件,先前提及视图控制器中的SKView,其职责在于呈现游戏场景Scene。不过现在空文件中神马都没有,我们将重写viewWillLayoutSubviews()方法呈现场景。定位到GameViewController类,添加以下代码:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    // 1.对view进行父类向子类的变形,结果是一个可选类型 因此需要解包
    if let  skView = self.view as? SKView{
        // 倘若skView中没有场景Scene,需要重新创建创建一个
        if skView.scene == nil{

            /*==  创建场景代码  ==*/

            // 2.获得高宽比例
            let aspectRatio = skView.bounds.size.height / skView.bounds.size.width
            // 3.new一个场景实例 这里注意场景的width始终为320 至于高是通过width * aspectRatio获得
            let scene = GameScene(size:CGSizeMake(320, 320 * aspectRatio))

            // 4.设置一些调试参数
            skView.showsFPS = true          // 显示帧数
            skView.showsNodeCount = true    // 显示当前场景下节点个数
            skView.showsPhysics = true      // 显示物理体
            skView.ignoresSiblingOrder = true   // 忽略节点添加顺序

            // 5.设置场景呈现模式
            scene.scaleMode = .AspectFill

            // 6.呈现场景
            skView.presentScene(scene)
        }
    }
}

这里需要注意2、3处,固定了游戏场景的宽度Width = 320,高度则通过Width乘以高宽比相乘得到,对于iPhone4s iPhone5/5s这些宽为320的设备来说自然没什么影响,但是对于iPhone6/6Pluse设备,相当于将设备宽高同时缩小相同倍数,直至宽为320时停止;再通过设置scaleModeAspectFill(更多ScaleMode,请点击这里了解)呈现视图。

对于4来说,我们需要了解游戏运行时每秒的帧数、当前场景中节点个数、显示节点的物理体等,因此通过设置这些参数能帮助我们更好的调试。

OK,点击运行项目,模拟器运行结果一片漆黑,不过右下角显示node=1 60.0fps,表明当前场景中显示了一个节点,帧数为60左右。

Question:什么都还没添加,视图中怎么会有一个节点Node了呢?

Answer:场景Scene类为SKScene,继承自SKNode,因此当skView呈现场景时,自然就将一个节点置于其中了。

03场景内容的填充

定位到GameScene.swift文件,可以看到文件中已经声明了一个GameScene类,当然类中我们还未实现任何东西,因此这是运行项目呈现出来的场景是漆黑一片。是时候一步步配置游戏场景了!

首先,定位到GameScene类中,在类中顶部添加如下三个变量,如下:

class GameScene:SKScene:{
let worldNode = SKNode()
var playableStart:CGFloat = 0
var playableHeight:CGFloat = 0
//...文件其他内容
}

如上实例化了一个节点命名为worldNode,原因在于之后游戏中所有的节点都将添加至这个节点中,方便管理。此外游戏中场景分为BackgroundGround两部分,前者是背景,鸟可以在该区域中上下飞行;后者地面,小鸟仅限于跌落至上面。具体划分请看下图:

L01-Scene
L01-Scene

其中,背景和地面均作为节点添加至worldNode节点中。请在didMoveToView(view:)方法中添加如下代码:

override func didMoveToView(view: SKView) {
    addChild(worldNode)
    setupBackground()
    setupForeground()
}

首先添加worldNode节点到场景中,接着setupBackground()setupForeground()两个方法分别设置背景和地面两个节点,当然此时方法还未实现。

通常游戏包含多个节点,为了细化节点的图层关系,节点Node中设定了一个zPosition属性用于标识节点相距你的程度,越小越里面,越大越外面。显然游戏中,背景至于最底部,其次是地面,最后才是Player那只鸟。为此我们将使用枚举来说明层级关系,在GameScene类上方添加Layer的声明:

enum Layer: CGFloat {
  case Background
  case Foreground
  case Player
}
class GameScene:SKScene{}

干完这些,是时候补充剩下的两个方法的实现了。首先添加setupBackground()方法至GameScene类中:

func setupBackground(){
    // 1
    let background = SKSpriteNode(imageNamed: "Background")
    background.anchorPoint = CGPointMake(0.5, 1)
    background.position = CGPointMake(size.width/2.0, size.height)
    background.zPosition = Layer.Background.rawValue
    worldNode.addChild(background)

    // 2
    playableStart = size.height - background.size.height
    playableHeight = background.size.height
}

依葫芦画瓢实现setupForeground()方法:

func setupForeground() {

  let foreground = SKSpriteNode(imageNamed: "Ground")
  foreground.anchorPoint = CGPoint(x: 0, y: 1)
  foreground.position = CGPoint(x: 0, y: playableStart)
  foreground.zPosition = Layer.Foreground.rawValue
  worldNode.addChild(foreground)
}

点击运行,你将看到如下画面,Good Job! 你已经完成了第一步,之后我们将添加Player以及障碍物到场景中。

L01-end
L01-end

倘若你觉得SpritKit的基础知识不够扎实,不妨看看这个

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,952评论 4 60
  • 嗯哼嗯哼蹦擦擦~~~ 转载自:https://github.com/Tim9Liu9/TimLiu-iOS 目录 ...
    philiha阅读 4,800评论 0 6
  • 本文转自http://blog.csdn.net/lmj623565791/article/details/242...
    radish520like阅读 395评论 0 0
  • 有些时候,一个人若是给你留了条路找他,赶紧去,别伤她的心,他只是害怕了…… 可有些时候,当她彻彻底底的从你的世界消...
    初画影阅读 95评论 0 0