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)_地主牌显示和出牌逻辑(不定期更新中~~~)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. (转)火溶CEO王伟峰: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. python基础之七种运算符

    废话不多说,上节说的是数据类型,本篇讲讲数据运算. 在算式"1+2"中,"1"和"2"被称为操作数,"+"被称为运算符 ...

  2. vue+axios 前端实现登录拦截(路由拦截、http拦截)

    一.路由拦截 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录 ...

  3. 一、js的数据类型

    一.数据类型 ECMAScript中有5种简单数据类型:Undefined.Null.Boolean.Number和String.还有一种复杂数据类型--Object.ECMAScript不支持任何创 ...

  4. 基于Apache axis2开发Java Web服务

    1.安装配置axis2环境 1)下载axis2-1.4.1-war(发布webservice)和axis2-1.4.1-bin.zip(webservice调用使用的各种包) 下载好后把axis2-1 ...

  5. 基于C#的BarCode 39实现

    一.39条码简介 39码是1974年发展出来的条码系统,是一种可供使用者双向扫瞄的分散式条码,也就是说相临两资料码之间,必须包含一个不具任何意义的空白(或细白,其逻辑值为0),且其具有支援文字的能力, ...

  6. 使用wsimport和JAX-WS调用Web Service接口

    本文简单举例说明如何使用wsimport工具和JAX-WS API调用Web Service接口.此方法的优点:使用JDK自带的工具和API接口,无需依赖第三方库. JDK版本:1.8.0_141开发 ...

  7. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

  8. web前端面试官挖的那些坑(js)

    题目1: function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () ...

  9. Java web JavaScript DOM 编程

     JavaScript DOM 编程 (1).DOM概述及分类 (2).DOM结构模型:XML DOM 和 HTML DOM 关系? (3).结点,结点树,结点属性与方法? 1.DOM是什么? d ...

  10. 浅谈Java接口

    接口(英文:Interface)是Java中非常重要的内容,初学的时候可能感受不深,但是在做项目的时候,对面向接口编程的运用就变得尤为重要,不过这是后话了.现在先讨论假如是刚刚接触接口这个概念,该怎么 ...