斗地主——牌型动画
框选手牌功能
参考上面链接,我这里就补充一点,上面链接里的博主只做了功能实现,并未适配分辨率。当在你使用了UGUI CanvasScale——>ScaleWithScreenSize——>MatchWidthOrHeight 这种模式进行适配时,
RectTransformUtility.WorldToScreenPoint();
Event.current.mousePosition;
不同分辨率下就会存在误差,理解深的可以自己将转出的屏幕坐标按照Canvas和Screen大小进行适配。
我这里偷工减料了直接将 “牌” 和 “鼠标” 的屏幕坐标直接使用如下接口进行转换
RectTransformUtility.ScreenPointToLocalPointInRectangle();
这里框选代码不贴了,参考上面提供的博文进行更改就行了,实在不会可以私信我。
牌相关动画
我这里自己做的小游戏,主要是完善了下部分功能。主要分为牌型动画、牌型组合、智能提示出牌。
接下来这篇文章主要粘贴牌型动画功能代码。变量要自己去声明,需要有点lua基础,这里主要提供类似于腾讯欢乐斗地主牌型动画,代码还需要去优化。
-- 明牌动画
local LUCKYNUMBER_SHOW = 1; -- 明牌显示类型
local LUCKYNUMBER_UPDATE = 2; -- 明牌出牌后更新
local LUCKYNUMBER_ADD_COMCARD = 3; -- 明牌增加公共牌(暂时没想到好的方案实现???????)
-- 手牌动画
local CardAnimType = {
E_DeclCard = 1, -- 发牌手牌动画
E_AddCommonCard = 2, -- 增加公共牌动画
E_PlayCard = 3, -- 出牌后更新手牌动画
}
local horizontalSpace = 50;
--[[
updateHandCardsAnim ——更新自己手牌变换动画
updatePlayCardsAnim ——出牌的牌型动画
updateLuckyNumberCardsAnim ——玩家明牌动画
--]]
function LandlordManager:updateHandCardsAnim(animType, incOrDecCards, callback)
local operCb = function()
if callback then
callback();
end
end
if self.animCo then
coli.cs_coroutine.stop(self.animCo);
self.animCo = nil;
end
if animType == CardAnimType.E_DeclCard then --发牌动画
local cards = {};
local timer = 0.12;
self.animCo = coli.cs_coroutine.start(function()
for i,v in ipairs(self.handCards) do
local len = #cards + 1;
v.card.transform.localScale = Unity.Vector3(1, 1, 1);
v.card.transform.localPosition = Unity.Vector3(len*horizontalSpace*0.5, 0, 0);
v.card.transform:SetSiblingIndex(i-1);
for k,base in ipairs(cards) do
local offsetX = base.card.transform.localPosition.x - horizontalSpace*0.5;
base.card.transform:DOLocalMoveX(offsetX, timer):SetEase(Tweening.Ease.Linear);
end
table.insert(cards, v);
coroutine.yield(Unity.WaitForSeconds(timer));
end
operCb();
end);
elseif animType == CardAnimType.E_AddCommonCard then --增加公共牌动画
local timer = 0.15;
local cards = incOrDecCards;
cards = LandlordTools:SortCards(cards);
local isCommonCards = function(raw)
for i,v in ipairs(cards) do
if v == raw then
return true;
end
end
return false;
end
local halfLenth = #self.handCards*0.5;
for i,v in ipairs(self.handCards) do
v.card.transform.localScale = Unity.Vector3(1, 1, 1);
v.card.transform:SetSiblingIndex(i-1);
if isCommonCards(v.baseInfo.rawVal) then
v.card.transform.localPosition = Unity.Vector3((i - halfLenth)*horizontalSpace, 80, 0);
v.card.transform:DOLocalMoveY(0, 0.65):SetEase(Tweening.Ease.Linear);
else
v.card.transform:DOLocalMoveX((i - halfLenth)*horizontalSpace, timer):SetEase(Tweening.Ease.Linear);
end
end
operCb();
elseif animType == CardAnimType.E_PlayCard then --出牌后更新手牌动画
local timer = 0.15;
local halfLenth = #self.handCards*0.5;
for i,v in ipairs(self.handCards) do
v.card.transform:SetSiblingIndex(i-1);
v.card.transform:DOLocalMoveX((i - halfLenth)*horizontalSpace, timer):SetEase(Tweening.Ease.Linear);
end
operCb();
end
end
function LandlordManager:updatePlayCardsAnim(chair, preChair, cards, callback)
local isPlayCard = false;
local isPlayFx = false;
local _completeAll = function()
log.info("_completeAll:", isPlayCard, isPlayFx);
if isPlayCard and isPlayFx then
if callback then
callback();
end
end
end
-- 打出去的牌动画,考虑到存在出牌特效展示,需要在出牌动画和特效播放后才能触发回调。
-- 我这里用的蠢办法,你们可以自行优化
local _playCardCompleteCb = function()
isPlayCard = true;
_completeAll();
end
local _playFxCompleteCb = function()
isPlayFx = true;
_completeAll();
end
if self.playCardCo then
coli.cs_coroutine.stop(self.playCardCo);
self.playCardCo = nil;
end
local isMe = chair:isMe();
local timer = 0.2;
local cycleTimer = 0.05;
local len = #cards;
local chairId = chair:getChairId();
local uiTranf = CardDisplayPos[chairId].posTransf;
local type = LandlordTools:GetCardType(self:getRawCards(cards));
-- 根据类型, 播放出牌特效,没有的话可以注释掉
self:playfx(chair, preChair, type, _playFxCompleteCb);
-- 出牌动画
-- 我这里只做顺子和非顺子两种动画
if type == CardType.CT_SINGLE_LINE then
if isMe then
local scale = Unity.Vector3(0.7, 0.7, 0.7);
local punchScale = Unity.Vector3(-0.1, -0.1, -0.1);
self.playCardCo = coli.cs_coroutine.start(function()
for i,v in ipairs(cards) do
v.card.transform:SetParent(uiTranf);
v.card.transform.localPosition = Unity.Vector3((i - len * 0.5)*horizontalSpace*0.7, 0, 0);
v.card.transform.localScale = scale;
v.isHandCard = false;
v.card:GetComponent(typeof(Runtime.LuaCardCell)):UpdateContent(v);
v.card.transform:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
coroutine.yield(Unity.WaitForSeconds(cycleTimer));
end
_playCardCompleteCb();
end);
else
local maxCount = 12;
local offsetY = -50;
local rate = 0.65;
local scale = Unity.Vector3(0.6, 0.6, 0.6);
local punchScale = Unity.Vector3(-0.08, -0.08, -0.08);
if chair:isLeft() then
self.playCardCo = coli.cs_coroutine.start(function()
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
v.card.transform:SetSiblingIndex(i-1);
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3((i-1)*horizontalSpace*rate, 0, 0);
else
v.card.transform.localPosition = Unity.Vector3((i-maxCount-1)*horizontalSpace*rate, offsetY, 0);
end
v.card.transform:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
coroutine.yield(Unity.WaitForSeconds(cycleTimer));
end
_playCardCompleteCb();
end);
else
self.playCardCo = coli.cs_coroutine.start(function()
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(-(i-1)*horizontalSpace*rate, 0, 0);
v.card.transform:SetSiblingIndex(len-i);
else
v.card.transform.localPosition = Unity.Vector3(-(i-maxCount-1)*horizontalSpace*rate, offsetY, 0);
v.card.transform:SetSiblingIndex(len+(maxCount-i));
end
v.card.transform:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
coroutine.yield(Unity.WaitForSeconds(cycleTimer));
end
_playCardCompleteCb();
end);
end
end
else
-- update card anim
if isMe then
local scale = Unity.Vector3(0.7, 0.7, 0.7);
for i,v in ipairs(cards) do
v.card.transform:SetParent(uiTranf);
v.card.transform.localPosition = Unity.Vector3((i - len * 0.5)*horizontalSpace*0.7, 0, 0);
v.card.transform.localScale = scale;
v.isHandCard = false;
v.card:GetComponent(typeof(Runtime.LuaCardCell)):UpdateContent(v);
end
uiTranf:DOPunchScale(Unity.Vector3(-0.1, -0.1, -0.1), timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
else
local maxCount = 12;
local offsetY = -50;
local rate = 0.65;
local scale = Unity.Vector3(0.6, 0.6, 0.6);
local punchScale = Unity.Vector3(-0.08, -0.08, -0.08);
if chair:isLeft() then
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
v.card.transform:SetSiblingIndex(i-1);
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3((i-1)*horizontalSpace*rate, 0, 0);
else
v.card.transform.localPosition = Unity.Vector3((i-maxCount-1)*horizontalSpace*rate, offsetY, 0);
end
end
uiTranf:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
else
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(-(i-1)*horizontalSpace*rate, 0, 0);
v.card.transform:SetSiblingIndex(len-i);
else
v.card.transform.localPosition = Unity.Vector3(-(i-maxCount-1)*horizontalSpace*rate, offsetY, 0);
v.card.transform:SetSiblingIndex(len+(maxCount-i));
end
end
uiTranf:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
end
end
_playCardCompleteCb();
end
end
function LandlordManager:updateLuckyNumberCardsAnim(chair, luckyType)
local cards = self.otherHandCards[chair:getChairId()];
local len = #cards;
local rate = 0.5;
local maxCount = 13;
local offsetY = -40;
local scale = Unity.Vector3(0.5, 0.5, 0.5);
if luckyType == LUCKYNUMBER_SHOW then -- 其他玩家点击明牌展示动画
local punchScale = Unity.Vector3(-0.05, -0.05, -0.05);
local timer = 0.1;
local cycleTimer = 0.02;
if chair:isLeft() then
if self.leftLuckyAnimCo then
coli.cs_coroutine.stop(self.leftLuckyAnimCo);
self.leftLuckyAnimCo = nil;
end
self.leftLuckyAnimCo = coli.cs_coroutine.start(function()
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
v.card.transform:SetSiblingIndex(i-1);
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(i*horizontalSpace*rate, 0, 0);
else
v.card.transform.localPosition = Unity.Vector3((i-maxCount)*horizontalSpace*rate, offsetY, 0);
end
v.card.transform:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
coroutine.yield(Unity.WaitForSeconds(cycleTimer));
end
end);
else
if self.rightLuckyAnimCo then
coli.cs_coroutine.stop(self.rightLuckyAnimCo);
self.rightLuckyAnimCo = nil;
end
self.rightLuckyAnimCo = coli.cs_coroutine.start(function()
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(-i*horizontalSpace*rate, 0, 0);
v.card.transform:SetSiblingIndex(len-i);
else
v.card.transform.localPosition = Unity.Vector3(-(i-maxCount)*horizontalSpace*rate, offsetY, 0);
v.card.transform:SetSiblingIndex(len+(maxCount-i));
end
v.card.transform:DOPunchScale(punchScale, timer, 12, 0.1):SetEase(Tweening.Ease.InQuart);
coroutine.yield(Unity.WaitForSeconds(cycleTimer));
end
end);
end
elseif luckyType == LUCKYNUMBER_UPDATE then --其他玩家出牌后,更新明牌
if chair:isLeft() then
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
v.card.transform:SetSiblingIndex(i-1);
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(i*horizontalSpace*rate, 0, 0);
else
v.card.transform.localPosition = Unity.Vector3((i-maxCount)*horizontalSpace*rate, offsetY, 0);
end
end
else
for i,v in ipairs(cards) do
v.card.transform.localScale = scale;
if i <= maxCount then
v.card.transform.localPosition = Unity.Vector3(-i*horizontalSpace*rate, 0, 0);
v.card.transform:SetSiblingIndex(len-i);
else
v.card.transform.localPosition = Unity.Vector3(-(i-maxCount)*horizontalSpace*rate, offsetY, 0);
v.card.transform:SetSiblingIndex(len+(maxCount-i));
end
end
end
end
end
结束语
有什么问题欢迎及时指正,万分感谢。有什么想法也可以提出来,咋们共同学习。
异步多任务完成后回调,如何设计?像我上面那样用两个bool值处理肯定是最low的。