---@class WB_CountingHeart_C:UUserWidget ---@field Button_AddCount UButton ---@field CanvasPanel_Map UCanvasPanel ---@field TextBlock_Count UTextBlock ---@field TextBlock_Time UTextBlock ---@field VerticalBox_CountingNum UVerticalBox ---@field WB_AllPlayerMiniScore UWB_AllPlayerMiniScore_C ---@field ShapeWidgetClass UClass --Edit Below-- local WB_CountingHeart = { bInitDoOnce = false; StartGame = false; MaxCount = 0; CountingHeartTable = {}; AllShapeWidget = {}; -- 移动形状的列表 ID = TargetPos(2D) 其中ID为AllShapeWidget的索引 MoveList = {}; NowLevel = 1; PlayerCountingNum = 0; StartAddCountTime = 0; StopAddCountTime = 0; -- 正在显示心形的数量 bHeartCountShowing = false; -- 移动速度 ShapeMoveSpeed = 0.3; -- 当前回合的心形widget HeartShapeList = {}; AllPlayerKey = {}; ShowHeartCountInterval = 0.2; }; function WB_CountingHeart:Construct() self:InitParam() end function WB_CountingHeart:OnShowPanel() self.bIsShow = true --local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C") --MainControlPanel:SetVisibility(ESlateVisibility.Collapsed) MiniGameConfig.ClientSetIsUIGame(true) end function WB_CountingHeart:OnClosePanel() self.bIsShow = false --local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C") --MainControlPanel:SetVisibility(ESlateVisibility.SelfHitTestInvisible) MiniGameConfig.ClientSetIsUIGame(false) WidgetManager:ShowPanel(WidgetConfig.EUIType.UIGameBG, false) end function WB_CountingHeart:InitParam() if self.bInitDoOnce then return end self.bInitDoOnce = true self.WB_AllPlayerMiniScore:Init() UGCEventSystem.AddListener(EventEnum.UpdateShapeInfo, self.UpdateShapeInfo, self) UGCEventSystem.AddListener(EventEnum.AddShapeMoveInfo, self.AddMoveInfo, self) UGCEventSystem.AddListener(EventEnum.ClientSyncCountingNum, self.SyncCountingNum, self) WidgetLibrary.BindButtonClicked(self.Button_AddCount, self.AddCount, self) self.ShowHeartCountInterval = MiniGameConfig.MiniGameInfo[MiniGameConfig.MiniGameType.CountingHeartShaped].GameParam.ShowHeartCountInterval local ParamTablePath = MiniGameConfig.MiniGameInfo[MiniGameConfig.MiniGameType.CountingHeartShaped].GameParam.ParamTable self.CountingHeartTable = UGCSystemLibrary.GetDataTableFromPath(ParamTablePath, true) -- 设置最大Item数量 for i, v in pairs(self.CountingHeartTable) do self.MaxCount = math.max(v.HeartCountMax + v.ConfoundCountMax, self.MaxCount) end self:UpdateAllShapeWidget() end function WB_CountingHeart:UpdateAllShapeWidget() for i = #self.AllShapeWidget + 1, self.MaxCount do local ShapeItem = UserWidget.NewWidgetObjectBP(UGCSystemLibrary.GetLocalPlayerController(), self.ShapeWidgetClass); self.CanvasPanel_Map:AddChild(ShapeItem) ShapeItem:SetVisibility(ESlateVisibility.Collapsed) self.AllShapeWidget[#self.AllShapeWidget + 1] = ShapeItem end end function WB_CountingHeart:GetMapSize() --if self.MapSize == nil or self.MapSize.X == 0 or self.MapSize.Y == 0 then -- -- local CanvasSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(self.CanvasPanel_Map); -- -- self.MapSize = CanvasSlot:GetSize() -- self.MapSize = SlateBlueprintLibrary.GetLocalSize(self.CanvasPanel_Map:GetCachedGeometry()) --end return SlateBlueprintLibrary.GetLocalSize(self.CanvasPanel_Map:GetCachedGeometry()) end function WB_CountingHeart:Tick(MyGeometry, InDeltaTime) if self.bIsShow and self.StartGame then self:UpdateMove(InDeltaTime) local ServerTime = UGCGameSystem.GameState:GetServerGameTime() if ServerTime >= self.StopAddCountTime then self:ShowHeartCount() end local ShowTime = math.floor(self.StopAddCountTime - ServerTime) if ShowTime > 0 then self.TextBlock_Time:SetText(tostring(ShowTime)) else self.TextBlock_Time:SetText("0") end end end ---@param MoveInfos table:{{ID:int, TargetPos:Vector2D}, ...} function WB_CountingHeart:AddMoveInfo(MoveInfos) local TempMapSize = self:GetMapSize() for _, Info in pairs(MoveInfos) do local TempTargetPos = VectorHelper.Mul2D(Info.TargetPos, TempMapSize) local InMoveList = false for i, v in pairs(self.MoveList) do if v.ID == Info.ID then InMoveList = true self.MoveList[i].TargetPos = TempTargetPos break end end if not InMoveList then self.MoveList[#self.MoveList + 1] = {ID = Info.ID, TargetPos = TempTargetPos} self.AllShapeWidget[Info.ID]:SetMoving() end end UGCLogSystem.LogTree("[WB_CountingHeart_AddMoveInfo] MoveList:", self.MoveList) end function WB_CountingHeart:ClearMoveList() self.MoveList = {} end function WB_CountingHeart:UpdateMove(DeltaTime) if #self.MoveList > 0 then -- .RenderTransform.Translation -- SetRenderTranslation for i = #self.MoveList, 1, -1 do local Item = self.AllShapeWidget[self.MoveList[i].ID] if Item then -- local Pos = Item.RenderTransform.Translation local ItemSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(Item) local Pos = ItemSlot:GetPosition(); local TargetPos = self.MoveList[i].TargetPos local NewPos = KismetMathLibrary.Vector2DInterpTo(Pos, TargetPos, DeltaTime, self.ShapeMoveSpeed) -- Item:SetRenderTranslation(NewPos) ItemSlot:SetPosition(NewPos); if KismetMathLibrary.EqualEqual_Vector2DVector2D(NewPos, TargetPos, 1e-3) then self.AllShapeWidget[self.MoveList[i].ID] = nil Item:StopMove() end else self.AllShapeWidget[self.MoveList[i].ID] = nil end end end end ---@param ShapeInfo table:{{IsHeart:bool, Shape:int, Color:int, Pos:Vector2D}, ...} function WB_CountingHeart:UpdateShapeInfo(Level, InStartAddCountTime, InStopAddCountTime, ShapeInfos) -- 设置当前回合的参数 self.NowLevel = Level self.StartAddCountTime = InStartAddCountTime self.StopAddCountTime = InStopAddCountTime -- 重置一些参数 self.PlayerCountingNum = 0 self:ClearMoveList() self.TextBlock_Count:SetText("0") self.bHeartCountShowing = false self.HeartShapeList = {} self.StartGame = true UGCLogSystem.LogTree("[WB_CountingHeart_UpdateShapeInfo]ShapeInfos:", ShapeInfos) local Size = self:GetMapSize() UGCLogSystem.Log("[WB_CountingHeart_UpdateShapeInfo] Size:%s", VectorHelper.ToString2D(Size)) for i, Item in pairs(self.AllShapeWidget) do local ShapeInfo = ShapeInfos[i] if ShapeInfo then local Tex = self:GetShapeTex(ShapeInfo.IsHeart, ShapeInfo.Shape) local Color = self:GetShapeColor(ShapeInfo.IsHeart, ShapeInfo.Color) if UE.IsValid(Tex) then Item:SetTexture(Tex) end if Color then Item:SetColor(Color) end Item:SetVisibility(ESlateVisibility.SelfHitTestInvisible) Item:ShowCountText(false) Item:SetIsHeart(ShapeInfo.IsHeart) local Pos = KismetMathLibrary.Multiply_Vector2DVector2D(Size, ShapeInfo.Pos) -- UGCLogSystem.Log("[WB_CountingHeart_UpdateShapeInfo] Pos%s", VectorHelper.ToString2D(Pos)) -- Item:SetRenderTranslation(Pos) local ItemSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(Item) ItemSlot:SetPosition(Pos); if ShapeInfo.IsHeart then self.HeartShapeList[#self.HeartShapeList + 1] = Item end -- UGCLogSystem.Log("[WB_CountingHeart_UpdateShapeInfo] i:%s", tostring(i)) else Item:SetVisibility(ESlateVisibility.Collapsed) Item:SetIsHeart(false) end end end function WB_CountingHeart:GetShapeTex(IsHeart, ShapeID) if self.CountingHeartTable[self.NowLevel] == nil then return nil end if IsHeart then return self.CountingHeartTable[self.NowLevel].HeartTextures[ShapeID] else return self.CountingHeartTable[self.NowLevel].ConfoundTextures[ShapeID] end end function WB_CountingHeart:GetShapeColor(IsHeart, ColorID) if self.CountingHeartTable[self.NowLevel] == nil then return nil end if IsHeart then return self.CountingHeartTable[self.NowLevel].HeartColors[ColorID] else return self.CountingHeartTable[self.NowLevel].ConfoundColors[ColorID] end end function WB_CountingHeart:AddCount() local NowServerTime = UGCGameSystem.GameState:GetServerGameTime() if NowServerTime > self.StartAddCountTime and NowServerTime < self.StopAddCountTime then self.PlayerCountingNum = self.PlayerCountingNum + 1 self.TextBlock_Count:SetText(tostring(self.PlayerCountingNum)) UGCSendRPCSystem.RPCEvent(nil, EventEnum.PlayerUpdateCountingNum, UGCSystemLibrary.GetLocalPlayerKey(), self.NowLevel, self.PlayerCountingNum) SoundSystem.PlaySound(SoundSystem.ESound.Clock) end end function WB_CountingHeart:ShowHeartCount() self.StartGame = false self.bHeartCountShowing = true UGCLogSystem.Log("[WB_CountingHeart_ShowHeartCount]") for i, v in pairs(self.MoveList) do self.AllShapeWidget[v.ID]:StopMove() end table.sort(self.HeartShapeList, function(a, b) local aItemSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(a) local aPos = aItemSlot:GetPosition(); local bItemSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(b) local bPos = bItemSlot:GetPosition(); if aPos.Y ~= bPos.Y then return aPos.Y < bPos.Y else return aPos.X < bPos.X end end) local ShowIndex = 1 if self.ShowHeartCountHandle == nil then self.ShowHeartCountHandle = UGCEventSystem.SetTimerLoop( self, function() if ShowIndex >= #self.HeartShapeList or self.bHeartCountShowing == false then UGCEventSystem.StopTimer(self.ShowHeartCountHandle) self.ShowHeartCountHandle = nil end if self.bHeartCountShowing then local Item = self.HeartShapeList[ShowIndex] if Item then Item:SetCount(ShowIndex) Item:ShowCountText(true) SoundSystem.PlaySound(SoundSystem.ESound.Point) end ShowIndex = ShowIndex + 1 end end, self.ShowHeartCountInterval ) end end function WB_CountingHeart:UpdateCountingNumPlayerKeys(InAllPlayerKey) self.AllPlayerKey = InAllPlayerKey UGCLogSystem.LogTree("[WB_AllPlayerMiniScore_UpdatePlayerKeys] AllPlayerKey", self.AllPlayerKey) for i = 1, self.VerticalBox_CountingNum:GetChildrenCount() do local Item = self.VerticalBox_CountingNum:GetChildAt(i - 1) Item:SetPlayerKey(self.AllPlayerKey[i]) end end function WB_CountingHeart:SyncCountingNum(AllPlayerCountingNum) UGCLogSystem.LogTree("[WB_CountingHeart_SyncCountingNum]AllPlayerCountingNum:", AllPlayerCountingNum) if #self.AllPlayerKey ~= table.getCount(AllPlayerCountingNum) then self:UpdateCountingNumPlayerKeys(table.getKeys(AllPlayerCountingNum)) end for i = 1, self.VerticalBox_CountingNum:GetChildrenCount() do local Item = self.VerticalBox_CountingNum:GetChildAt(i - 1) if AllPlayerCountingNum[Item:GetPlayerKey()] then Item:UpdatePlayerScore(AllPlayerCountingNum[Item:GetPlayerKey()]) end end end return WB_CountingHeart;