極致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