游戏设计&游戏开发程序员

SceneKit教程03 - 搭建game scene

2018-05-06  本文已影响61人  Xtuphe

前面两篇主要在做一些准备工作, 这一篇就有趣了, 开始搭建游戏场景.

我们在之前已经在game scene创建了一个巨大的草坪, 现在我们要补上其余的细节: 两条拥挤的高速公路, 漂亮的树, 和我们的主角猪大哥.

添加主角

首先先来添加我们的主角Mr. Pig到game scene, 这样有助于将其作为参照物来放置其他的物体.

首先选中MrPig.scnassets/ GameScene.scn, 在Media Library找到Mr. Pig reference, 将其拖动到scene, 并确保Position跟Euler都为0; Mr. Pig reference

然后到ViewController.swift, 添加这条属性, 用来持有Mr.Pig的实例:

var pigNode: SCNNode!

添加下面这行到setupNodes():

pigNode = gameScene.rootNode.childNode(withName: "MrPig", recursively:
            true)!

这个方法会在GameScene.scn加载完成后调用, 所以是一个安全的方法来绑定game scene里实际的对象到pigNode.
(虽然Mr. Pig是一个reference node, 你仍可以在game scene中像正常node一样访问它)

设置镜头和灯光

跟前面一样, 这里仍使用"自拍杆"原则, 即通过创建empty node来作为camera 或 light的焦点 - 这样可以简化很多数学问题, 你应该不会介意的. :]

创建跟随镜头

返回MrPig.scnassets/GameScene.scn, 首先确保Scene graph上没有东西被选中, 然后点左下角 + 创建empty node. 将其命名为Follow Camera, Position值为0, Euler:(x:-45, y:20, z:0).

然后把之前的camera拖动到新建的Follow Camera下面, 将camera的Position设置为(x:0, y:0, z:14), Euler为0;

点击Perspective 选中camera, 你的视角应该是上图的样子.

选中ViewController.swift, 添加这两个属性:

    var cameraNode: SCNNode!
    var cameraFollowNode: SCNNode!

这用来持有camera和Follow Camera的实例

添加下面代码到setupNodes():

        // 1 将camera绑定到cameraNode
        cameraNode = gameScene.rootNode.childNode(withName: "camera", recursively: true)!
        // 2 将hud作为子node添加给camera, 这样玩家可以始终看到游戏内需要展示的信息
        cameraNode.addChildNode(game.hudNode)
        // 3 将Follow Camera绑定到cameraFollowNode, 这样你仅仅需要更新cameraFollowNode的position就可以使我们的镜头时刻跟随猪大哥
        cameraFollowNode = gameScene.rootNode.childNode(withName: "Follow Camera", recursively: true)!

创建跟随光源

这里会用到和上面镜头差不多的步骤, 我们需要两个基础光源, 一个环境光来填充, 一个平行光来模拟阳光照射和它产生的阴影.

首先确保Scene graph没有东西被选中, 点击左下 + , 命名为Follow Light并将Position 和 Euler 设置为0.

从Object Library拖动Ambient Light和Directional Light到Follow Light下, 选中ambient, 确保Position 和 Euler 均为0, 点击Attributes Inspector, 颜色选择Aluminum, 这会让整个场景稍微亮一些. 选中directional, 设置Position : (x:-5, y:5, z:5), Euler : (x:-45, y:-60, z:0), 这会把平行光放置在scene的左上方, 很好的照亮了大地. 然后点击Attributes Inspector开始设置阴影. 选中Casts shadows, 设置Sample count为0, 取消Auto Adjust并设置Scale 和 Clipping如下图所示.

因为阴影是个相对比较消耗性能的操作, 所以你并不想在玩家看不到的地方计算阴影.

接下来是一些代码工作, 将下面属性添加到ViewController.swift

var lightFollowNode: SCNNode!

这用来持有FollowLight的实例

添加下面的代码到setupNodes():

lightFollowNode = gameScene.rootNode.childNode(withName: "Follow Light", recursively: true)!

这将Follow Light与lightFollowNode绑定, 你可以将lightFollowNode的position设置为与Follow Camera相同来使玩家可视区域投射出漂亮的阴影.

command + R来验证一下你的成果:



看起来像一个阳光明媚的好天气, 注意一下你的阴影, 简直闻到了烤肉的香气 :]

添加高速公路与车流

首先, 确保你的game scene的scene graph没东西被选中, 点击左下角 + 添加empty node, 将其命名为Highway. 这个node用来作为两条高速公路的容器node来使用.

然后在Media Library拖动两个Road到Highway下, 选中第一个, 设置Position:(x:0, y:0, z:-4.5), Euler为0.

选中第二个, 设置Position:(x:0, y:0, z:-11.5), Euler : 0. Perspective处选中camera, 应该看起来像这样

(我这里Xcode又出了问题, scene editor的马路被阳光照射成了白色, 但实际运行起来是ok的, Xcode的bug真是多啊)


看道路与上图的区别

添加车流

跟前面类似, 创建一个empty node并命名为Traffic作为容器, 然后从Media Library拖动Bus到Traffic下, 并设置position : (x:0, y:0, z:-4), Euler: (x:0, y:-90, z:0).

重复类似步骤, 再从Media Library拖动Mini 与 SUV到Traffic下, 并设置Mini :position (x:3, y:0, z:-5). Euler (x:0, y:-90, z: 0); SUV: position (x:-3, y:0, z:-5)Euler (x:0, y:-90, z:0).
完美! 接下来添加下面属性到ViewController.swift,
var trafficNode: SCNNode!

因为路上车会很多, 不需要给每个引用添加一个属性, 而是通过这个属性来持有所有车辆.
添加下面代码到setupNodes():

trafficNode = gameScene.rootNode.childNode(withName: "Traffic", recursively: true)!

这会绑定Traffic到trafficNode, 你可以访问它所有的子node来是车辆动起来.

下面是挑战内容, 你可以尝试自己添加很多很多很多的车辆来使公路变得热闹起来. 当你完成时差不多应该是这样的:


Challenge

添加时你应该注意如下事项:

当你完成后, command + R来验证一下你的成果.


你的猪大哥不再孤单

添加树🌲

目前看起来像是有人在足球场上建了两条路, 我们要的效果是在公园里有两条路, 所以现在要加树 :]

接下来你要添加两组不同的树: 树线, 和 树组... 树线用来勾勒整个公园的边界, 树组用来装饰, 使足球场变公园.

创建树线TreeLine

比起一棵棵的栽树, 你会采用一个更聪明的方法: 创建一个由很多树构成的可复用的scene, 然后在game scene把这些作为reference node来使用.

首先在File Template Library拖动一个SceneKit Scene File到Project Navigator. 将其命名为TreeLine, 并放在MrPig.scnassets目录下. 选中, 删除里面自带的camera因为你不会用到, 在里面再创建一个empty node 并命名为TreeLine. 然后按照下面的模式来搭建TreeLine:

这个表是啥意思呢? 每个白色方块代表一棵树的位置.

创建树组TreePatch

这根上面几乎是完全一样的, 除了模式换成了这样的:
当你完成时应该看起来是这样:

添加数线

终于, 我们的reference node准备完毕, 是时候把它们扔进game scene了.

选中GameScene.scn并确保Scene graph上没有东西被选中, 创建一个empty node命名为Trees. 接下来从Media Library 拖动一个TreeLine到scene, 然后开始复制并调整位置, 直到你的game scene看起来差不多这个样子:



我个人习惯按着option + command一个一个拖动来布局, 当然, 你也可以直接复制一堆TreeLine, 然后在Node Inspector直接修改Position, 如果你选择后者, 可以这样修改:
猪先生前面
• Position:(x:0,y:0,z:7),Euler:(x:0,y:0,z:0).
• Position:(x:-7, y:0, z:3), Euler: (x:0, y:90, z:0).
• Position:(x:7,y:0,z:3),Euler:(x:0,y:90,z:0).
• Position:(x:-14,y:0,z:-1),Euler:(x:0,y:0,z:0).
• Position:(x:14,y:0,z:-1),Euler:(x:0,y:0,z:0).
道路两侧
• Position:(x:-14,y:0,z:-8),Euler:(x:0,y:0,z:0).
• Position:(x:14,y:0,z:-8),Euler:(x:0,y:0,z:0).
后面
• Position:(x:18,y:0,z:-19),Euler:(x:0,y:90,z:0).
• Position:(x:-18,y:0,z:-19),Euler:(x:0,y:90,z:0).
• Position:(x::-11,y:0,z:-23),Euler:(x:0,y:0,z:0).
• Position: (x:0, y:0, z:-23), Euler: `(x:0, y:0, z:0).
• Position:(x:11,y:0,z:-23),Euler:(x:0,y:0,z:0).

添加树组

这个就简单多了, 只有三个
• Position:(x:10,y:0,z:-17),Euler:(x:0,y:0,z:0).
• Position:(x:-10,y:0,z:-17),Euler:(x:0,y:0,z:0).
• Position:(x:0,y:0,z:-17),Euler:(x:0,y:90,z:0).
完成后大概是这样的:



最后, 再次确认你的树node都在Trees容器node下面.

添加金币

听说🐷都爱金币 :] , 所以现在我们要添加些金币到我们的game scene.

先创建一个名为Coins的empty node, 然后从Media Library拖动一个coin到里面, 再复制3个, 设置位置如下:
• Position:(x:0,y:0.5,z:-8).
• Position:(x:0,y:0.5,z:-21).
• Position:(x:-14,y:0.5,z:-20).
• Position:(x:14,y:0.5,z:-20).


完美! 最后comman + R来验证一下本章的成果.


现在, 你有一个漂亮的启动页面Splash Scene, 然后有个漂亮的转场动画让你的Mr.Pig出现在你刚搭建的有着拥挤车流的漂亮的公园, 一切都是那么的漂亮. 应该给自己一个掌声了.

然而, 我们猪大哥跟车流都是静止的, 如何让他们动起来呢? 我们下篇见!

目录 (不定期更新中 :] )

1 准备工作、创建项目、Splash Scene
2 过场动画 Transition
3 搭建游戏场景 Game Scene
4 用场景编辑器添加动作
5 用代码添加动作

上一篇下一篇

猜你喜欢

热点阅读