火男无脑开发录
前介
- 开发引擎:SpriteKit
- 开发语言:Swift
- 其他:NodeJS(放弃) ,MySQL(放弃)
走着
我写了个标题叫极致,我要做个游戏,然后顺带写这个教程,但是实际上意思是反的,我以做个游戏的名义来特地写个教程。
先介绍将要开发的游戏,一款类似跑酷类型,主角为一只小兔子,游戏开始会一直往前冲,但是前面却是万丈深渊,所以需要玩家点击屏幕在下方生成一个平台,避免小兔子掉下去,玩家需要控制平台升降的高度,太高了小兔子会上不去gg,如果平台降得很低,小兔子也将掉出屏幕,同样gg。游戏的目标是,在有限的下降空间内让小兔子跑得更远,后面编写的后台程序将纪录下每次小兔子的跑酷纪录,然后写入数据库,当点开排名界面的时候,将从后台获取前10位玩家的纪录。
流程就介绍完了,开干吧……
因为打算只针对游戏开发流程,所以其他不相干的知识尽量摒弃,前提是熟悉Swift 这门语言,而SpriteKit 也仅支持Obj-C 和Swift 。
以下为将用到的美术资源
新建工程
直接选择Game ,填写项目名语言、框架、运行的平台。
next保存到目录,xcode与git是无缝衔接的,需要版本管理或远程协同就选上吧。
一个简单的工程,默认有架飞机,但是删掉,
GameScene
中涉及不相干逻辑的部分也删掉,并且不涉及游戏逻辑的类文件或资源文件放在新建的Group 中。
创建第一个类
configue
用来保存游戏中的全局属性。
游戏画面尺寸设置为1242*2208,因为我们的游戏场景是用的sks文件读取的方式,所以sks文件中需要手动设置一下场景尺寸跟winSize
一致即可。
设计好游戏逻辑的层级关系
- 菜单层
- 角色层
- 背景层
游戏中各类元素的前后关系写在configure
中,姑且把configure
看作是包含各种宏定义的类吧。
notificationCenter
为获取的消息中心实例,backgroundMove``backgroundStop
用来表示控制背景移动和停止的消息名称。
编写内容
先从地面平台开始,一步步拓展看,地面以一条三块土方组合成的平台柱子为一个单位,分为上中下,中层可以根据需要放置一个或者多个土块,上下土块固定好。
创建土块
打开GroundCobe.swift
编写以下代码
以最上层的土块贴图创建
SKSpriteNode
对象,在此基础上添加中层土块,最后在底部添加下层土块。完成这一步,开始创建整个游戏的背景类,稍后将在背景类中添加土块。
创建背景
打开Background.swift
编写以下代码
notificationCenter.addObserver(self, selector: #selector(Background.move), name: kBackgroundMove, object: nil)
notificationCenter.addObserver(self, selector: #selector(Background.stop), name: kBackgroundStop, object: nil)
添加两个消息监听用来控制背景的移动和停止,当小兔子掉落的时候,背景保持禁止,当小兔子跑动的时候,背景往后移动。
在GameScene.swift
中的didFinishUpdate
中添加背景的更新函数调用
override func didFinishUpdate() {
background.didFinishUpdate()
}
创建小兔子
小兔子的素材分三组动画序列帧,跑动,禁止,下落
打开Player.swift
编写以下代码
state
用来表示小兔子当前的状态,并定义分别包含三种状态序列帧的贴图数组runTextures
fallTextures
stayTextures
。
添加以下方法,用来切换小兔子状态,并通知背景层做相应停止或移动处理,这样只需要控制小兔子的状态,便能让背景的状态与只同步。
//Mark:角色动作状态切换
func setState(newState: PlayerState){
state = newState
removeAllActions()
switch state! {
case .Run:
let action = SKAction.animateWithTextures(runTextures, timePerFrame: 0.1)
runAction(SKAction.repeatActionForever(action))
//通知背景开始平移
����notificationCenter.postNotificationName(kBackgroundMove, object: nil)
case .Fall:
��let action = SKAct����ion.animateWithTextures(fallTextures, timePerFrame: 0.2)
runAction(action)
//通知背景停止平移
notificationCenter.postNotificationName(kBackgroundStop, object: nil)
case .Stay:
let action = SKAction.animateWithTextures(stayTextures, timePerFrame: 0.1)
runAction(SKAction.repeatActionForever(action))
//通知背景停止平移
notificationCenter.postNotificationName(kBackgroundStop, object: nil)
}
需要模拟兔子的坠落效果,那么给兔子添加物理体
private func setPhysics(){
physicsBody = SKPhysicsBody(circleOfRadius: size.width * 0.4)
physicsBody?.allowsRotation = false
physicsBody?.categoryBitMask = Bitmask.player
physicsBody?.collisionBitMask = Bitmask.cobe //设置能与之产生物理碰撞的物体
physicsBody?.contactTestBitMask = Bitmask.cobe | Bitmask.enemy //设置能与之检测碰撞的物体
physicsBody?.restitution = 0 //设置反弹力度
}
configure.swift
中定义的各个物体物理体是UInt32
类型,意味着一个游戏可以创建32种不同类型的物理体,应该足够了
//物理体
struct Bitmask{
static let cobe:UInt32 = 0x1 << 1 //地面
static let player:UInt32 = 0x1 << 2 //角色
static let enemy:UInt32 = 0x1 << 3 //障碍物
}
在GameScene中合并它们
准确的说法是编写控制土块移动的交互代码和小兔子状态被动切换的代码
物理体协议
这个。。。有个小意外,本来是通过物理体碰撞来控制小兔子的状态切换,后来发现这种方式很不靠谱,所以不用了。而且后来我做的项目基本上是避免让他附带物理效果,或者能自己写编自己写,实际上原生得并不好控制细节(除非只需要真实的物理模拟)
让兔子活动起来
在GameScene.swift
下的Update
函数中写一些简单代码
override func update(currentTime: CFTimeInterval) {
//当小兔子位置超出屏幕便结束游戏
if player.position.y < 0 || player.position.x > winSize.width || player.position.x < 0 {
isGameover = true
}
//既然结束游戏了,下面就不执行了guard的具体含义百度百度
guard !isGameover else{
return
}
//通过获取小兔子当前的运动矢量来判断小兔子当前的状态
//dy<0 意味着它正在下落,那么切换兔子状态吧
//否则dx<0意味着它被卡住了,游戏结束,并切换状态为停止
//否则意味着它在平地上了,那么让它跑起来吧
let playerVelocity = player.physicsBody!.velocity
if playerVelocity.dy < 0 {
player.setState(.Fall)
}else{
if playerVelocity.dx < -0.05 {
isGameover = true
player.setState(.Stay)
}else{
player.setState(.Run)
}
}
}
完事
大概就是这么个过程,原来还有不少东西要写,我简化了些,但是。。。这玩意能跑
呵呵
美术图地址:百度网盘