麻将牌堆渲染(Lua)
2026/6/6 13:00:08 网站建设 项目流程

麻将牌堆渲染(Lua):

用法:

-- 牌堆localnTotalRemaining=tData.nRemainingCountor0localtDice=tData.tDiceor{0,0}localtWall=MahjongUI_CalcWallTiles(tData.nRemainingCount,tData.tDice)fornDir=1,4dolocalnAbsSeat=((nMySeat-1+nDir-1)%4)+1MahjongUI_UpdateMaPai(nDir,tWall[nAbsSeat],26)end

实现:

localMAHJONG_TOTAL_TILES=108-- 总牌数(万条筒各1-9×4)localMAHJONG_TILES_PER_WALL=27-- 每方墙 108/4 = 27 张--- 根据骰子点数和剩余张数计算4方墙各显示多少张--- 牌墙是连续一整条,从切牌位顺时针顺序消耗,剩余显示在对应墙--- @param nRemainingCount number 剩余总张数--- @param tDice table|nil 骰子数组 {d1, d2},nil时均分--- @return table tWallTiles[1..4] 每方墙张数functionMahjongUI_CalcWallTiles(nRemainingCount,tDice)localtWall={0,0,0,0}localR=nRemainingCountor0ifR<=0thenreturntWallendlocalnCutWall=1localnDeadCards=0iftDiceandtDice[1]andtDice[2]andnot(tDice[1]==0andtDice[2]==0)thenlocalnSum=tDice[1]+tDice[2]nCutWall=((nSum-1)%4)+1nDeadCards=(nSum-1)*2end-- 1. 切牌墙先放死牌localnDead=math.min(nDeadCards,R)tWall[nCutWall]=nDead R=R-nDeadifR<=0thenreturntWallend-- 2. 顺时针分配(下家->对家->上家)localMAX_PER_WALL=26localORDER={[1]=2,[2]=3,[3]=4,[4]=1}localnIdx=nCutWallwhileR>0donIdx=ORDER[nIdx]localnCanAdd=MAX_PER_WALL-tWall[nIdx]localnAdd=math.min(nCanAdd,R)tWall[nIdx]=tWall[nIdx]+nAdd R=R-nAddifnCanAdd<=0thenbreakendendifR>0thentWall[nCutWall]=tWall[nCutWall]+RendifMAHJONG_DEBUGthenmodule_mahjong.MJLOGT("CalcWallTiles: result=%s",toString(tWall))endreturntWallend--- 根据骰子计算每方墙初始牌数(发牌后剩余56张)--- @param tDice table 骰子点数--- @return table[4] 每方墙初始牌数functionMahjongUI_GetInitWallTiles(tDice)returnMahjongUI_CalcWallTiles(56,tDice)end-- === _UpdateMaPai_Unified ===-- 统一牌墙渲染(带详细日志)localfunction_UpdateMaPai_Unified(nDir,wndMaPai,nTiles,nCutSeat,nDiceSum)localszTemplate=MAPAI_TEMPLATES[nDir]localMAX_PILES=13localbIsCutWall=(nDir==nCutSeat)localnDeadPiles=bIsCutWalland(nDiceSum-1)or0localnDeadCards=nDeadPiles*2localnEffMaxPiles=MAX_PILES-nDeadPileslocalnEffectiveTiles=math.max(0,nTiles-nDeadCards)localnRemainingPiles=math.ceil(nEffectiveTiles/2)localbPartial=(nEffectiveTiles>0)and(nEffectiveTiles%2==1)localnConsumed=nEffMaxPiles-nRemainingPiles-- 入口方向:仅本家入口在索引13,其他三家入口在索引1localbEntryAtHigh=(nDir==1ornDir==4)ifMAHJONG_DEBUGthenmodule_mahjong.MJLOGT("_UpdateMaPai_Unified: dir=%d, tiles=%d, isCut=%s, deadPiles=%d, effTiles=%d, remainPiles=%d, consumed=%d, partial=%s",nDir,nTiles,tostring(bIsCutWall),nDeadPiles,nEffectiveTiles,nRemainingPiles,nConsumed,tostring(bPartial))endlocaltCutWalls={}fori=1,MAX_PILESdolocalnIdx=i-- 控件从左到右创建-- 计算该位置在消耗方向上的逻辑序号(1 = 入口端)localnPosifbEntryAtHighthennPos=MAX_PILES-i+1-- 本家:索引13对应位置1(入口)elsenPos=i-- 其他:索引1对应位置1(入口)endlocalbPH,bIsPartialifnPos<=nDeadPilesthenbPH,bIsPartial=false,falseelseifnPos<=nDeadPiles+nConsumedthenbPH,bIsPartial=true,falseelseifnPos==nDeadPiles+nConsumed+1andbPartialthenbPH,bIsPartial=false,trueelsebPH,bIsPartial=false,falseendlocalwndCard=wndMaPai:CreateChildWindowFromTemplate(szTemplate)ifnotwndCardthenbreakendwndCard:SetName("mapai_"..tostring(nDir).."_"..tostring(nIdx))wndCard:Show(true)localcard1=wndCard:FindEx("card1")localcard2=wndCard:FindEx("card2")card1:Show(true)card2:Show(true)ifbPHthencard1:SetAlpha(0.0)card2:SetAlpha(0.0)elseifbIsPartialthencard1:SetAlpha(1.0)card2:SetAlpha(0.0)elseifbIsCutWallthentable_insert(tCutWalls,wndCard)elsecard1:SetAlpha(1.0)card2:SetAlpha(1.0)endend-- 切牌墙专用二次修正ifbIsCutWalland#tCutWalls>0thenlocaltotalCutPiles=nDiceSum-1localtotalCutCards=totalCutPiles*2localnDrawn=math.max(0,totalCutCards-nTiles)localnHideFull=math.floor(nDrawn/2)localbCutPartial=(nDrawn%2==1)-- 根据方向决定遍历顺序:本家/左家倒序(从右到左),右家/对家正序(从左到右)localbReverse=bEntryAtHigh-- 高位入口的方向采用倒序localnCount=#tCutWallsforseq=1,nCountdolocalwndCardifbReversethenwndCard=tCutWalls[nCount-seq+1]-- 倒序elsewndCard=tCutWalls[seq]-- 正序endlocalcard1=wndCard:FindEx("card1")localcard2=wndCard:FindEx("card2")ifseq<=nHideFullthencard1:SetAlpha(0.0)card2:SetAlpha(0.0)elseifseq==nHideFull+1andbCutPartialthencard1:SetAlpha(1.0)card2:SetAlpha(0.0)elsecard1:SetAlpha(1.0)card2:SetAlpha(1.0)endendendend-- === MahjongUI_UpdateMaPai ===-- 牌墙渲染入口:根据切牌位置分派到固定13墩(Fixed13)或动态 SC 模板。-- 销毁并重新创建所有牌墙实例。-- 阶段:所有阶段(初始发牌和游戏中)。-- @param nDir number 方向 (1-4)-- @param nRemainingTiles number 该墙当前剩余牌数-- @param nInitTiles number 该墙初始牌数-- @return nilfunctionMahjongUI_UpdateMaPai(nDir,nRemainingTiles,nInitTiles)localframe=FindWindow("mahjong_main_panel")ifnotframethenreturnendlocalwndMaPai=MahjongUI_FindWindow(frame,"wnd_table","list_mapai"..tostring(nDir))ifnotwndMaPaithenreturnendlocalnTiles=nRemainingTilesor0localnInit=nInitTilesor0ifnInit<=0thenifnDir~=1andnDir~=2andnDir~=3andnDir~=4thenreturnendendwndMaPai:DestroyAllChildWindow()localtDice=module_mahjong.mahjong_client_core.Client_GetData().tDicelocalnDiceSum=(tDiceandtDice[1]andtDice[2])and(tDice[1]+tDice[2])or0localnCutSeatAbs=(nDiceSum>0)and((nDiceSum-1)%4+1)or0localnMySeat=MahjongUI_GetMySeat()localnCutSeat=(nCutSeatAbs>0andnMySeat>0)andMahjongUI_GetRelativeSeat(nMySeat,nCutSeatAbs)or0ifMAHJONG_DEBUGthenmodule_mahjong.MJLOGT("UpdateMaPai: nDir=%d nCutSeat(abs=%d→rel=%d) nMySeat=%d nTiles=%d",nDir,nCutSeatAbs,nCutSeat,nMySeat,nTiles)end-- 统一渲染(正式使用)_UpdateMaPai_Unified(nDir,wndMaPai,nTiles,nCutSeat,nDiceSum)end

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询