
大家好! 预期将推出
“ iOS开发人员”课程
。 “基础课程”我们又组织了一次
公开课 。 这次网络研讨会是为有使用任何语言和平台进行开发但希望学习Swift语言并精通iOS开发的人们而设计的。 在本课中,我们详细
研究了Swift语言的
语法和关键构造 ,并熟悉了主要的开发工具。
网络研讨会参与者了解到:
- Swift语言是什么,它的功能是什么?
- Xcode开发环境如何帮助您入门
- 如何为iOS创建简单的游戏。
网络研讨会由Yandex的iOS开发人员
Alexei Sobolevsky主持。
自己动手做蛇
在工作中,我们使用了集成开发
环境Xcode 。 这是由Apple创建的便捷,免费且实用的环境。
在开始时,我们创建了一个新项目并选择了基本的“游戏”文件集:

事不宜迟,他们将项目称为“ Snake”。 默认情况下保留所有设置,确保SpriteKit在游戏技术行中。
项目创建的详细信息。执行上述操作后,将在窗口的左侧显示为我们的项目自动创建的文件列表。 最重要的文件之一是
AppDelegate.swift ,它可以在应用程序发生任何重大事件(启动,推送,单击链接等)时帮助系统与我们的代码通信。 该文件的代码:
同样重要的文件是
GameScene.swift和
GameViewController.swift 。 GameScene类创建场景,而GameViewController负责我们看到的应用程序的一个屏幕(一个屏幕-一个GameViewController)。 当然,并不总是支持此规则,但是总的来说,它是可行的。 由于我们的应用程序非常简单,因此我们只有一个GameViewController。 让我们从他开始。
编写一个GameViewController
我们将删除默认代码。 视图控制器有几种可以根据屏幕状态工作的方法。 例如,当所有屏幕元素均已加载且屏幕即将出现在智能手机上时,将触发
viewDidLoad()
。 由于我们有一个游戏,因此我们需要将游戏场景放置在我们的视图控制器中(这是蛇将奔跑的地方,并且游戏的所有其他事件都将发生)。
创建一个场景:
let scene = GameScene(size: view.bounds.size)
let是一个常量和一个关键字。 Swift还使用var关键字,该关键字是定义变量所必需的。 使用
var ,我们可以在程序运行时多次更改变量的值。 使用let时,我们无法在初始化后更改变量的值。
现在,我们需要确保将要放置创建的场景的视图与所需的类型相对应。 为此,请使用
guard构造-与
if
相同,只是相反(如果不是):
guard let skView = view as? SKView else { return }
确保屏幕元素匹配所需的类型后,我们将场景添加到其中:
skView.presentScene(scene)
您还需要显示每秒的帧数(FPS):
skView.showsFPS = true
然后显示场景中所有类型的元素数:
skView.showsNodeCount = true
让我们将元素显示在屏幕上,而不管它们在元素层次结构中的顺序如何:
skView.ignoresSiblingOrder = true
并且不要忘记我们的场景应该延伸到屏幕的整个宽度:
scene.scaleMode = .resizeFill
这是
GameViewController.swift文件的最终代码:
import UIKit import SpriteKit import GameplayKit class GameViewController: UIViewController { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() setup() } private func setup() { guard let skView = view as? SKView else { return } let scene = GameScene(size: view.bounds.size) skView.showsFPS = true skView.showsNodeCount = true skView.ignoresSiblingOrder = true scene.scaleMode = .resizeFill skView.presentScene(scene) } }
创建GameViewController.swift文件的详细信息。因此,我们创建了一个场景,但是它是空的,因此,如果现在运行模拟器,我们只会看到黑屏。
编写GameScene
与上次一样,我们删除了大部分代码,然后
对场景进行必要的设置 。 它也有自己的方法。 例如,由于将场景添加到ViewController中,因此需要
didMove()
方法:
override func didMove(to view: SKView) { setup(in: view) }
此外,当游戏开始时,每帧都会调用
Update()
方法:
override func update(_ currentTime: TimeInterval) { snake?.move() }
我们还需要一些处理程序来点击屏幕:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return }
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return }
如您所知,Swift以
语法糖的存在而闻名。 语法糖-这些技术方面的内容可以简化开发人员的工作,加快代码编写速度。 所有这些对设置场景很有帮助,我们现在要做的是。 首先,设置颜色:
backgroundColor = SKColor.white
由于蛇在飞机上工作,因此我们不需要物理学,您可以将其关闭,以免蛇由于重力而掉下。 另外,我们不需要游戏旋转等:
physicsWorld.gravity = .zero physicsWorld.contactDelegate = self physicsBody = SKPhysicsBody(edgeLoopFrom: frame) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = CollisionCategories.edgeBody physicsBody?.collisionBitMask = CollisionCategories.snake | CollisionCategories.snakeHead view.showsPhysics = true
现在创建按钮:
let counterClockwiseButton = ControlsFactory.makeButton(at: CGPoint(x: scene.frame.minX + 30, y: scene.frame.minY + 50), name: .counterClockwiseButtonName) addChild(counterClockwiseButton) let clockwiseButton = ControlsFactory.makeButton(at: CGPoint(x: scene.frame.maxX - 90, y: scene.frame.minY + 50), name: .clockwiseButtonName) addChild(clockwiseButton)
编写一段代码后,应该考虑是否可以对代码进行改进或重构,以便将来可以
重用 。 看,我们基本上在屏幕上有两个按钮,用于创建使用相同的代码。 因此,可以在单独的函数中取出此代码。 为此,使用以下代码
创建一个新类,并相应地
创建 ControlsFactory.swift文件:
import SpriteKit final class ControlsFactory { static func makeButton(at position: CGPoint, name: String) -> SKShapeNode { let button = SKShapeNode() button.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 45, height: 45)).cgPath button.position = position button.fillColor = .gray button.strokeColor = UIColor.lightGray.withAlphaComponent(0.7) button.lineWidth = 10 button.name = name return button } }
要绘制我们的蛇将“吃掉”的随机苹果,请
创建Apple类和
Apple.swift文件:
import SpriteKit final class Apple: SKShapeNode { let diameter: CGFloat = 10 convenience init(at point: CGPoint) { self.init() path = UIBezierPath(ovalIn: CGRect(x: -diameter/2, y: -diameter/2, width: diameter, height: diameter)).cgPath fillColor = .red strokeColor = UIColor.red.withAlphaComponent(0.7) lineWidth = 5 position = point physicsBody = SKPhysicsBody(circleOfRadius: diameter / 2, center: .zero) physicsBody?.categoryBitMask = CollisionCategories.apple } }
然后,我们使用
GameScene.swift中的
createApple()
函数描述我们的苹果:
private func createApple() { let padding: UInt32 = 15 let randX = CGFloat(arc4random_uniform(UInt32(gameFrameRect.maxX) - padding) + padding) let randY = CGFloat(arc4random_uniform(UInt32(gameFrameRect.maxY) - padding) + padding) let apple = Apple(at: CGPoint(x: randX, y: randY).relative(to: gameFrameRect)) gameFrameView.addChild(apple) }
好吧,这条蛇来了。 它由两部分组成:主体(
SnakeBodyPart.swift )和头部(
SnakeHead.swift )。
SnakeBodyPart.swift代码:
import SpriteKit class SnakeBodyPart: SKShapeNode { init(at point: CGPoint, diameter: CGFloat = 10.0) { super.init() path = UIBezierPath(ovalIn: CGRect(x: -diameter/2, y: -diameter/2, width: diameter, height: diameter)).cgPath fillColor = .green strokeColor = UIColor.green.withAlphaComponent(0.7) lineWidth = 5 position = point physicsBody = SKPhysicsBody(circleOfRadius: diameter - 4, center: .zero) physicsBody?.isDynamic = true physicsBody?.categoryBitMask = CollisionCategories.snake physicsBody?.contactTestBitMask = CollisionCategories.edgeBody | CollisionCategories.apple } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
SnakeHead.swift代码:
import SpriteKit final class SnakeHead: SnakeBodyPart { init(at point: CGPoint) { super.init(at: point, diameter: 20) physicsBody?.categoryBitMask = CollisionCategories.snakeHead physicsBody?.contactTestBitMask = CollisionCategories.edgeBody | CollisionCategories.apple } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
但是,
由于在视频中很好地显示
了创建GameScene.swift文件和其他类
的详细信息 ,
因此我们不会对每行进行描述。 我们提供的仅是为了查看
GameScene.swift的最终代码:
import SpriteKit import GameplayKit class GameScene: SKScene { var gameFrameRect: CGRect = .zero var gameFrameView: SKShapeNode! var startButton: SKLabelNode! var stopButton: SKLabelNode! var snake: Snake? override func didMove(to view: SKView) { setup(in: view) } override func update(_ currentTime: TimeInterval) { snake?.move() } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .green if touchedNode.name == .counterClockwiseButtonName { snake?.moveCounterClockwise() } else if touchedNode.name == .clockwiseButtonName { snake?.moveClockwise() } } else if touchedNode.name == .startButtonName { start() } else if touchedNode.name == .stopButtonName { stop() } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .gray } } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .gray } }
结果就是最简单的Snake游戏:

我们花了大约一个半小时来编写游戏。 如果您想掌握Swift的编程技能,请自己重复所有步骤。 顺便说一句,
在这里您将获得对该项目中使用的所有代码文件的完全访问权限。