勇者与羁绊 游戏开发日志(五)

8 篇文章 1 订阅
6 篇文章 2 订阅

开发进度

完成了基本的抽卡弃卡的逻辑

代码思路

首先我需要一个管理类,并且这是一个单例,用于持有一些全局变量以及控制所有的卡牌逻辑

然后从流程上来说分成三个部分展开
一、战斗开始
1.根据获取到的卡牌ID数组生成对象
2.将所有生成的对象打乱后放入抽牌堆数组
二、回合开始
调用抽牌方法,并传入一个int类型的参数,表示抽几张牌
这个参数得由一个管理类持有
三、回合结束
将所有的手牌和在本回合内使用过的卡牌都放入弃牌堆中

Ps.关于抽牌方法的实现逻辑流程图
在这里插入图片描述

具体执行步骤

Step1:创建管理类CardManager

public class CardManager : SingletonMonoBehaviour<CardManager>
{
    #region Piles
    public List<GameObject> AllCards;//所有的卡牌
    public List<GameObject> DrawPile;//这是抽牌堆
    public List<GameObject> FoldPile;//这是弃牌堆
    public List<GameObject> HandPile;//这是手牌堆
    public List<GameObject> UsedPile;//这是当前使用区,玩家在回合内打出的卡牌先进入当前使用区,在回合结束的时候再全部转入弃牌堆
    public List<GameObject> EquipPile;//这是装备区
    public List<GameObject> ExhaustPile;//这是放逐区
    #endregion

    #region PileParents
    public GameObject InitPile_Parent;//生成卡牌对象时所使用的父节点
    public GameObject DrawPile_Parent;//抽牌堆的父节点
    public GameObject FoldPile_Parent;//弃牌堆的父节点
    public GameObject HandPile_Parent;//手牌堆的父节点
    public GameObject UsedPile_Parent;//当前使用区的父节点
    public GameObject EquipPile_Parent;//装备区的父节点
    public GameObject ExhaustPile_Parent;//放逐区的父节点
    #endregion

    public GameObject CardPrefab;//卡牌的prefab

    public int DrawCount;//回合开始时的抽牌数
}

Step2:完成战斗开始部分的逻辑

因为BattleManager是控制战斗流程的管理器,所以通过PlayMaker来加载卡牌数据
在这里插入图片描述
LoadBattleInfoAction是扩展自FsmStateAction

public class LoadBattleInfoAction : FsmStateAction
{
    public override void OnEnter()
    {
        LoadMapInfo();
        LoadPlayerInfo();
        LoadCardInfo();
        LoadEnemiesInfo();
        Finish();
    }

    public void LoadMapInfo()
    {
        //TODO
    }

    public void LoadPlayerInfo()
    {
        //TODO
    }

    public void LoadCardInfo()
    {
        CardManager._instance.InitCards(TestData._instance.CardIDList);
    }

    public void LoadEnemiesInfo()
    {
        //TODO
    }
}

所调用的InitCards方法的实现方式:

	/// <summary>
    /// 战斗开始时初始化卡牌
    /// </summary>
    /// <param name="IDs"></param>
    public void InitCards(List<int> IDs)
    {
        //根据ID生成卡牌对象
        int i = 0;
        foreach (int id in IDs)
        {
            GameObject go = GameObject.Instantiate(CardPrefab, InitPile_Parent.transform);
            go.GetComponent<CardScriptContainer>().SetCardScriptByID(id);
            AllCards.Add(go);
            go.name = id + "";
            go.SetActive(false);
            i++;
        }
        //将数组打乱后放入抽牌堆
        DrawPile = Disorganize<GameObject>(AllCards); //这是一个用于打乱List的方法,定义在下面
        foreach (GameObject go in DrawPile)
        {
            go.transform.SetParent(DrawPile_Parent.transform);
        }
    }

	/// <summary>
    /// 将一个List打乱的方法
    /// </summary>
    /// <param name="input">所需打乱的List</param>
    /// <typeparam name="T">List的类型</typeparam>
    /// <returns></returns>
    private List<T> Disorganize<T>(List<T> input)
    {
        List<T> output = new List<T>();
        foreach (var item in input)
        {
            output.Insert(Random.Range(0, output.Count), item);
        }
        return output;
    }

Step3:完成回合开始部分的逻辑

通过PlayMaker对抽牌方法进行调用
在这里插入图片描述
以下是抽牌方法的实现方式:

	/// <summary>
    /// 抽牌
    /// </summary>
    /// <param name="count">抽牌的数量</param>
    public void DrawCard(int count)
    {
        if (count > DrawPile.Count + FoldPile.Count) count = DrawPile.Count + FoldPile.Count;
        if (count == 0) return;
        if (count > DrawPile.Count)
        {
        	//如果抽牌堆数量不足的话
            Shuffle();//先洗牌
            DrawCard(count);//再尝试抽一次牌
        }
        else
        {
        	//如果抽牌堆数量充足的话
            List<GameObject> temp = new List<GameObject>();
            //将抽牌堆中的对应数量的卡牌放入手牌堆
            for (int i = 0; i < count; i++)
            {
                HandPile.Add(DrawPile[i]);
                temp.Add(DrawPile[i]);
            }
            //再将放入手牌堆的那些牌从抽牌堆中移除
            foreach (GameObject go in temp)
            {
                DrawPile.Remove(go);
            }
            //刷新UI
            RefreshUI();
        }
    }

在写抽牌方法的时候,发现了之前流程图中存在的问题,那就是当抽牌数量超过了抽牌堆和弃牌堆数量之和时,会产生无限循环的问题。
因此在第一条判断中,就加入了一个这个判断:
如果抽牌数量大于抽牌堆和弃牌堆之和的话,就将抽牌数量改为最大数量。
如果这个数量是0的话,也就是抽牌堆和弃牌堆都没有卡牌但是仍然要抽牌的话,那么是不会有任何反应的。

抽牌方法中调用了一个洗牌方法
以下是洗牌方法的实现方式:

public void Shuffle()
    {
        DrawPile.AddRange(Disorganize<GameObject>(FoldPile));//Disorganize是前面提到的打乱一个List的方法
        FoldPile.Clear();
        RefreshUI();
    }

Step4:完成回合结束部分的逻辑

同样是通过PlayMaker调用CardManager的方法
在这里插入图片描述
以下是在回合结束时弃牌的方法实现:

public void FoldCardsOnTurnEnd()
    {
    	//将使用区和手牌区的卡牌全部移入弃牌区
        FoldPile.AddRange(UsedPile);
        FoldPile.AddRange(HandPile);
        //然后清空使用区与手牌区
        HandPile.Clear();
        UsedPile.Clear();
        RefreshUI();
    }

运行效果

正常情况下的测试

测试数据:
在这里插入图片描述
第一回合:
在这里插入图片描述
第二回合
上图中蓝色区域的应该移到弃牌堆,红色区域的应该移到手牌堆
实际效果:
在这里插入图片描述
第三回合
弃牌区应该为空,因为回合结束的时候先把手牌五张移入弃牌区,第三回合开始的时候要抽五张,但是抽牌堆中只有1张,所以会把弃牌堆洗回抽牌堆
然后手牌区的第一张应该是绿色的那张,下面四张是随机的,因为洗过牌了
抽牌堆则应该都是随机顺序的几张牌
实际效果:
在这里插入图片描述
第四回合
跟第二回合应该是同一种情况
实际效果:
在这里插入图片描述
第N回合
在N回合后,没有出现报错的现象。
正常情况功能测试完成。

当牌库数量少于每回合抽卡数量时的测试

在这里插入图片描述
第一回合
在这里插入图片描述
第二回合
在这里插入图片描述
第三回合
在这里插入图片描述
第N回合
每回合的卡牌顺序都会随机排序,在N回合后,没有出现报错的现象。
测试完成。

寻找合作

目前需要Unity开发程序员UI美术二次元人物原画师
数值、关卡、剧情等策划如果有兴趣也可以来聊一聊交流交流
如果有想参与项目的小伙伴,或者只是单纯想交朋友的,都可以添加我QQ:425202998

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值