Unity3D手機鬥地主遊戲開發實戰(03)_地主牌顯示和出牌邏輯

Hi,以前有同窗說要我把源碼發出來,那我就把半成品源碼的連接放在每篇文件的最後,有興趣的話能夠查閱參考,有問題能夠跟我私信,也能夠關注個人我的公衆號,互相交流嘛。固然,代碼也是在不斷的持續改進中~git

上期咱們實現了叫地主功能,不過遺留了一個小功能:叫地主完成之後,要顯示地主的3張牌,這期首先彌補這塊的功能;github

接着咱們要進入開發出牌邏輯的開發階段,好了,廢話很少說,繼續咱們鬥地主開發之旅~dom

地主牌的顯示

咱們在玩家界面的頂部中間位置,放置一個新的GameObject,命名爲BidCards,用來記錄3張地主牌的顯示位置。ide

因此咱們重構了CardManager中的發牌方法,在給地主發牌同時,生成地主牌的實例,放在BidCards相應位置:測試

    /// <summary>
    /// 發牌堆上的牌(若是如今不是搶地主階段,發普通牌,若是是,發地主牌)
    /// </summary>
    /// <returns></returns>
    private IEnumerator DealHeapCards(bool ifForBid)
    {
        //顯示牌堆
        heapPos.gameObject.SetActive(true);
        playerHeapPos.ToList().ForEach(s => { s.gameObject.SetActive(true); });

        var cardNamesNeeded = ifForBid
            ? cardNames.Skip(cardNames.Length - 3).Take(3)  //若是是搶地主牌,取最後3張
            : cardNames.Take(cardNames.Length - 3);         //若是首次發牌

        //計算每張地主牌的位置
        int cardIndex = 0;
        var width = (bidCards.GetComponent<RectTransform>().sizeDelta.x - 20) / 3;
        var centerBidPos = Vector3.zero;
        var leftBidPos = centerBidPos - Vector3.left * width;
        var rightBidPos = centerBidPos + Vector3.left * width;
        List<Vector3> bidPoss = new List<Vector3> { leftBidPos, centerBidPos, rightBidPos };
        foreach (var cardName in cardNamesNeeded)
        {
            //給當前玩家發一張牌
            Players[termCurrentIndex].AddCard(cardName);

            var cover = Instantiate(coverPrefab, heapPos.position, Quaternion.identity, heapPos.transform);
            cover.GetComponent<RectTransform>().localScale = Vector3.one;
            //移動動畫,動畫結束後自動銷燬
            var tween = cover.transform.DOMove(playerHeapPos[termCurrentIndex].position, 0.3f);
            tween.OnComplete(() => Destroy(cover));

            yield return new WaitForSeconds(1 / dealCardSpeed);

            //若是給地主發牌
            if (ifForBid)
            {
                //顯示地主牌
                var bidcard = Instantiate(cardPrefab, bidCards.transform.TransformPoint(bidPoss[cardIndex]), Quaternion.identity, bidCards.transform);
                bidcard.GetComponent<Card>().InitImage(new CardInfo(cardName));
                bidcard.GetComponent<RectTransform>().localScale = Vector3.one * 0.3f;
            }
            else
            {
                //下一個須要發牌者
                SetNextPlayer();
            }

            cardIndex++;
        }

        //隱藏牌堆
        heapPos.gameObject.SetActive(false);
        playerHeapPos[0].gameObject.SetActive(false);

        //發普通牌
        if (!ifForBid)
        {
            //顯示玩家手牌
            ShowPlayerSelfCards();
            StartBiding();
        }
        //發地主牌
        else
        {
            if (Players[bankerIndex] is PlayerSelf)
            {
                //顯示玩家手牌
                ShowPlayerSelfCards();
            }
            StartFollowing();
        }
    }
View Code

好的,咱們地主牌顯示已經沒有問題了,接下來,咱們要實現出牌回合邏輯動畫

出牌回合功能實現

出牌回合其實跟叫地主回合相似,也是能夠抽象出3種方法:進入出牌階段、出牌、不出(比較進入叫地主階段、叫地主、不叫地主);spa

所以,咱們參照叫地主的邏輯,再實現出牌邏輯:3d

調整Player基類

添加開始出牌ToFollowing、出牌ForFollow、不出NotFollow:code

  • ToFollowing:進入本身回合,關閉其餘人的倒計時,進入本身的倒計時階段;
  • ForFollow:關閉本身的倒計時,而後將選擇的牌添加到出牌區域,跳出本身回合;
  • NotFollow:關閉本身的倒計時,跳出本身回合;
    /// <summary>
    /// 開始出牌
    /// </summary>
    public virtual void ToFollowing()
    {
        isMyTerm = true;

        //關閉倒計時
        StopCountDown(CountDownTypes.Follow);

        //開始倒計時
        StartCountDown(CountDownTypes.Follow);
    }
    /// <summary>
    /// 出牌
    /// </summary>
    public void ForFollow()
    {
        //關閉倒計時
        StopCountDown(CountDownTypes.Follow);

        //選擇的牌,添加到出牌區域
        var selectedCards = cardInfos.Where(s => s.isSelected).ToList();
        var offset = 5;
        for (int i = 0; i < selectedCards.Count(); i++)
        {
            var card = Instantiate(prefabSmall, smallCardPos.position + Vector3.right * offset * i, Quaternion.identity, smallCardPos.transform);
            card.GetComponent<RectTransform>().localScale = Vector3.one * 0.3f;
            card.GetComponent<Image>().sprite = Resources.Load("Images/Cards/" + selectedCards[i].cardName, typeof(Sprite)) as Sprite;
            card.transform.SetAsLastSibling();

            smallCards.Add(card);
        }
        cardInfos = cardInfos.Where(s => !s.isSelected).ToList();

        CardManager._instance.ForFollow();
        isMyTerm = false;
    }
    /// <summary>
    /// 不出
    /// </summary>
    public void NotFollow()
    {
        //關閉倒計時
        StopCountDown(CountDownTypes.Follow);

        CardManager._instance.NotFollow();
        isMyTerm = false;
    }
    /// <summary>
    /// 銷燬出牌對象
    /// </summary>
    public void DropAllSmallCards()
    {
        smallCards.ForEach(Destroy);
        smallCards.Clear();
    }
View Code

調整PlayerSelf類

實現ToFollowing:orm

調用基類的ToFollowing,並顯示出牌按鈕以供玩家選擇

    /// <summary>
    /// 開始出牌
    /// </summary>
    public override void ToFollowing()
    {
        base.ToFollowing();
        CardManager._instance.SetFollowButtonActive(true);
    }
View Code

調整PlayerOther類

模擬出牌,隨機選擇除手牌中的一張

    void Update()
    {
        //若是當前是本身回合,模擬對手叫牌
        if (isMyTerm)
        {
            if (CardManager._instance.cardManagerState == CardManagerStates.Bid)
            {
                if (Input.GetKeyDown(KeyCode.Q))    //叫牌
                {
                    ForBid();
                }
                if (Input.GetKeyDown(KeyCode.W))    //不叫
                {
                    NotBid();
                }
            }
            if (CardManager._instance.cardManagerState == CardManagerStates.Playing)
            {
                if (Input.GetKeyDown(KeyCode.Q))    //出牌
                {
                    var rd1 = Random.Range(0, cardInfos.Count);
                    cardInfos[rd1].isSelected = true;

                    ForFollow();
                }
                if (Input.GetKeyDown(KeyCode.W))    //不出
                {
                    NotFollow();
                }
            }
        }
    }
View Code

調整CardManager

實現卡牌管理對玩家出牌的控制:

  • 發完地主牌之後,開始出牌階段,由地主先出牌;
  • 玩家選擇出牌後,將上輪玩家的出牌堆清空,並將選擇的牌添加到本身的出牌堆,輪轉到下個玩家;
  • 玩家選擇不出牌,將上輪玩家的出牌堆清空,輪轉到下個玩家;
    /// <summary>
    /// 開始出牌階段
    /// </summary>
    private void StartFollowing()
    {
        cardManagerState = CardManagerStates.Playing;
        //地主先出牌
        Players[bankerIndex].ToFollowing();
    }
    /// <summary>
    /// 玩家出牌
    /// </summary>
    public void ForFollow()
    {
        SetFollowButtonActive(false);

        //上輪玩家出牌清空
        Players[(termCurrentIndex + Players.Length - 1) % 3].DropAllSmallCards();
        if (Players[termCurrentIndex] is PlayerSelf)
            ShowPlayerSelfCards();

        SetNextPlayer();
        Players[termCurrentIndex].ToFollowing();
    }
    /// <summary>
    /// 玩家不出
    /// </summary>
    public void NotFollow()
    {
        SetFollowButtonActive(false);

        //上輪玩家出牌清空
        Players[(termCurrentIndex + Players.Length - 1) % 3].DropAllSmallCards();

        SetNextPlayer();
        Players[termCurrentIndex].ToFollowing();
    }
View Code

代碼整理

如今咱們的代碼具備必定的規模了,爲了方便更好的管理,把現有的代碼從新整理一下,並進行功能分類,好比:

    

總結

嗯,今天到此爲止,咱們再來測試驗證下,固然,目前只是實現了出牌的功能,沒有對牌力進行校驗和出牌的控制,對手玩家隨機模擬出牌,還沒有加入AI。咱們之後逐步去實現~來看看這期的效果吧~

資源

項目源碼

相關文章
相關標籤/搜索