Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)
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();
}
代码整理
现在我们的代码具有一定的规模了,为了方便更好的管理,把现有的代码重新整理一下,并进行功能分类,比如:

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

资源
Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)的更多相关文章
- Unity3D手机斗地主游戏开发实战(04)_出牌判断大小(已完结)
之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...
- Unity3D手机斗地主游戏开发实战(04)_出牌判断大小
之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...
- Unity3D手机斗地主游戏开发实战(01)_发牌功能实现
园子荒废多年,闲来无事,用Unity3D来尝试做一个简单的小游戏,一方面是对最近研究的Unity3D有点总结,一方面跟广大的园友相互学习和提高.话不多说,进入正题~ 一.创建项目 1.创建Unity2 ...
- Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现(不定期更新中~~~)
目录 Unity3D手机斗地主游戏开发实战(01)_发牌功能实现 Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现 一.大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和 ...
- Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现
大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和动画,并展示当前的手牌.这期我们继续实现接下来的功能--叫地主. 1.首先这两天,学习了DOTween,这是一个强大的Unity动画 ...
- 【转】 [Unity3D]手机3D游戏开发:场景切换与数据存储(PlayerPrefs 类的介绍与使用)
http://blog.csdn.net/pleasecallmewhy/article/details/8543181 在Unity中的数据存储和iOS中字典的存储基本相同,是通过关键字实现数据存储 ...
- (转)火溶CEO王伟峰:Unity3D手机网游开发
今天看到这篇文章,感觉很不错,尤其是那句“Unity3D的坑我觉得最严重的坑就是没有懂3D的程序员,把Unity当成Office用”. 转自http://blog.csdn.net/wwwang891 ...
- 手机3D游戏开发:自定义Joystick的相关设置和脚本源码
Joystick在手游开发中非常常见,也就是在手机屏幕上的虚拟操纵杆,但是Unity3D自带的Joystick贴图比较原始,所以经常有使用自定义贴图的需求. 下面就来演示一下如何实现自定义JoySti ...
- cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发
cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发 的产生 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622 ...
随机推荐
- oracle pl/sql 简介
一.pl/sql 是什么pl/sql(procedural language/sql)是oracle在标准的sql语言上的扩展.pl/sql不仅允许嵌入sql语言,还可以定义变量和常量,允许使用条件语 ...
- Highway Networks Pytorch
导读 本文讨论了深层神经网络训练困难的原因以及如何使用Highway Networks去解决深层神经网络训练的困难,并且在pytorch上实现了Highway Networks. 一 .Highway ...
- TCO之旅
TCO之旅 时间限制: 1 Sec 内存限制: 128 MB提交: 77 解决: 24[提交][状态][讨论版] 题目描述 我们的小强终于实现了他TCO的梦想了,爬进了TCO的全球总决赛,开始了他 ...
- Tomcat 设置自启动时遇到的错误问题与解决方案
首先,今天在做tomcat开机自启动时,原本很简单的一个问题,但却浪费了很长时间: 首先系统环境采用的是Window10,设置Tomcat自启动过程当中需要注意的是:JDK的版本和Tomcat的位数必 ...
- Android UI 笔记
EditText中添加小图标 <TextView android:layout_width="wrap_content" android:layout_height=&quo ...
- Python自学笔记-字符串编码(来自廖雪峰的官网Python3)
感觉廖雪峰的官网http://www.liaoxuefeng.com/里面的教程不错,所以学习一下,把需要复习的摘抄一下. 以下内容主要为了自己复习用,详细内容请登录廖雪峰的官网查看. 1.理解变 ...
- 从零开始配置TypeScript + React + React-Router + Redux + Webpack开发环境
转载请注明出处! 说在前面的话: 1.为什么不使用现成的脚手架?脚手架配置的东西太多太重了,一股脑全塞给你,我只想先用一些我能懂的库和插件,然后慢慢的添加其他的.而且自己从零开始配置也能学到更多的东西 ...
- Java面向对象 正则表达式
Java面向对象 正则表达式 知识概要: (1)正则表达式的特点 (2)正则表达的匹配 (3)正则表达式的切割,替换,获取 (4)正则表达式的练习 正则表达式:符合 ...
- asp.net中使用Global.asax文件中添加应用出错代码,写入系统日志文件或数据库
void Application_Error(object sender, EventArgs e) { // 在出现未处理的错误时运行的代码 Exception objErr = Server.Ge ...
- KMP算法的细节问题
preface: 想必,很多人都知道D.E.Knuth与V.R.Pratt和J.H.Morris同时提出所谓的狂拽酷炫屌炸天的KMP算法,在对字符串的匹配(或是字符串的查找)方面表现出比较好的效率,该 ...