Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)

时间:2022-09-21 17:50:53

Hi,之前有同学说要我把源码发出来,那我就把半成品源码的链接放在每篇文件的最后,有兴趣的话可以查阅参考,有问题可以跟我私信,也可以关注我的个人公众号,互相交流嘛。当然,代码也是在不断的持续改进中~

上期我们实现了叫地主功能,不过遗留了一个小功能:叫地主完成以后,要显示地主的3张牌,这期首先弥补这块的功能;

接着我们要进入开发出牌逻辑的开发阶段,好了,废话不多说,继续我们斗地主开发之旅~

地主牌的显示

我们在玩家界面的顶部中间位置,放置一个新的GameObject,命名为BidCards,用来记录3张地主牌的显示位置。

所以我们重构了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 - ).Take() //如果是抢地主牌,取最后3张
: cardNames.Take(cardNames.Length - ); //如果首次发牌 //计算每张地主牌的位置
int cardIndex = ;
var width = (bidCards.GetComponent<RectTransform>().sizeDelta.x - ) / ;
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( / 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[].gameObject.SetActive(false); //发普通牌
if (!ifForBid)
{
//显示玩家手牌
ShowPlayerSelfCards();
StartBiding();
}
//发地主牌
else
{
if (Players[bankerIndex] is PlayerSelf)
{
//显示玩家手牌
ShowPlayerSelfCards();
}
StartFollowing();
}
}

好的,我们地主牌显示已经没有问题了,接下来,我们要实现出牌回合逻辑

出牌回合功能实现

出牌回合其实跟叫地主回合类似,也是可以抽象出3种方法:进入出牌阶段、出牌、不出(比较进入叫地主阶段、叫地主、不叫地主);

因此,我们参照叫地主的逻辑,再实现出牌逻辑:

调整Player基类

添加开始出牌ToFollowing、出牌ForFollow、不出NotFollow:

  • 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 = ;
for (int i = ; 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();
}

调整PlayerSelf类

实现ToFollowing:

调用基类的ToFollowing,并显示出牌按钮以供玩家选择

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

调整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(, cardInfos.Count);
cardInfos[rd1].isSelected = true; ForFollow();
}
if (Input.GetKeyDown(KeyCode.W)) //不出
{
NotFollow();
}
}
}
}

调整CardManager

实现卡牌管理对玩家出牌的控制:

  • 发完地主牌以后,开始出牌阶段,由地主先出牌;
  • 玩家选择出牌后,将上轮玩家的出牌堆清空,并将选择的牌添加到自己的出牌堆,轮转到下个玩家;
  • 玩家选择不出牌,将上轮玩家的出牌堆清空,轮转到下个玩家;
    /// <summary>
/// 开始出牌阶段
/// </summary>
private void StartFollowing()
{
cardManagerState = CardManagerStates.Playing;
//地主先出牌
Players[bankerIndex].ToFollowing();
}
/// <summary>
/// 玩家出牌
/// </summary>
public void ForFollow()
{
SetFollowButtonActive(false); //上轮玩家出牌清空
Players[(termCurrentIndex + Players.Length - ) % ].DropAllSmallCards();
if (Players[termCurrentIndex] is PlayerSelf)
ShowPlayerSelfCards(); SetNextPlayer();
Players[termCurrentIndex].ToFollowing();
}
/// <summary>
/// 玩家不出
/// </summary>
public void NotFollow()
{
SetFollowButtonActive(false); //上轮玩家出牌清空
Players[(termCurrentIndex + Players.Length - ) % ].DropAllSmallCards(); SetNextPlayer();
Players[termCurrentIndex].ToFollowing();
}

代码整理

现在我们的代码具有一定的规模了,为了方便更好的管理,把现有的代码重新整理一下,并进行功能分类,比如:

Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)    Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)

总结

嗯,今天到此为止,我们再来测试验证下,当然,目前只是实现了出牌的功能,没有对牌力进行校验和出牌的控制,对手玩家随机模拟出牌,尚未加入AI。我们以后逐步去实现~来看看这期的效果吧~

Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)

资源

项目源码

Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)的更多相关文章

  1. Unity3D手机斗地主游戏开发实战(04)&lowbar;出牌判断大小(已完结)

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  2. Unity3D手机斗地主游戏开发实战(04)&lowbar;出牌判断大小

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  3. Unity3D手机斗地主游戏开发实战(01)&lowbar;发牌功能实现

    园子荒废多年,闲来无事,用Unity3D来尝试做一个简单的小游戏,一方面是对最近研究的Unity3D有点总结,一方面跟广大的园友相互学习和提高.话不多说,进入正题~ 一.创建项目 1.创建Unity2 ...

  4. Unity3D手机斗地主游戏开发实战(02)&lowbar;叫地主功能实现&lpar;不定期更新中~~~&rpar;

    目录 Unity3D手机斗地主游戏开发实战(01)_发牌功能实现 Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现 一.大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和 ...

  5. Unity3D手机斗地主游戏开发实战(02)&lowbar;叫地主功能实现

    大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和动画,并展示当前的手牌.这期我们继续实现接下来的功能--叫地主. 1.首先这两天,学习了DOTween,这是一个强大的Unity动画 ...

  6. 【转】 &lbrack;Unity3D&rsqb;手机3D游戏开发:场景切换与数据存储(PlayerPrefs 类的介绍与使用)

    http://blog.csdn.net/pleasecallmewhy/article/details/8543181 在Unity中的数据存储和iOS中字典的存储基本相同,是通过关键字实现数据存储 ...

  7. (转)火溶CEO王伟峰&colon;Unity3D手机网游开发

    今天看到这篇文章,感觉很不错,尤其是那句“Unity3D的坑我觉得最严重的坑就是没有懂3D的程序员,把Unity当成Office用”. 转自http://blog.csdn.net/wwwang891 ...

  8. 手机3D游戏开发:自定义Joystick的相关设置和脚本源码

    Joystick在手游开发中非常常见,也就是在手机屏幕上的虚拟操纵杆,但是Unity3D自带的Joystick贴图比较原始,所以经常有使用自定义贴图的需求. 下面就来演示一下如何实现自定义JoySti ...

  9. cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发

     cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发 的产生 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622     ...

随机推荐

  1. 即时通信系统中如何实现:聊天消息加密,让通信更安全? 【低调赠送:QQ高仿版GG 4&period;5 最新源码】

    加密重要的通信消息,是一个常见的需求.在一些*部门的即时通信软件中(如税务系统),对聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据.我在最新的GG 4.5中,增加了对聊天消息 ...

  2. Netbeans 中的编译器相关配置

    gcc-core:C 编译器 gcc-g++:C++ 编译器 gdb:GNU 调试器 make:"make" 实用程序的 GNU 版本

  3. &lbrack;转&rsqb;AndroidManifest&period;xml文件详解

    转自:http://www.cnblogs.com/greatverve/archive/2012/05/08/AndroidManifest-xml.html AndroidManifest.xml ...

  4. Jquery 学习一

    一.jQuery概述 1.Javascript代码库 在早期的项目开发中都是使用Javascript原生代码,一行一行编写.但是Javascript自身存在3个弊端: ① 复杂的DOM操作 ② 不一致 ...

  5. ubuntu 14&period;04 64位 下 编译安装MySQL 5&period;7&period;11

    步骤一: 先去mysql的官方网站 去down 编译源码包 mysql 网址:www.mysql.com downloads  (MySQL Community Server) 下载版本选择  sou ...

  6. LeetCode之&OpenCurlyDoubleQuote;链表”:Sort List

    题目链接 题目要求: Sort a linked list in O(n log n) time using constant space complexity. 满足O(n log n)时间复杂度的 ...

  7. python nose测试框架全面介绍十二 ----用例执行顺序打乱

    在实际执行自动化测试时,发现我们的用例在使用同一个资源的操作时,用例的执行顺序对测试结果有影响,在手工测试时是完全没法覆盖的. 但每一次都是按用例名字来执行,怎么打乱来执行的. 在网上看到一个有意思的 ...

  8. Entity Framework 6&period;x - 创建模型来自于现有数据库

    Creating a Model from an Existing Database 一.创建数据库 Chapter2 USE master GO CREATE DATABASE Chapter2 G ...

  9. 样条之埃尔米特(Hermite)

    埃尔米特(Charles Hermite,1822—1901) 法国数学家.巴黎综合工科学校毕业.曾任法兰西学院.巴黎高等师范学校.巴黎大学教授.法兰西科学院院士.在函数论.高等代数.微分方程等方面都 ...

  10. 【Android】16&period;3 带Intent过滤器的Services

    分类:C#.Android.VS2015: 创建日期:2016-03-01 一.简介 这一节演示带Intent过滤器的Services的基本用法. 1.配置Intent Filter 不论是本地解决方 ...