1. 程式人生 > >一個卡牌遊戲的DEMO(0)

一個卡牌遊戲的DEMO(0)

最近有一個卡牌遊戲的創意,打算用Unity把Demo實現出來練練手。我儘量嘗試每天記錄一下開發的進度。
打算在這裡主要記錄遊戲設計和開發的過程,作為自己的一個摸索的記錄。
雖然只有一個人在做,但還是打算用git來做一下版本控制,畢竟回退之類的相當方便
https://github.com/LouisHuangGT/Yggdrasills-dream

這個遊戲類似於卡牌遊戲和類《神界:原罪》的回合制RPG結合。玩家扮演一個召喚師,可以將隨從召喚到戰場上(類似爐石和萬智牌),而在戰場上則遵循回合制戰棋遊戲的規則。玩家每個回合的資源由Action Point決定。做任何的動作:移動隨從,攻擊、打出卡牌都會消耗Action Point,因此玩家必須合理的規劃自己的Action Point來進行對戰。

此外,我們的Action Point不像爐石或萬智牌一樣每回合增長,而更像戰場女武神,每一個玩家召喚的強力角色(例如一個英雄單位)都會提高總的Action Point。為了增加趣味性,還為每個隊伍增加一個Magic Point資源,玩家作為召喚師,召喚到戰場上的隨從是靠法力進行維持的,因此在戰場上的每一個單位都會佔用一定的Magic Point,玩家需要規劃自己召喚出的隨從:例如可以召喚一個強力的隨從,但這會佔用全部的MP;也可以召喚許多脆弱的隨從。遊戲設計上大致就是這樣。一些具體的細節規則我還在進行調整。

可以看到,從實現的角度來看,我們主要要開發兩套系統:一個戰棋類回合制RPG和一個卡牌系統。兩者其實耦合程度很低,完全可以分開來進行實現。我打算先從比較核心的戰棋類回合制遊戲入手。

在寫程式碼之前我們先分析一遍戰棋類回合制RPG的戰鬥流程:
首先是回合內的流程:

Created with Raphaël 2.1.2玩家回合開始選擇一個單位AP是否耗完End彈出選單,選擇這個單位的動作執行動作動作是否執行完成?yesnoyesno

之後是回合間的流程

Created with Raphaël 2.1.2遊戲開始玩家回合玩家回合結束?敵方回合敵人回合結束?迴圈,直到達到勝利條件yesnoyesno

這個流程我們把它拆成兩塊來實現。首先一個全域性的TurnManager負責管理回合的進行:例如回合的切換等,這個類也負責用滑鼠選取的方式生成一個controllingUnit,使得玩家可以對其進行操作。即第一張流程圖到選取單位這個部分的內容在TurnManager中實現。而對於單個單位的操作可以抽象出來,由一個controller來進行。controller負責接收按鈕的回撥,確定玩家下的指令,並分配當前這個controller正在操作的unit來執行這個指令。Controller主要通過一個Run函式進行實現,這個函式輸入一個選中的單位,然後對這個單位進行一系列的玩家操作。返回操作是否成功/完成。如果操作成功則進入下一個選單位流程,否則不做任何操作,繼續這個操作(如流程圖1所示)。

玩家的單位目前用一個基類Unit來處理,玩家的具體操作以及一系列的判定就在unit中進行實現。

首先是TurnManager的update()實現:
整個遊戲程序的執行相當於全部在這個update中實現。這個update的作用相當於選中單位和對應的操作後等待操作完成,操作完成後選下一個單位,如果沒有完成則阻塞等待操作完成(這裡的阻塞利用了update每幀迴圈呼叫的特性來實現,不需要自己寫一個死迴圈來阻塞)

void Update () {
        if (selectedUnit != null)
        {
            if (controller.run(selectedUnit))
            {
                team[currenTeamIndex].ActionPoint--;
                selectedUnit = selectUnit();
            }
            //選中一個單位,把它放到controller進行操作,並返回一個操作是否完成的布林值。
            //如果操作完成,那麼這個隊伍的AP減少1,並選一個新的單位
            //如果操作還沒完成,那麼不做任何事情,下一幀繼續這個操作
        }
        if (team[currenTeamIndex].ActionPoint <= 0)
        {
            team[currenTeamIndex].ActionPoint = team[currenTeamIndex].maxActionPoint;
            currenTeamIndex = 1 - currenTeamIndex;
        }
        //當一個隊伍的AP小於等於0時,我們重置這個隊伍的AP並將當前的控制權轉移到另一支隊伍上面(即改變當前索引值)
    }

其中的SelectUnit函式實現比較簡單,目前用了一個滑鼠raycast的方法來選中對應物體

GameObject selectUnit()
    {
        if (Input.GetMouseButtonUp(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                if (isIn(hit.transform.gameObject, team[currenTeamIndex].units))
                //判斷選中的這個單位是不是在(isIn)當前的隊伍列表中,只有選中當前隊伍的單位才返回
                    return hit.transform.gameObject;
                else
                    return null;
            }
            else
                return null;
        }
        else
            return null;
    }

有了TurnManager以後,我們就可以開始實現Controller裡面的Run函式。這個函式負責給selectedUnit分配一個操作,並執行。

public bool run(GameObject selectedUnit)
    {
        controllerMenu.SetActive(true);
        Unit unit = selectedUnit.GetComponent<Unit>();

        bool result = false;
        switch (currentState)
        {
            case State.IDLE:
                result = false;
                break;
            case State.MOVE:
                result = unit.Move();
                break;
            case State.ATTACK:
                result = unit.Attack();
                break;
            case State.SKILL:
                result = unit.Cast();
                break;
            case State.SUMMON:
                result = unit.Summon();
                break;
            default:
                result = false;
                break;
        }
        if (result == true)
        {
            currentState = State.IDLE;
            controllerMenu.SetActive(false);
        }
        return result;
    }

目前暫定有四種操作:移動、攻擊、使用技能(一些隨從有主動技能)和召喚(即使用卡牌)。在unit類中進行具體實現。
其中currentState由四個按鈕的回撥函式來設定對應的值,例如按下Move按鈕對應的值就是State.MOVE。最後這個函式需要返回一個執行的結果,如果進行了操作,那麼返回操作的結果,如果沒有按下任何按鈕(沒有輸入,即IDLE狀態),則返回false。

最後,在Unit類中,實現了一個移動的功能

 public bool Move()
    {
        if (Input.GetMouseButtonUp(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                agent.SetDestination(hit.point);
            }
        }
        if (agent.remainingDistance < agent.radius && agent.hasPath)
            return true;
        else
            return false;
    }

一個比較簡單的點選地面移動的實現。每次執行的時候檢測是否有滑鼠按鍵擡起,如果有則射一道光束到地面,並用NavMeshAgent將當前單位移動過去。設定完目的地後判斷一下剩餘距離是否小於agent的半徑,如果是的說明到達目的地,返回true說明操作結束,可以進行下一個單位的選擇和操作;如果沒有,說明操作沒有結束,返回false,下次update繼續這個操作。
這邊的實現其實會有一點bug,如果選擇move以後在到達目的地前不停點選滑鼠會使單位不停的重新定向,可以考慮在input裡面加一個flag使得在到達目的地前只能接受一次滑鼠的輸入。另外在移動過程中我個人傾向於還是需要把選單暫時關閉,這個需要調整一下controller中的實現。
程式碼寫完以後場景就比較好處理了。我做了一個賊簡單的場景,其中藍色方塊是己方單位,紅色方塊是敵方單位。選中效果還沒有加上,但目前已經可以接近回合制式的移動各個單位了。
這裡寫圖片描述
今天基本上把回合制的框架搭了個七七八八,下面可以往裡面填unit中的幾個操作的實現了。下面一個比較麻煩是一套RPG系統,例如實現血量、攻擊等等機制。另外ActionPoint這個機制也要做更復雜的實現,每一個技能、每一個動作都應該有一個自己消耗的ActionPoint。最後,其實這樣去實現一個回合制的流程動作應該還有不少bug,還要等後面慢慢進行重構。

相關推薦

一個遊戲DEMO0

最近有一個卡牌遊戲的創意,打算用Unity把Demo實現出來練練手。我儘量嘗試每天記錄一下開發的進度。 打算在這裡主要記錄遊戲設計和開發的過程,作為自己的一個摸索的記錄。 雖然只有一個人在做,但還是打算用git來做一下版本控制,畢竟回退之類的相當方便 ht

利用Vuforia開發一個AR對戰:多圖識別+EventHandler框架

卡牌對戰1:多圖識別+EventHandler框架 這個系列主要講解實現一個簡易的AR卡牌對戰的功能,這次首先實現多圖識別和EventHandler的框架介紹。 首先我們來實現多圖識別。 1.上傳識別圖並下載資料包,然後得到LicenseKey。這裡用了兩個識別圖,一次打包

使用unity製作的一款生存類遊戲demo

   花了20多天的時間來完成這個demo,主要是為了實現一些自己設想的功能,並未注重關卡和玩法的設計,整體上還不夠完善或者說不夠完整。    demo中的美術資源均來自asset store和各種資源網站。使用的外掛有NGUI,post progressing stack

【BZOJ】3191 [JLOI2013]遊戲概率dp

如果 style ++ bzoj mem color con size oid 題目 傳送門:QWQ 分析 算是概率dp不錯的題。 $ dp[i][j] $表示有i個人時,這i個人中的第j個獲勝的概率。 我們把i從1推到n,那麽答案就是$ dp[n

H - 遊戲簡單期望

Description 小貝喜歡玩卡牌遊戲。某個遊戲體系中共有N種卡牌,其中M種是稀有的。小貝每次和電腦對決獲勝之後都會有一個抽卡機會,這時系統會隨機從N種卡中選擇一張給小貝。普通卡可能多次出現,而稀有卡牌不會被重複抽到。小貝希望收集到K種稀有卡牌,她想知道期望需要多少次獲勝才能實現這個目標

概率/dpP2059 [JLOI2013]遊戲

https://www.luogu.org/problemnew/show/P2059 第一次做概率dp的題,還以為要用組合數學知識去推公式 上次牛客也遇到概率dp的題,就忘了補題 考慮從1個人正推到n個人的情況,發現k個人的時候通過抽牌淘汰掉一個人之後能從k-1已經計算的狀態轉

【貪心】【2018.10.1提高組模擬】T1WOJ 2687 遊戲

題目(卡牌遊戲): 【題目描述】   L最近喜歡上了一個卡片遊戲,遊戲規則是: 2個人一共拿2n張卡片,編號1..2n,每個人n張,然後進行n輪出牌,每輪2個人都打一張牌,,點數大的玩家每次獲1分 L可以預測到對方要打牌的順序。 同時,L有一次機會選擇了某個時間點,從

2018.10.01 NOIP模擬 遊戲貪心

描述 L最近喜歡上了一個卡片遊戲,遊戲規則是: 2個人一共拿2n張卡片,編號1…2n,每個人n張,然後進行n輪出牌,每輪2個人都打一張牌,,點數大的玩家每次獲1分 L可以預測到對方要打牌的順序。 同時,

遊戲簡單期望

Description 小貝喜歡玩卡牌遊戲。某個遊戲體系中共有N種卡牌,其中M種是稀有的。小貝每次和電腦對決獲勝之後都會有一個抽卡機會,這時系統會隨機從N種卡中選擇一張給小貝。普通卡可能多次出現,而稀有卡牌不會被重複抽到。小貝希望收集到K種稀有卡牌,她想知道期望需要多少次獲

一個AngularJS Demo購物車

mod 購物 set sco tle ng-model -m -c 刪除 <!DOCTYPE html><html><head>   <meta charset="utf-8" />   <script sr

Java反射機制demo—獲得並調用一個類中的方法

color 擁有 oca logs over super getmethod equals() bool 這個demo在使用反射機制操作屬性之前,主要原因是因為在.class文件字節碼中,方法排在屬性的前面。 1,獲得一個類中的方法 先看一下方法和運行結果。獲取所有的方

PTA 陣列迴圈左移 20 分 本題要求實現一個對陣列進行迴圈左移的簡單函式:一個數組a中存有n>0)個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向左移m0)個位置,即將a中的

陣列迴圈左移 (20 分) 本題要求實現一個對陣列進行迴圈左移的簡單函式:一個數組a中存有n(>0)個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向左移m(≥0)個位置,即將a中的資料由(a​0​​a​1​​⋯a​n−1​​)變換為(a​m​​⋯a​n−

細解一個dubbo的小demo附原始碼

今天小編來說說怎麼使用dubbo+zookeeper+maven+Idea搭建一個小demo——HelloWorld。 新建框架 首先新建專案框架,並在pom.xml中進行maven的相關配置。 完善api專案 我們知道,client和server專案都依賴於

一天練習一個小C/C++程式 控制檯版“金山打字”遊戲

今天練習了一個C語言小程式,控制檯版的簡易“金山打字”小遊戲。 效果圖: 程式碼: #include<stdio.h> #include<stdlib.h> #incl

手把手教你做一個 C 語言編譯器0:前言

“手把手教你構建 C 語言編譯器” 這一系列教程將帶你從頭編寫一個 C 語言的編譯器。希望通過這個系列,我們能對編譯器的構建有一定的瞭解,同時,我們也將構建出一個能用的 C 語言編譯器,儘管有許多語法並不支援。 在開始進入正題之前,本篇是一些閒聊,談談這個系列的初衷

造輪子:搭建一個簡單的nodejs伺服器,從零開始搭建一個自用網站0

伺服器用的是阿里雲最早期的伺服器低配版本1Gcpu,512M記憶體,20G硬碟,1M頻寬,平常只是用來做測試,目前只處理業務邏輯,網站的設計上儘量避免佔用太多的頻寬, 靜態檔案的儲存用的是阿里雲oss,100G空間,夠放視訊,圖片什麼的, html/js/c

5分鐘搭建一個HTML5視訊聊天DemoWebRTC+NodeJS

轉載自: http://blog.csdn.net/u012377333/article/category/2670379   謝謝版主 到 http://nodejs.org/ 下載最新版nodejs,我下的是“node-v0.10.7-x86.msi”。 安裝,

怎麼通過Unity和谷歌紙盒做一個VR遊戲

作者是用iPhone適配的,我是用的Android手機且由於SDK版本的關係所以會有些小細節不一樣。 遊戲工程地址:忍者飛鏢                                                                        

使用php完成一個使用者註冊以及管理的demo

1.設計mysql的使用者表 2.設計檔案結構 3.製作後臺增加使用者的介面 4.對於資料庫操作的封裝,用來操作資料庫的一些方式 5. include.php的製作 (1)使用者表的設計 mysql資料庫 /如果使用者表user已經存在的

一個jmter介面測試的demo轉載

轉載地址忘了。。。 將下面的程式碼貼上儲存為demotest.jmx檔案,然後再jmeter中開啟 <?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properti