unity3d-学习笔记16-卡牌游戏制作(部分功能的优化)
修复boss 和人物的血量超过预设值没有保持预设值的bug
加多一个判断即可
if (bossLife>100)
{
GameObject.Find("lifeNumber").GetComponent<Text>().text = 100 + "";
}
实现每15张为一组,不断循环出牌的功能
逻辑
目前想到的逻辑是利用之前打出的牌都存到了cardUsed集合里的功能,将点击下一回合中cardList集合里的卡类替换成cardUsed集合里的数据
2021.2.23更新:思路有问题,应该给卡类添加一个属性,记录是否被打出去了,如果被打出去了,则bool设为true,然后在抽卡的时候判断有没有卡属性里是否打出的属性为true的卡类,有的话则为他们创建一个新的集合,并打乱他们的顺序,才将牌打出,打出的时候还要把是否打出的属性的bool还原回false,从而实现循环。目前这个思路好像没什么毛病
具体实现
2021.2.24更新,昨天的思路是没问题的,今天实现了,关键点是通过在初始化卡牌的时候给他一个标记,我这里是给卡添加了一个id,因为id是惟一的,所以可以通过id来追踪到卡,通过cardController在每次把当前卡打出去的时候,获得当前卡的id,然后根据ID用集合里的findindex方法
FindIndex(c => c.Id == cardId)
如上,这是用了lambda表达式(没记错的话),c是声明一个变量,任意字母都行,然后后面跟着判定条件,如果找到条件的变量,会返回这个变量的索引
通过这个方法把索引对应的卡牌的是否被打出的bool值修改为true,从而在每次点击下一回合的时候循环cardList集合,找到其中bool为true的卡,意味着已经被打出了。然后打乱发出。即可实现
int cardId = int.Parse(gameObject.transform.GetChild(6).GetComponent<Text>().text);
int index = CardDesktop.cardList.FindIndex(c => c.Id == cardId);
CardDesktop.cardList[index].isActive = true;
如图,上面是cardController类在打出当前卡的时候获得当前卡的id,然后根据id获得他在集合里的索引,然后修改bool值
foreach (Card card in CardDesktop.cardList)
{
if (card.isActive)
{
linShiJiHe.Add(card);//把已经打过的牌记录到临时的集合里方便后面洗牌和发牌
}
}
//打乱已经使用过的卡牌的集合
//为了降低运算的数量级,当执行完一个元素时,就需要把此元素从原List中移除
int countNum = linShiJiHe.Count;
//使用while循环,保证将a中的全部元素转移到b中而不产生遗漏
List<Card> b = new List<Card>();
while (b.Count < countNum)
{
//随机将a中序号为index的元素作为b中的第一个元素放入b中
int index = Random.Range(0, linShiJiHe.Count - 1);
//检测是否重复,保险起见
if (!b.Contains(linShiJiHe[index]))
{
//若b中还没有此元素,添加到b中
b.Add(linShiJiHe[index]);
//成功添加后,将此元素从a中移除,避免重复取值
linShiJiHe.Remove(linShiJiHe[index]);
}
}
如上。然后是在点击下一回合的按钮中循环cardlist,找到里面bool被修改为true的卡,然后打乱
if ( b.Count < 2)
{
for (int i = 1; i <= b.Count; i++)
{
Card card = b[i-1];
string cardFront = "";
if (card.CardName == "多重打击")
{
cardFront = 1 + "";
}
if (card.CardName == "攻击")
{
cardFront = 2 + "";
}
if (card.CardName == "斩击")
{
cardFront = 3 + "";
}
if (card.CardName == "火球术")
{
cardFront = 5 + "";
}
if (card.CardName == "治疗药水")
{
cardFront = 4 + "";
}
if (card.CardName == "神圣治愈")
{
cardFront = 6 + "";
}
if (card.CardName == "毒液")
{
cardFront = 7 + "";
}
if (card.CardName == "祝福")
{
cardFront = 8 + "";
}
GameObject go = (GameObject)Instantiate(Resources.Load("Card/Card" + cardFront), MianTrasfrom.position, MianTrasfrom.rotation);
//go.transform.parent = MianTrasfrom;//设置实例化对象的父级
go.transform.GetChild(0).GetComponent<Text>().text = card.CardType;
go.transform.GetChild(3).GetComponent<Text>().text = card.CardName;
go.transform.GetChild(4).GetComponent<Text>().text = card.CardIntroduction;
go.transform.GetChild(5).GetComponent<Text>().text = card.CardDemage + "";
go.transform.GetChild(6).GetComponent<Text>().text = card.Id + "";
go.transform.SetParent(MianTrasfrom, false);
go.transform.Translate(new Vector3(MianTrasfrom.position.x * Time.deltaTime, 0, 0));
yield return new WaitForSeconds(0.3f);
ButtonToNextRound.isNextRound = false;
//找到cardId对应的卡的索引
int index = CardDesktop.cardList.FindIndex(c=>c.Id ==card.Id);//打出去后将牌重新设置为没打出来的
//Debug.Log("bid = " + card.Id + "-----" + index);
CardDesktop.cardList[index].isActive = false;
}
}
if (b.Count >= 2)
{
for (int i = 0;i <3;i++)
{
Card card = b[i];
string thisCardId = "";
if (card.CardName == "多重打击")
{
thisCardId = 1 + "";
}
if (card.CardName == "攻击")
{
thisCardId = 2 + "";
}
if (card.CardName == "斩击")
{
thisCardId = 3 + "";
}
if (card.CardName == "火球术")
{
thisCardId = 5 + "";
}
if (card.CardName == "治疗药水")
{
thisCardId = 4 + "";
}
if (card.CardName == "神圣治愈")
{
thisCardId = 6 + "";
}
if (card.CardName == "毒液")
{
thisCardId = 7 + "";
}
if (card.CardName == "祝福")
{
thisCardId = 8 + "";
}
GameObject go = (GameObject)Instantiate(Resources.Load("Card/Card" + thisCardId), MianTrasfrom.position, MianTrasfrom.rotation);
//go.transform.parent = MianTrasfrom;//设置实例化对象的父级
go.transform.GetChild(0).GetComponent<Text>().text = card.CardType;
go.transform.GetChild(3).GetComponent<Text>().text = card.CardName;
go.transform.GetChild(4).GetComponent<Text>().text = card.CardIntroduction;
go.transform.GetChild(5).GetComponent<Text>().text = card.CardDemage + "";
go.transform.GetChild(6).GetComponent<Text>().text = card.Id + "";
go.transform.SetParent(MianTrasfrom, false);
go.transform.Translate(new Vector3(MianTrasfrom.position.x * Time.deltaTime, 0, 0));
yield return new WaitForSeconds(0.3f);
ButtonToNextRound.isNextRound = false;
//找到cardId对应的卡的索引
int index = CardDesktop.cardList.FindIndex(c => c.Id == card.Id);//打出去后将牌重新设置为没打出来的
CardDesktop.cardList[index].isActive = false;
}
}
然后因为打出的卡可能只有一张,两张,所以不能统一按照每回合发三张的for循环去写,只能添加多一个判断,如果打出的卡不超过2张,则直接把这两张打出去,如果超过,再用for循环
注意,在把卡抽出显示的同时,要用前面一样的思路,获得这个卡在cardList里的索引,找到他在cardList里的位置,然后把bool修改回false,这样就能实现循环了~
总结, 这个思路卡了快一个月,中间因为一些原因太着急,没时间,到今天才实现,不过,实现出来的感觉是真的爽。最关键是完全靠自己想出来的(不包括打乱卡的逻辑)。
我个人建议萌新(像我一样的),最好就是在有一定编程基础或者逻辑的前提下再尝试敲逻辑比较复杂的代码,会省去很多不必要浪费的时间~
接下来的任务:
把2号3号卡的功能实现
添加战斗结束的判定和界面
把战斗的界面统一到所有需要战斗的事件里
添加除战斗界面的其他事件界面