【Daily Games——开发篇】:一个帅气的副本效果之翻牌兑换

不知不觉已经干了这么久了,看看我完成的界面吧。

一个帅气的翻牌匹配小游戏不是吗,涉及的内容是发牌,位置点确定,翻转匹配

翻转匹配是服务器的返回数据,但是本地同样可以抢先配对。

发牌代码如下:

服务器给的是点的位置,由于最多7*4列,服务器给的数据是3,7,11这样的数字

首先计算牌的位置最为重要,代码如下:

--子长度,子间距,子个数
function GetPos(width_item,width_cell,count)
	local posx_table = {}
	local x_len = width_item + width_cell
	local num = math.floor(count/2)
	local ys = count%2
	if ys == 1 then
		for i=0,num do
			posx_table[num+1+i] = x_len*i
			posx_table[num+1-i] = 0-x_len*i
		end
	else
		for i=0,num-1 do
			posx_table[num+1+i] = 0-x_len*i - width_cell/2 - width_item/2
			posx_table[num-i] = x_len*i + width_cell/2 + width_item/2
		end
	end
	return posx_table
end
--子长宽,子间距xy,规格,横着数的位置
function InitPosTable(i_w,i_h,c_x,c_y,l_x,l_y)
	local table_x = GetPos(i_w,c_x,l_y)
	local table_y = GetPos(i_h,c_y,l_x)
	for i=1,l_x*l_y do
		local x = i%l_y
		if x == 0 then
			x = l_y
		end
		local y = math.ceil(i/l_y)
		local temp = {}
		temp.posx = table_x[x]
		temp.posy = table_y[y]
		postable[i] = temp
	end
end

只需要指定牌的大小和间距就可以了,原理计算按照原点开始的对称点计算。

每次翻牌判定要将其他牌设为不可按,当服务器返回匹配成功失败数据,raycast再设为true

整体代码如下:

local GameObject=CS.UnityEngine.GameObject
local Vector3=CS.UnityEngine.Vector3
local UIMgr = CS.UIMgr
local UIDataMgr = CS.UIDataMgr
--表单信息 位置点 Onshow获取一次
local postable = {}
--cardtable_tran 生成卡牌transform
local cardtable_tran = {}
--cardtable_btnscript 卡牌button脚本,修改enable
local cardtable_btnscript = {}
local cardlist = {} --服务器获取的卡牌表单
--当前关卡 card_num:翻正面的牌数 oldcard:第一次点击的牌 newcard:第二次点击的牌
local round_now = 0
local card_num = 0
local oldcard
local newcard
--时分秒用于计时器
local timer_hour = 0
local timer_min = 0
local timer_sec = 0
local timer_total = 0
local card_width = 100
local card_height = 100
--初始化获取组件,文本组件 头像img组建 crosspanel的文本框
local btntable = {}
local txttable = {}
local head_img_table = {}
local crosstable = {}
local cell = 25
--右侧世界最佳data 玩家最佳data 人物头像img
local worldbestdata = {}
local playerdata = {}
local bestplayerheadimg
--发牌点
local startPos
--发牌个数 第几关文本 通关奖励money exp
local num_give = 1
local roundtext
local earn_money
local earn_exp
--翻牌相关特效
local Quaternion = CS.UnityEngine.Quaternion
local EffectMgr = CS.EffectMgr.Instance
local Object=CS.UnityEngine.Object
local eff_table=
{
	[1]="ef_ui_fanpai_xuanzhong",
	[2]="ef_ui_fanpai_chenggong",
	[3]="ef_ui_fanpai_shibai",
	[4]="ef_ui_fanpai_fapai",
	[5]="ef_ui_fanpai_jiesuan",
}
--子长度,子间距,子个数
function GetPos(width_item,width_cell,count)
	local posx_table = {}
	local x_len = width_item + width_cell
	local num = math.floor(count/2)
	local ys = count%2
	if ys == 1 then
		for i=0,num do
			posx_table[num+1+i] = x_len*i
			posx_table[num+1-i] = 0-x_len*i
		end
	else
		for i=0,num-1 do
			posx_table[num+1+i] = 0-x_len*i - width_cell/2 - width_item/2
			posx_table[num-i] = x_len*i + width_cell/2 + width_item/2
		end
	end
	return posx_table
end
--子长宽,子间距xy,规格,横着数的位置
function InitPosTable(i_w,i_h,c_x,c_y,l_x,l_y)
	local table_x = GetPos(i_w,c_x,l_y)
	local table_y = GetPos(i_h,c_y,l_x)
	for i=1,l_x*l_y do
		local x = i%l_y
		if x == 0 then
			x = l_y
		end
		local y = math.ceil(i/l_y)
		local temp = {}
		temp.posx = table_x[x]
		temp.posy = table_y[y]
		postable[i] = temp
	end
end
--输入间距即可
function ResetPanel(cell_x,cell_y,l_x,l_y)
	l_content.transform:EX_ClearChild(1)
	local w_i = l_card_back:GetComponent("RectTransform").rect.width
	local h_i = l_card_back:GetComponent("RectTransform").rect.height
	GetPosXY(w_i,h_i,cell_x,cell_x,l_x,l_y)
end

function OnShow(param)
	HandEvent(true)
	InitPosTable(card_width,card_height,cell,cell,4,7)
	InitDataInfo()
	InitPanelInfo()
	l_startText:GetComponent("Text").text =  LanguageMnager.Get(91006)
	l_card_start:SetActive(true)
	l_passPanel:SetActive(false)
	l_next_text:GetComponent("Text").text = LanguageMnager.Get(91000)
end

function OnHide()
	HandEvent(false)
	OnGameEnd()
	l_startText:GetComponent("Text").text =  LanguageMnager.Get(91006)
end

function InitDataInfo()
	local k
	--round_now:当前关卡 round_text:"第x关" roundtext:"x/5"	当前玩家pid
	round_now = PlayerManager.getEventDataX(EID.opencard) + 1
	roundtext = LanguageMnager.Get(91004)
	roundtext = string.format(roundtext,round_now)
	--玩家名字时间头像
	playerdata.name = PlayerManager.PlayerInfo.PlayerName
	playerdata.time = PlayerManager.getEntityPAttr(EntityProp.opencard_function+round_now)
	k,playerdata.headimg = PlayerManager.GetRoleJobNameAndIcon()
	--世界玩家信息(datax:time datay:转职等级 dataz:玩家职业 datas:玩家名字)
	local worlddata = WorldMediator.getWorldAttrs(WorldProp.opencard_function+round_now)
	--我就是最强玩家! 设置名字时间头像
	if worlddata.datas == playerdata.name then
		worldbestdata.name = playerdata.name
		worldbestdata.time = playerdata.time
		bestplayerheadimg = playerdata.headimg
	--如果最佳时间不为0
	elseif not EX_HasNotData(worlddata) and worlddata.datax ~= 0 then
		worldbestdata.name = worlddata.datas
		worldbestdata.time = worlddata.datax
		bestplayerheadimg = PlayerManager.GetRoleJobSprite(worlddata.dataz,worlddata.datay)
	else
		worldbestdata.name = LanguageMnager.Get(91005)
		worldbestdata.time = 0
		bestplayerheadimg = playerdata.headimg
	end
	if not EX_HasNotData(gdOpenCardRewards) then
		--这里要按照等级等策划配完 先默认获取第一个数据
		--到时候这里的1换成当前玩家等级就可以=v=
		earn_money = gdOpenCardRewards[1].money
		earn_exp = gdOpenCardRewards[1].exp
	end
end

function InitPanelInfo()
	if EX_HasNotData(btntable) then
		btntable[1] = l_startBtn:GetComponent("Button")
		btntable[1].onClick:AddListener(OnClickRestart)
		btntable[2] = l_passbtn:GetComponent("Button")
		btntable[2].onClick:AddListener(OnClickNext)
		btntable[3] = l_exitBtn:GetComponent("Button")
		btntable[3].onClick:AddListener(OnClickExit)
	end
	if EX_HasNotData(txttable) then
		txttable[1] = l_roundTitle:GetComponent("Text")
		txttable[2] = l_remainCount:GetComponent("Text")
		txttable[3] = l_best_player_name:GetComponent("Text")
		txttable[4] = l_best_player_time:GetComponent("Text")
		txttable[5] = l_player_name:GetComponent("Text")
		txttable[6] = l_player_time:GetComponent("Text")
		txttable[7] = l_timeNow:GetComponent("Text")
	end
	if EX_HasNotData(crosstable) then
		local c_tran = l_passPanel.transform:Find("UIText")
		crosstable[1] = c_tran:Find("timetext"):GetComponent("Text")
		crosstable[2] = c_tran:Find("moneytext"):GetComponent("Text")
		crosstable[3] = c_tran:Find("exptext"):GetComponent("Text")
	end
	if EX_HasNotData(head_img_table) then
		head_img_table[1] = l_best_player_head:GetComponent("Image")
		head_img_table[2] = l_player_head:GetComponent("Image")
	end
	if not EX_HasNotData(txttable) then
		txttable[1].text = roundtext
		txttable[2].text = (6-round_now).."/5"
	end
	if not EX_HasNotData(worldbestdata) and not EX_HasNotData(playerdata) and not EX_HasNotData(head_img_table) then
		txttable[3].text = worldbestdata.name
		txttable[4].text = FormatTime(worldbestdata.time)
		txttable[5].text = playerdata.name
		txttable[6].text = FormatTime(playerdata.time)
		head_img_table[1].sprite = bestplayerheadimg
		head_img_table[2].sprite = playerdata.headimg
	end
end

--重置游戏也看做游戏开始=.=
function OnGameStart()
	--收到开始游戏的消息(做一重判断,判断界面是否开启[掉线处理])
	if not UIMgr.Instance:GetUIStateEx(UINameEnum.FanpaiPanel) then
		return
	end
	
	--重新获取关卡信息和初始化界面
	InitDataInfo()
	InitPanelInfo()
	--确保关闭
	l_crossimg:SetActive(false)
	l_passPanel:SetActive(false)
	l_card_start:SetActive(false)
	if not EX_HasNotData(postable) and not EX_HasNotData(gdOpenCards) then
		l_startText:GetComponent("Text").text =  LanguageMnager.Get(91007)
		CS.TimeMgr.Instance:AddTimeInterval("RecordTime", CS.TimerStruct(-1, false,RecordTime,1))--游戏开始记时
		for i=1,#postable do
			for j = 1,#cardlist do
				if cardlist[j].index == i then
					local item_tran = GameObject.Instantiate(l_card_back).transform
					item_tran:SetParent(l_content.transform)
					item_tran.localScale = Vector3.one
					item_tran.position = l_startPos.transform.position-Vector3(0,0,0.1*i)
					item_tran.name = tonumber(i)
					local img_index = cardlist[j].cardtype
					local img_name = gdOpenCards[img_index]
					item_tran:Find("Image"):GetComponent("Image").sprite = UIDataMgr.LoadSprite(tostring(img_name))
					local item_btn = item_tran:GetComponent("Button")
					--这里传递的是button脚本 img_index用于判断两张牌是否相同
					item_btn.onClick:AddListener(function() OnClickCard(item_btn) end)
					cardtable_tran[#cardtable_tran+1] = item_tran
					cardtable_btnscript[#cardtable_btnscript+1] = item_tran:GetComponent("Button")
				end
			end
		end
		CS.TimeMgr.Instance:AddTimeInterval("GiveCard", CS.TimerStruct(-1, false,GiveCard,0.1))	--游戏开始发牌
	end
end
--下一关 显示crosspanel 设置参数
function OnGameNext()
	CS.SoundManager.Instance:PlaySound(90054)
	l_crossimg:SetActive(false)
	local timer = 0
	if round_now == 5 then
		l_next_text:GetComponent("Text").text = LanguageMnager.Get(82320)
	end
	l_passPanel:SetActive(true)
	ShowFanPaiEff(l_passPanel,eff_table[5])
	if not EX_HasNotData(crosstable) then
		crosstable[1].text = FormatTime(timer_total)
		crosstable[2].text = earn_money
		crosstable[3].text = earn_exp
	end
	OnGameEnd()
end
--当前游戏被重置。结束/panel关闭时候调用
function OnGameEnd()
	CS.TimeMgr.Instance:RmvTimeInterval("RecordTime")
	CS.TimeMgr.Instance:RmvTimeInterval("GiveCard")
	card_num = 0
	num_give = 1
	cardtable_tran = {}
	cardtable_btnscript = {}
	if Ex_IsNotNil(oldcard) then
		oldcard.transform:EX_DOKill()
	end
	if Ex_IsNotNil(newcard) then
		newcard.transform:EX_DOKill()
	end
	oldcard = nil
	newcard = nil
	timer_hour = 0
	timer_min = 0
	timer_sec = 0
	timer_total = 0
	if not EX_HasNotData(txttable) then
		txttable[7].text = "00.00.00"
	end
	l_content.transform:EX_ClearChild(1)
end

function OnClickStart()
	SendMsgForFanpaiInfo(FuncProp.opencard_start)
end
function OnClickNext()
	if round_now == #gdOpendCardIndexs then
		CS.UIMgr.Instance:PopUIEx(UINameEnum.FanpaiPanel)
		return 
	end
	OnGameEnd()
	SendMsgForFanpaiInfo(FuncProp.opencard_start)
end
function OnClickExit()
	CS.UIMgr.Instance:PopUIEx(UINameEnum.FanpaiPanel)
end

function OnClickRestart()
	OnGameEnd()
	SendMsgForFanpaiInfo(FuncProp.opencard_start)
end

function HandEvent(flag)
	if flag == true then
		LuaEvent.RegEvent(gdGame.EventNameEnum.EVENT_OPEN_CARD,OnMsgFuncCardDataOperatorResponse)
		LuaEvent.RegEvent(gdGame.EventNameEnum.EVENT_FANPAI_LUA,OnMsgFuncDataOperatorResponse)
	else
		LuaEvent.RmvEvent(gdGame.EventNameEnum.EVENT_OPEN_CARD,OnMsgFuncCardDataOperatorResponse)
		LuaEvent.RegEvent(gdGame.EventNameEnum.EVENT_FANPAI_LUA,OnMsgFuncDataOperatorResponse)
	end
end

function SendMsgForFanpaiInfo(funcid,datax,datay,dataz)
	local ret={}
	ret.funcid=funcid
	ret.datax = datax
	ret.datay = datay
	ret.dataz = dataz
	Networks.Push_msg(Network.MsgFuncDataOperatorRequest,ret)
end
--开始游戏服务器信息cardlist获取
function OnMsgFuncDataOperatorResponse(ret)
	if not EX_HasNotData(ret) and not EX_HasNotData(ret.cardlist) then
		cardlist = {}
		cardlist = ret.cardlist
		OnGameStart()
	end
end
--点击牌服务器返回被点击牌信息
function OnMsgFuncCardDataOperatorResponse(ret)
	--两张牌一样,设置为不可动
	if not EX_HasNotData(ret) and Ex_IsNotNil(newcard) and not EX_HasNotData(cardtable_btnscript) and Ex_IsNotNil(newcard) and Ex_IsNotNil(oldcard) then
		if ret.state == 2 then
			CS.SoundManager.Instance:PlaySound(90052)
			--从btn中删除元素,不修改按钮状态
			for i=1,#cardtable_btnscript do
				if newcard == cardtable_btnscript[i] or oldcard == cardtable_btnscript[i] then
					cardtable_btnscript[i].enabled = false
					table.remove(cardtable_btnscript,i)
				end
			end
			for i=1,#cardtable_btnscript do
				cardtable_btnscript[i].enabled = true
			end
			ShowFanPaiEff(newcard.gameObject,eff_table[2])
			ShowFanPaiEff(oldcard.gameObject,eff_table[2])
			RemoveEff(newcard.gameObject,eff_table[1])
			RemoveEff(oldcard.gameObject,eff_table[1])
			newcard = nil
			oldcard = nil
			card_num  = card_num + 2	--配对成功则+2
			if card_num == #cardtable_tran then
				OnGameNext()
				card_num = 0
			end
		--两张牌不一样 翻回去可以点击
		elseif ret.state == 0 then
			--CS.SoundManager.Instance:PlaySound(90053)
			local timer = 0
			ShowFanPaiEff(l_crossimg,eff_table[5])
			RemoveEff(newcard.gameObject,eff_table[1])
			RemoveEff(oldcard.gameObject,eff_table[1])
			ShowFanPaiEff(newcard.gameObject,eff_table[3])
			ShowFanPaiEff(oldcard.gameObject,eff_table[3])
			
			CS.TimeMgr.Instance:AddTimeInterval("ShowFail", CS.TimerStruct(-1, false,function()
				timer = timer + 0.1
				if timer > 0.3 then
					if Ex_IsNotNil(oldcard) then
					    oldcard.transform:EX_DORotate(Vector3(0,0,0),0.3)
					end
					if Ex_IsNotNil(newcard) then
					    newcard.transform:EX_DORotate(Vector3(0,0,0),0.3)
					end
					for i=1,#cardtable_btnscript do
						cardtable_btnscript[i].enabled = true
					end
					oldcard = nil
					newcard = nil
					CS.TimeMgr.Instance:RmvTimeInterval("ShowFail")
				end
			end,0.1))
			
		end
	end
end

--点击牌触发事件
function OnClickCard(card)
	if not Ex_IsNotNil(oldcard) then	--翻第一张牌,设为不可按
		oldcard = card
		ShowFanPaiEff(card.gameObject,eff_table[1])
		oldcard.enabled = false
	elseif not Ex_IsNotNil(newcard) and not EX_HasNotData(cardtable_btnscript) and not (oldcard == card) then --翻第二张牌,设所有牌不可按(OnMsgFuncCardDataOperatorResponse判断完会修改状态)
		newcard = card
		ShowFanPaiEff(card.gameObject,eff_table[1])
		for i=1,#cardtable_btnscript do
			cardtable_btnscript[i].enabled = false
		end
	end
	--告诉服务器翻转这张牌(按太快state本该返回2变成1)
	ShowFanPaiEff(card.gameObject,eff_table[4])
	CS.SoundManager.Instance:PlaySound(90051)
	card.transform:EX_DOScale(1.2,0.1):EX_OnComplete(function()
		card.transform:EX_DOScale(1,0.1)
		card.transform:EX_DORotate(Vector3(0,180,0),0.3):EX_OnComplete(function()
		SendMsgForFanpaiInfo(FuncProp.opencard_open,card.gameObject.name,timer_total)
	end)
	end)

	--[[card.transform:EX_DORotate(Vector3(0,180,0),0.3):EX_OnComplete(function()
		SendMsgForFanpaiInfo(FuncProp.opencard_open,card.gameObject.name,timer_total)
	end)--]]
end
--计时器调用方法,倒计时
function RecordTime()
	if not EX_HasNotData(txttable) then
		txttable[7].text = string.format("%02d.%02d.%02d",timer_hour,timer_min,timer_sec)
	end
	timer_total = timer_total+1
	timer_sec = timer_sec+1
	if timer_sec > 60 then
		timer_min = math.floor(timer_sec/60) + timer_min
		timer_sec = timer_sec % 60
	end
	if timer_min > 60 then
		timer_hour = math.floor(timer_min/60) + timer_hour
		timer_min = timer_min % 60
	end
end
--秒转换00"00"00 91s->00"01"31
function FormatTime(second)
	local min = 0
	local hour = 0
	min = math.floor(second/60)
	second = second % 60
	hour = math.floor(min/60)
	min = min % 60
	local time_text = string.format("%02d.%02d.%02d",hour,min,second)
	return time_text
end
--发牌效果实现主要代码
function GiveCard()
	if not EX_HasNotData(cardtable_tran) and num_give < (#cardtable_tran+1)then
		local cardIndex = tonumber(cardtable_tran[num_give].gameObject.name)
		if cardIndex then
			l_confirm_pos.transform.localPosition = Vector3(postable[cardIndex].posx,postable[cardIndex].posy,-100)
			local endPos = l_confirm_pos.transform.position-Vector3(0,0,num_give*0.1)
			cardtable_tran[num_give]:EX_DOMove(endPos,0.3)
			local num = num_give
			CS.SoundManager.Instance:PlaySound(90055)
			cardtable_tran[num_give]:EX_DOScale(1.2,0.2):EX_OnComplete(function()
				if cardtable_tran[num] ~= nil then
					cardtable_tran[num]:EX_DOScale(1,0.1)
				end
			end)
			num_give = num_give+1
		end
	else
		CS.SoundManager.Instance:PlaySound(90055)
		CS.TimeMgr.Instance:RmvTimeInterval("GiveCard")
		local count = l_content.transform.childCount-1
		for i=0,count do
			local img = l_content.transform:GetChild(i):GetComponent("Image")
			if img ~= nil then
				img.raycastTarget = true
			end
		end
	end
end
--洗牌实现,弃用
--local stuffle_flag = 1
--local stuffle_count = 0
--CS.TimeMgr.Instance:AddTimeInterval("Stuffle", CS.TimerStruct(-1, false,Stuffle,0.6))
--[[function Stuffle()
	if not EX_HasNotData(cardtable_tran) then
		local endPos
		for i=1,#cardtable_tran do
			stuffle_flag = stuffle_flag * -1
			local pos = cardtable_tran[i].position
			endPos = pos+Vector3(stuffle_flag*0.5,0,0)
			cardtable_tran[i]:EX_DOMove(endPos,0.1):EX_OnComplete(function()
				endPos = pos+Vector3(-0.5*stuffle_flag,0,0)
				cardtable_tran[i]:EX_DOMove(endPos,0.2):EX_OnComplete(function()
					cardtable_tran[i]:EX_DOMove(pos,0.1)
				end)
			end)
		end
		stuffle_count = stuffle_count +1
		if stuffle_count >2000 then
			CS.TimeMgr.Instance:RmvTimeInterval("Stuffle")
			stuffle_count = 0
		end
	end
end--]]
function ShowFanPaiEff(obj,effname)
    EffectMgr:PlayEffect("UI/" .. effname, obj,  Vector3(0,0,2), Quaternion.identity, Vector3(1.2,1.2,1), function(eff, dummyParam)
	    CS.UIDepth.Get(eff):SetValue(5,false)
		eff.gameObject.name = effname
	    eff:EX_SetLayer("UI")
    end)
end

function RemoveEff(obj,effname)
	local eff = obj.transform:Find(effname)
	if Ex_IsNotNil(eff) then
		Object.Destroy(eff.gameObject)
	end
end

这个界面效果还是很满意的。

加油

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值