极致2d游戏开发

火男无脑开发录

前介

  • 开发引擎:SpriteKit
  • 开发语言:Swift
  • 其他:NodeJS(放弃) ,MySQL(放弃)

走着

我写了个标题叫极致,我要做个游戏,然后顺带写这个教程,但是实际上意思是反的,我以做个游戏的名义来特地写个教程。

先介绍将要开发的游戏,一款类似跑酷类型,主角为一只小兔子,游戏开始会一直往前冲,但是前面却是万丈深渊,所以需要玩家点击屏幕在下方生成一个平台,避免小兔子掉下去,玩家需要控制平台升降的高度,太高了小兔子会上不去gg,如果平台降得很低,小兔子也将掉出屏幕,同样gg。游戏的目标是,在有限的下降空间内让小兔子跑得更远,后面编写的后台程序将纪录下每次小兔子的跑酷纪录,然后写入数据库,当点开排名界面的时候,将从后台获取前10位玩家的纪录。

流程就介绍完了,开干吧……

因为打算只针对游戏开发流程,所以其他不相干的知识尽量摒弃,前提是熟悉Swift 这门语言,而SpriteKit 也仅支持Obj-CSwift

以下为将用到的美术资源


屏幕快照 2016-06-04 下午8.09.53.png

新建工程

屏幕快照 2016-06-04 下午8.11.16.png

屏幕快照 2016-06-04 下午8.11.51.png

直接选择Game ,填写项目名语言、框架、运行的平台。
屏幕快照 2016-06-04 下午8.12.16.png

next保存到目录,xcode与git是无缝衔接的,需要版本管理或远程协同就选上吧。
屏幕快照 2016-06-04 下午8.12.40.png

一个简单的工程,默认有架飞机,但是删掉,GameScene中涉及不相干逻辑的部分也删掉,并且不涉及游戏逻辑的类文件或资源文件放在新建的Group 中。

创建第一个类

configue 用来保存游戏中的全局属性。

屏幕快照 2016-06-04 下午8.14.29.png

游戏画面尺寸设置为1242*2208,因为我们的游戏场景是用的sks文件读取的方式,所以sks文件中需要手动设置一下场景尺寸跟winSize一致即可。

屏幕快照 2016-06-04 下午8.14.51.png

屏幕快照 2016-06-04 下午8.16.00.png

设计好游戏逻辑的层级关系

  • 菜单层
  • 角色层
  • 背景层
    屏幕快照 2016-06-04 下午8.55.59.png

    游戏中各类元素的前后关系写在configure中,姑且把configure看作是包含各种宏定义的类吧。
    屏幕快照 2016-06-04 下午9.01.08.png

    notificationCenter为获取的消息中心实例,backgroundMove``backgroundStop用来表示控制背景移动和停止的消息名称。

编写内容

屏幕快照 2016-06-04 下午9.05.30.png

先从地面平台开始,一步步拓展看,地面以一条三块土方组合成的平台柱子为一个单位,分为上中下,中层可以根据需要放置一个或者多个土块,上下土块固定好。

创建土块

打开GroundCobe.swift编写以下代码

屏幕快照 2016-06-04 下午9.11.45.png

以最上层的土块贴图创建SKSpriteNode对象,在此基础上添加中层土块,最后在底部添加下层土块。完成这一步,开始创建整个游戏的背景类,稍后将在背景类中添加土块。

创建背景

打开Background.swift编写以下代码

屏幕快照 2016-06-04 下午9.28.40.png

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()
    }

创建小兔子

屏幕快照 2016-06-04 下午9.35.42.png

小兔子的素材分三组动画序列帧,跑动,禁止,下落

打开Player.swift编写以下代码

屏幕快照 2016-06-04 下午9.54.43.png

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)
            }
        }
    }
    

完事

大概就是这么个过程,原来还有不少东西要写,我简化了些,但是。。。这玩意能跑
呵呵
美术图地址:百度网盘

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 由于很多小伙伴要demo我就不一一发了,直接丢在github上自己下载吧:https://github.com/s...
    FKSky阅读 23,650评论 27 99
  • 总是在看纪录片的时候,在看到先人对于国家的信念,感到热泪盈眶,继而又会产生深深的无奈。这是个,没有太多信念的时代。
    科尔摩斯阅读 162评论 0 0
  • “人是欲望的傀儡!” “我是一名召唤师,问我召唤什么?那么 我告诉你,是欲望!” 当我说出这句话以后,整个召唤师聚...
    今何在jhz阅读 272评论 0 0
  • 那些年 鲜血染红了长髯 那些年 笛声美哭了云天 那些年 寒气拥抱着长剑 那些年 晚霞喧嚣过海湾 有故事的人 永远不...
    卍天下卐阅读 167评论 0 0
  • 6月份,杭州进入梅雨季节,24号早上,整个杭城都是倾盆大雨。中午吃过午饭,雨好像小了一点,因一天宅在宿舍,午觉从下...
    fly1a阅读 125评论 0 0