PikaHUDBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/HUD.h" #include "PikaMainInterface.h" #include "PikaUIData.h" #include "PikaGodStonePlayerController.h" #include "PikaHUDBase.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaHUDBase : public AHUD { GENERATED_BODY() public: APikaHUDBase(); virtual void BeginPlay() override; //该函数类似Tick函数,会被连续调用 virtual void DrawHUD() override; FORCEINLINE APikaGodStonePlayerController* PikaGetPC(); //UI数据 UPikaUIData * PikaUIDataInstance; private: //主界面指针 UPikaMainInterface * PikaMainInterfacePre; };
PikaHUDBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaHUDBase.h" #include "ConstructorHelpers.h" APikaHUDBase::APikaHUDBase() { //加载主界面蓝图 TSubclassOf<UPikaUIData> MyUIData = UPikaUIData::StaticClass(); if (GetWorld()) { PikaUIDataInstance = NewObject<UPikaUIData>(GetWorld(), MyUIData); static ConstructorHelpers::FClassFinder<UPikaMainInterface> PikaMainInterfaceInstance(TEXT("/Game/HUD/GameUI/PikaMainInterfaceBP")); TSubclassOf<UPikaMainInterface> PikaInterfaceTsubclass = PikaMainInterfaceInstance.Class; if (PikaInterfaceTsubclass && PikaUIDataInstance) { PikaMainInterfacePre = CreateWidget<UPikaMainInterface>(GetWorld(), PikaInterfaceTsubclass); PikaMainInterfacePre->PikaUIDataPtr = PikaUIDataInstance; PikaMainInterfacePre->AddToViewport(); } } } void APikaHUDBase::BeginPlay() { Super::BeginPlay(); } //该函数类似Tick函数,会被连续调用 void APikaHUDBase::DrawHUD() { if (PikaGetPC() && PikaGetPC()->PikaGlobalConfigPrePlayerCon && PikaGetPC()->PikaGameResourcePtr) { //绘制我们的地图 if (PikaGetPC()->PikaGetCurrentLevelMiniMap() && Canvas && PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap.IsValidIndex(PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaGameLevelManangenment.PikaCurrentLevel)) { //******************************************************************************************** int32 PikaCurrentLevel = PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaGameLevelManangenment.PikaCurrentLevel; //贴图占我们的720分辨率的百分比 float PikaView_RatioY = PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeY / 720.f; float PikaView_WHRatio = PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeY / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeX; //我们的视野离边界的距离 float PikaView_RatioIntervalY = PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeYInterval / 720.f; float PikaView_IntervalWHRatio = PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeYInterval / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapSizeXInterval; //当前的贴图大小 float PikaView_CurrentHeight = PikaView_RatioY * Canvas->SizeY; float PikaView_CurrentWidth = PikaView_CurrentHeight / PikaView_WHRatio; //当前的贴图与外边框的距离 float PikaView_CurrentIntervalHeight = PikaView_RatioIntervalY * Canvas->SizeY; float PikaView_CurrentIntervalWidth = PikaView_CurrentIntervalHeight / PikaView_IntervalWHRatio; //获取绘制地图的x,y坐标 float PikaView_MiniMapSizeX = Canvas->SizeX - (PikaView_CurrentWidth + PikaView_CurrentIntervalWidth); float PikaView_MiniMapSizeY = Canvas->SizeY - (PikaView_CurrentHeight + PikaView_CurrentIntervalHeight); //绘制地图 DrawTexture(PikaGetPC()->PikaGetCurrentLevelMiniMap(), PikaView_MiniMapSizeX, PikaView_MiniMapSizeY, PikaView_CurrentWidth, PikaView_CurrentHeight, 0, 0, 1, 1); //******************************************************************************************** //绘制玩家的位置坐标 if (PikaGetPC()->PikaGlobalConfigPrePlayerCon) { //移除死亡的,不绘制 for (int32 i = 0; i < PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterSpawnID.Num(); i++) { if (!PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterActive[i]) PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaRemoveIt(i); } for (int32 i = 0; i < PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterSpawnID.Num(); i++) { //所有角色的世界位置 FVector PikaCharacter_Pos = PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterLocation[i]; //获取该角色相对与我们的M(X,Y)的坐标的位置 FVector PikaVecLocation = (-1 * (PikaGetPC()->PikaGetMapMarkPointRotator())).RotateVector(PikaCharacter_Pos - PikaGetPC()->PikaGetMapMarkPointLocation()); //求出在真实场景内玩家在小地图上的距离 float PikaMiniMap_SizeX = (PikaVecLocation.X / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMapSizeX) * PikaView_CurrentWidth; float PikaMiniMap_SizeY = (PikaVecLocation.Y / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMapSizeY) * PikaView_CurrentHeight; //求出角色在我们地图上的坐标 float PikaChar_PosMiniMapX = PikaView_MiniMapSizeX + PikaMiniMap_SizeX; float PikaChar_PosMiniMapY = PikaView_MiniMapSizeY + PikaMiniMap_SizeY; //绘制点在我们的小地图上 if (PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterTeam[i]) Canvas->K2_DrawLine(FVector2D(PikaChar_PosMiniMapX, PikaChar_PosMiniMapY), FVector2D(PikaChar_PosMiniMapX + 1, PikaChar_PosMiniMapY + 1), 6, FLinearColor::Blue); else Canvas->K2_DrawLine(FVector2D(PikaChar_PosMiniMapX, PikaChar_PosMiniMapY), FVector2D(PikaChar_PosMiniMapX + 1, PikaChar_PosMiniMapY + 1), 6, FLinearColor::Red); } //绘制相机框 if (PikaGetPC()->PikaGameResourcePtr->PikaNewCameraBoard && PikaGetPC()->GetPawn()) { //获取地图比值 FVector2D PikaCharacter_Pos = PikaGetPC()->PikaGameResourcePtr->PikaPlayerLocConverMiniMapCoord(PikaCurrentLevel, PikaGetPC()->PikaGetMapMarkPoint(), PikaGetPC()->GetPawn()); float PikaMiniMap_SizeX = FMath::Abs(PikaCharacter_Pos.X* PikaView_CurrentWidth); float PikaMiniMap_SizeY = FMath::Abs(PikaCharacter_Pos.Y* PikaView_CurrentHeight); //求出角色在我们地图上的坐标 float PikaChar_PosMiniMapX = PikaView_MiniMapSizeX + PikaMiniMap_SizeX; float PikaChar_PosMiniMapY = PikaView_MiniMapSizeY + PikaMiniMap_SizeY; //摄像机尺寸 float PikaCamraBoardX = ((PikaGetPC()->PikaGameResourcePtr->PikaNewCameraBoardSize.X / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMapSizeX)* PikaView_CurrentWidth)*PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaMouseZoom; float PikaCamraBoardY = ((PikaGetPC()->PikaGameResourcePtr->PikaNewCameraBoardSize.Y / PikaGetPC()->PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMapSizeY)* PikaView_CurrentHeight)*PikaGetPC()->PikaGlobalConfigPrePlayerCon->PikaMouseZoom; DrawTexture(PikaGetPC()->PikaGameResourcePtr->PikaNewCameraBoard, PikaChar_PosMiniMapX - PikaCamraBoardX, PikaChar_PosMiniMapY - PikaCamraBoardY / 2, PikaCamraBoardX, PikaCamraBoardY, 0, 0, 1, 1); } } } } } FORCEINLINE APikaGodStonePlayerController* APikaHUDBase::PikaGetPC() { return PlayerOwner != NULL ? ((APikaGodStonePlayerController*)PlayerOwner) : NULL; }
PikaMainInterface.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUI_Inventory.h" #include "SizeBox.h" #include "PikaUITowerInfo.h" #include "PikaUIGameCount.h" #include "PikaUIGameMenu.h" #include "PikaGameErrorHint.h" #include "WidgetSwitcher.h" #include "PikaUIReadAndWrite.h" #include "PikaUIHallGameSetting.h" #include "PikaUIGameWarning.h" #include "PikaMainInterface.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FEventPikaLog, FString, MyString); /** * */ UCLASS() class PIKAGODSTONE_API UPikaMainInterface : public UPikaUIWidgetBase { GENERATED_BODY() //用来载入PikaUI_Inventory的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUI_Inventory> PikaInventoryClass; //用来载入UPikaUITowerInfo的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUITowerInfo> PikaUITowerInfoClass; //用来载入UPikaUIGameCount的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUIGameCount> PikaUIGameCountClass; //用来载入UPikaUIGameMenu的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUIGameMenu> PikaUIGameMenuClass; //用来载入UPikaGameErrorHint的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaGameErrorHint> PikaGameErrorHintClass; //用来载入UPikaUIReadAndWrite的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUIReadAndWrite> PikaReadAndWriteClass; //用来载入UPikaUIHallGameSetting的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUIHallGameSetting> PikaHallGameSettingsClass; //用来载入UPikaUIGameWarning的蓝图类 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUIGameWarning> PikaGameWarningClass; //BoxSize相关的名字 ////////////////////////////////////////////////////////////////////////// UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaAttributeInfoArrayName; //物品栏集合的名字,由蓝图传入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaInventoryArrayName; //物品栏道具的信息,由蓝图传入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterInfoArrayName; //游戏规则和游戏计时,由蓝图传入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaUIGameCountArrayName; //游戏内部简易菜单,由蓝图传入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaUIGameMenuArrayName; //错误提示,由蓝图传入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGameErrorHintArrayName; //打开游戏菜单 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGameOpenMenuName; //设置和存储菜单 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaBoxSaveGameArrayName; //警告框 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaBoxGameWarningArrayName; public: virtual void AddToViewport(int32 ZOrder = 0) override; //每一帧的屏幕信息 FGeometry ScreenGeometry; //打印的代理 FEventPikaLog PikaLog; //负责打印GameLOG virtual void PikaLogPrintf(FString MyString) override; virtual void PikaDrawUIToScreen() override; //Tick virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; //敲击 virtual void PikaOnClickedWidget(UWidget* MyWidget)override; //屏蔽操作 void PikaShieldedInteractiveOperation(bool InVisibility); //存档与游戏设置切换 void PikaSetBoxListDisplayOrder(PikaBoxListType::Type BoxListType); PikaBoxListType::Type PikaGetBoxListDisplayOrder() const; virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) override; ////////////////////////////////////内联///////////////////////////////////// FORCEINLINE USizeBox* PikaGetCharacterAttribute() const { return PikaAttributeInfoArray; } FORCEINLINE UPikaUITowerInfo* PikaGetUITowerInfo() const { return PikaUITowerInfoPtr; } FORCEINLINE UWidgetSwitcher* PikaGetBoxSaveGameArray()const { return PikaBoxSaveGameArray; } FORCEINLINE UPikaUIReadAndWrite* PikaGetReadAndWrite() const { return PikaReadAndWrite; } FORCEINLINE UPikaUIGameWarning* PikaGetGameWarning() const { return PikaGameWarningPtr; } private: //UPikaUI_Inventory类的指针 UPikaUI_Inventory * PikaUIInventoryPtr; //UPikaUITowerInfo类的指针,对应PikaAttributeInfoArray UPikaUITowerInfo * PikaUITowerInfoPtr; //作为临时角色数据显示 FPikaCharacterInformationWidget* PikaTempCharacterInformationWidget; //游戏规则和游戏计时 UPikaUIGameCount* PikaUIGameCountPtr; //游戏内部简易菜单 UPikaUIGameMenu* PikaUIGameMenuPtr; //错误提示 UPikaGameErrorHint* PikaGameErrorHintPtr; //保存和读取界面 UPikaUIReadAndWrite* PikaReadAndWrite; //游戏设置 UPikaUIHallGameSetting* PikaHallGameSettings; //提示界面 UPikaUIGameWarning* PikaGameWarningPtr; //容器相关 USizeBox * PikaInventorySlotArrayBox; USizeBox * PikaCharacterInfoArray; USizeBox* PikaAttributeInfoArray; USizeBox* PikaGameCountArray; USizeBox* PikaGameErrorHintArray; USizeBox* PikaGameMenuArray; UButton* PikaGameOpenMenu; UWidgetSwitcher* PikaBoxSaveGameArray; USizeBox* PikaBoxGameWarninArray; //存储我们的控件的上级 TArray<UWidget*> PikaBoxSizeArray; protected: //NativeOnDragDetected激活后,如果将图标从一个物品栏拖拽到另外一个物品栏则会触发该事件 //接收拖拽信息,InOperation为空时,该函数不会被激活 virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override; };
PikaMainInterface.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaMainInterface.h" #include "Engine/Engine.h" #include "Public/PikaDragDropOperation.h" void UPikaMainInterface::AddToViewport(int32 ZOrder /*= 0*/) { Super::AddToViewport(ZOrder); PikaInventorySlotArrayBox = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaInventoryArrayName)); PikaCharacterInfoArray = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaCharacterInfoArrayName)); PikaGameCountArray = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaUIGameCountArrayName)); PikaGameErrorHintArray = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaGameErrorHintArrayName)); PikaGameMenuArray = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaUIGameMenuArrayName)); PikaGameOpenMenu = PikaGetButtonFromBlueprint(PikaGameOpenMenuName); PikaBoxSaveGameArray = Cast<UWidgetSwitcher>(PikaqiuGetBlueprintWidget(PikaBoxSaveGameArrayName)); PikaBoxGameWarninArray = Cast<USizeBox>(GetWidgetFromName(PikaBoxGameWarningArrayName)); //在基础UI里添加控件 if (GetWorld()) { //添加Inventory if (PikaInventoryClass && PikaInventorySlotArrayBox) { PikaUIInventoryPtr = CreateWidget<UPikaUI_Inventory>(GetWorld(), PikaInventoryClass); PikaUIInventoryPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaInventorySlotArrayBox, PikaUIInventoryPtr); PikaUIInventoryPtr->PikaSetMainInterface(this); PikaUIInventoryPtr->PikaDrawUIToScreen(); } //添加PikaUITowerInfo控件 if (PikaUITowerInfoClass && PikaCharacterInfoArray) { PikaUITowerInfoPtr = CreateWidget<UPikaUITowerInfo>(GetWorld(), PikaUITowerInfoClass); PikaUITowerInfoPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaCharacterInfoArray, PikaUITowerInfoPtr); PikaUITowerInfoPtr->PikaDrawUIToScreen(); //默认状态下隐藏 PikaUITowerInfoPtr->SetVisibility(ESlateVisibility::Hidden); } //添加UPikaUIGameCount if (PikaUIGameCountClass && PikaGameCountArray) { PikaUIGameCountPtr = CreateWidget<UPikaUIGameCount>(GetWorld(), PikaUIGameCountClass); PikaUIGameCountPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaGameCountArray, PikaUIGameCountPtr); PikaUIGameCountPtr->PikaSetMainInterface(this); PikaUIGameCountPtr->PikaDrawUIToScreen(); } //添加UPikaUIGameMenu if (PikaUIGameMenuClass && PikaGameMenuArray) { PikaUIGameMenuPtr = CreateWidget<UPikaUIGameMenu>(GetWorld(), PikaUIGameMenuClass); PikaUIGameMenuPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaGameMenuArray, PikaUIGameMenuPtr); PikaUIGameMenuPtr->PikaSetMainInterface(this); PikaUIGameMenuPtr->PikaDrawUIToScreen(); //默认状态下隐藏 PikaUIGameMenuPtr->SetVisibility(ESlateVisibility::Hidden); } //添加UPikaGameErrorHint if (PikaGameErrorHintClass && PikaGameErrorHintArray) { PikaGameErrorHintPtr = CreateWidget<UPikaGameErrorHint>(GetWorld(), PikaGameErrorHintClass); PikaGameErrorHintPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaGameErrorHintArray, PikaGameErrorHintPtr); PikaGameErrorHintPtr->PikaSetMainInterface(this); PikaGameErrorHintPtr->PikaDrawUIToScreen(); } //叠加界面 if (PikaBoxSaveGameArray) { //隐藏自己 PikaBoxSaveGameArray->SetVisibility(ESlateVisibility::Hidden); //添加我们的游戏存储界面 if (PikaReadAndWriteClass) { PikaReadAndWrite = CreateWidget<UPikaUIReadAndWrite>(GetWorld(), PikaReadAndWriteClass); check(PikaReadAndWrite); PikaReadAndWrite->PikaUIDataPtr = PikaUIDataPtr; PikaBoxSaveGameArray->AddChild(PikaReadAndWrite); PikaReadAndWrite->PikaDrawUIToScreen(); if (PikaUIGameMenuPtr) PikaReadAndWrite->PikaSetGameMenu(PikaUIGameMenuPtr); PikaReadAndWrite->PikaSetButtonText(PikaReadAndWrite->Pika_WText[0]); PikaReadAndWrite->PikaSetNewButtonType(PikaETDButtonType::SaveGame); } //添加设置界面 if (PikaHallGameSettingsClass) { PikaHallGameSettings = CreateWidget<UPikaUIHallGameSetting>(GetWorld(), PikaHallGameSettingsClass); check(PikaHallGameSettings); PikaHallGameSettings->PikaUIDataPtr = PikaUIDataPtr; PikaBoxSaveGameArray->AddChild(PikaHallGameSettings); PikaHallGameSettings->PikaDrawUIToScreen(); if (PikaUIGameMenuPtr) PikaHallGameSettings->PikaSetGameMenu(PikaUIGameMenuPtr); } } //加载游戏警告 if (PikaGameWarningClass && PikaBoxGameWarninArray) { //隐藏自己 PikaBoxGameWarninArray->SetVisibility(ESlateVisibility::Hidden); PikaGameWarningPtr = CreateWidget<UPikaUIGameWarning>(GetWorld(), PikaGameWarningClass); check(PikaGameWarningPtr); PikaGameWarningPtr->PikaUIDataPtr = PikaUIDataPtr; //添加进去 PikaAddSizeBox(PikaBoxGameWarninArray, PikaGameWarningPtr); PikaGameWarningPtr->PikaSetMainInterface(this); PikaGameWarningPtr->PikaDrawUIToScreen(); //隐藏 //SetWarningWindowsState(false, 0.5f); } } //添加到数组,用在暂停游戏时,屏蔽掉所有不能和鼠标互动的组件 if (PikaInventorySlotArrayBox) PikaBoxSizeArray.Add(PikaInventorySlotArrayBox); if (PikaGameOpenMenu) PikaBoxSizeArray.Add(PikaGameOpenMenu); if (PikaCharacterInfoArray) PikaBoxSizeArray.Add(PikaCharacterInfoArray); if (PikaGameCountArray) PikaBoxSizeArray.Add(PikaGameCountArray); if (PikaGameErrorHintArray) PikaBoxSizeArray.Add(PikaGameErrorHintArray); } void UPikaMainInterface::PikaLogPrintf(FString MyString) { PikaLog.Broadcast(MyString); } void UPikaMainInterface::PikaDrawUIToScreen() { ///////////////////////////////////控件/////////////////////////////////////// //InventorySlotArray = Cast<USizeBox>(GetWidgetFromName(InventorySlotArrayName)); //WidgetInformationArray = Cast<USizeBox>(GetWidgetFromName(WidgetInformationArrayName)); //GameMenuArray = Cast<USizeBox>(GetWidgetFromName(GameMenuName)); //GamePromptErrorArray = Cast<USizeBox>(GetWidgetFromName(GamePromptErrorName)); //GameCountArray = Cast<USizeBox>(GetBlueprintWidget(GameCountName)); //BoxSaveGameArray = Cast<UWidgetSwitcher>(GetBlueprintWidget(BoxSaveGameArrayName)); //BoxGameWarninArray = Cast<USizeBox>(GetWidgetFromName(BoxGameWarningArrayName)); //BoxCharacterList = Cast<USizeBox>(GetWidgetFromName(BoxCharacterButtonName)); //BoxKeyList = Cast<USizeBox>(GetBlueprintWidget(BoxKeyListName)); //ConditionsArray = Cast<USizeBox>(GetWidgetFromName(ConditionsArrayName)); PikaAttributeInfoArray = Cast<USizeBox>(GetWidgetFromName(PikaAttributeInfoArrayName)); //APointOnScreen = Cast<UImage>(GetBlueprintWidget(APointOnScreenName)); ////////////////////////////////////////////////////////////////////////// } void UPikaMainInterface::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) { Super::NativeTick(MyGeometry, InDeltaTime); //获取角色数据并在界面上显示 if (PikaUIInventoryPtr && PikaUITowerInfoPtr) { if (PikaUIInventoryPtr->PikaGetNewInventorySlot() && PikaUIInventoryPtr->PikaGetNewInventorySlot()->PikaBuildingTowerStruct.PikaIsActive()) { //只要是我们的CharacterInformationWidget的值发生改变,才会显示改变的值 if (!PikaTempCharacterInformationWidget || !(&PikaUIInventoryPtr->PikaGetNewInventorySlot()->PikaBuildingTowerStruct.PikaCharacterInformationWidget == PikaTempCharacterInformationWidget)) { PikaUITowerInfoPtr->PikaCharacterInformationWidget = &PikaUIInventoryPtr->PikaGetNewInventorySlot()->PikaBuildingTowerStruct.PikaCharacterInformationWidget; //作为临时判断的界面信息 PikaTempCharacterInformationWidget = &PikaUIInventoryPtr->PikaGetNewInventorySlot()->PikaBuildingTowerStruct.PikaCharacterInformationWidget; //更新界面显示 PikaUITowerInfoPtr->PikaUpdateCharacterInformation(); } } } } //onclick事件是通过父类UPikaUIWidgetBase里的PikaGetButtonFromBlueprint方法绑定的 void UPikaMainInterface::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaGameOpenMenu) { if (PikaUIGameMenuPtr && PikaGetPlayerController()) { PikaUIGameMenuPtr->SetVisibility(ESlateVisibility::Visible); PikaShieldedInteractiveOperation(false); //设置全局时间 if (PikaGetGameInstance()) { //设置全局时间的增量为0,默认值为0 PikaGetGameInstance()->PikaSetGlobalGameTime(); } } } } void UPikaMainInterface::PikaShieldedInteractiveOperation(bool InVisibility) { for (UWidget* ElementWidger : PikaBoxSizeArray) { ElementWidger->SetIsEnabled(InVisibility); } //锁住CD更新或继续CD更新 if (PikaUIInventoryPtr) PikaUIInventoryPtr->PikaLockSlotCD(!InVisibility); //暂停游戏或继续游戏 PikaGetPlayerController()->SetPause(!InVisibility); } void UPikaMainInterface::PikaSetBoxListDisplayOrder(PikaBoxListType::Type BoxListType) { if (PikaBoxSaveGameArray) PikaBoxSaveGameArray->SetActiveWidgetIndex(BoxListType); } PikaBoxListType::Type UPikaMainInterface::PikaGetBoxListDisplayOrder() const { if (PikaBoxSaveGameArray) return (PikaBoxListType::Type)PikaBoxSaveGameArray->GetActiveWidgetIndex(); return (PikaBoxListType::Type)INDEX_NONE; } void UPikaMainInterface::PikaSetWarningWindowsState(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= PikaEButtonSureType::BST_None*/) { if (IsVisibles) { //显示警告框 PikaGameWarningPtr->PikaSetText(MyWidget); PikaBoxGameWarninArray->SetVisibility(ESlateVisibility::Visible); } else { PikaBoxGameWarninArray->SetVisibility(ESlateVisibility::Hidden); } } bool UPikaMainInterface::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) { Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation); bool PikaIsDrop = false; return PikaIsDrop; }
PikaMonster.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaCharacterBase.h" #include "PikaBulletBase.h" #include "PikaMonster.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaMonster : public APikaCharacterBase { GENERATED_BODY() public: //怪物的攻击逻辑 virtual void PikaAttackTarget(AActor * Target) override; //接收对方的伤害 virtual float PikaGetDefenceDamage(AActor * OtherActor); //子弹 APikaBulletBase * PikaMyBullet; //怪物死亡函数 virtual void PikaDestoryCharacter(float DelayTime = 0) override; virtual void BeginPlay() override; };
PikaMonster.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaMonster.h" #include "Kismet/GameplayStatics.h" #include "Public/PikaMonsterAIController.h" //怪物的攻击逻辑,攻击目标Target由行为树传递过来 void APikaMonster::PikaAttackTarget(AActor * Target) { Super::PikaAttackTarget(Target); if (PikaCharacterBullet && GetWorld() && GetSpawnPoint()) { APikaCharacterBase * PikaEnemyTower = Cast<APikaCharacterBase>(Target); FVector PikaBulletLocation = GetSpawnPoint()->GetComponentLocation(); //FRotator PikaBuletRotator = GetSpawnPoint()->GetComponentRotation(); //销毁上一次的子弹 /*if (PikaMyBullet) { PikaMyBullet->Destroy(true); PikaMyBullet = NULL; }*/ PikaMyBullet = GetWorld()->SpawnActor<APikaBulletBase>(PikaCharacterBullet, PikaBulletLocation, FRotationMatrix::MakeFromX(PikaEnemyTower->GetHomingPoint()->GetComponentLocation() - PikaBulletLocation).Rotator()); if (PikaMyBullet) { //将自己赋值到子弹的施法者里 PikaMyBullet->PikaSetCasterCharacter(this); //跟踪子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Track) { APikaCharacterBase * PikaMyTarget = (APikaCharacterBase*)Target; if (PikaMyTarget) { //跟踪加速度大小 PikaMyBullet->GetProjectleMovment()->HomingAccelerationMagnitude = 4000.f; //跟踪组件 PikaMyBullet->GetProjectleMovment()->HomingTargetComponent = PikaMyTarget->GetHomingPoint(); //绑定伤害特效 /*if (PikaMyBullet->PikaDamageParticle) { UGameplayStatics::SpawnEmitterAttached(PikaMyBullet->PikaDamageParticle, PikaMyTarget->GetHomingPoint()); }*/ } return; } //直线飞行子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Line) { return; } //范围攻击型子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Range) { return; } //闪电型攻击 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Chain) { return; } } } } float APikaMonster::PikaGetDefenceDamage(AActor * OtherActor) { return 0; } void APikaMonster::PikaDestoryCharacter(float DelayTime) { //上传死亡的数据 if (PikaGetPlayerController()) PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaKillSoldierNumber++; Super::PikaDestoryCharacter(DelayTime); APikaMonsterAIController * PikaMonAICon = Cast<APikaMonsterAIController>(Controller); //告诉行为树角色已死亡 if (PikaMonAICon) { PikaMonAICon->PikaSetCharacterDeathInfoSendBehaviorTree(true); } } void APikaMonster::BeginPlay() { Super::BeginPlay(); //将塔的Team设置为true,初始化时为false if (PikaCharDataPre) PikaCharDataPre->PikaCharBaseData.PikaTeam = false; }
PikaMonsterAIController.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "AIController.h" #include "BehaviorTree/BehaviorTree.h" #include "Public/PikaTowers.h" #include "PikaMonsterAIController.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaMonsterAIController : public AAIController { GENERATED_BODY() //创建行为树指针 UPROPERTY(EditDefaultsOnly , Category = "PikaBehaviorTree") UBehaviorTree * PikaMonsterBeahaviorTreePre; UPROPERTY(EditDefaultsOnly, Category = "PikaBehaviorTree") FName PikaDeathName; public: virtual void BeginPlay() override; //寻找目标 AActor * PikaFindTarget(); //获取随机点 FVector PikaGetRandomLoaction(); //将角色的死亡信息传递到行为树 void PikaSetCharacterDeathInfoSendBehaviorTree(bool BoolDeath); APikaTowers* PikaGetRecentlyTowers(TArray<APikaTowers*>MyTowersArr); };
PikaMonsterAIController.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaMonsterAIController.h" #include "Public/PikaCharacterBase.h" #include "EngineUtils.h" #include "AI/Navigation/NavigationSystem.h" #include "BehaviorTree/BlackboardComponent.h" void APikaMonsterAIController::BeginPlay() { Super::BeginPlay(); //执行行为树 if (PikaMonsterBeahaviorTreePre) { RunBehaviorTree(PikaMonsterBeahaviorTreePre); } //初始化死亡状态 PikaSetCharacterDeathInfoSendBehaviorTree(false); } //寻找目标 AActor * APikaMonsterAIController::PikaFindTarget() { if (!GetWorld() || !GetPawn()) { return NULL; } //存储主塔 TArray<APikaTowers*> PikaTargetMainTarray; //存储需要攻击的目标 TArray<APikaTowers*> PikaTargetTarray; APikaCharacterBase * PikaPawn = Cast<APikaCharacterBase>(GetPawn()); //获取整个场景中APikaCharacterBase类的全部实例 if (PikaPawn) { for (TActorIterator<APikaTowers>it(GetWorld() , APikaTowers::StaticClass()); it; ++it) { APikaTowers * PikaTheCharacter = *it; if (PikaTheCharacter && PikaTheCharacter->PikaIsActive()) { if (PikaTheCharacter->PikaGetTowersType() == EPikaTowersType::PikaTOWERS_MainTowers) { PikaTargetMainTarray.Add(PikaTheCharacter); } else if (PikaTheCharacter->PikaGetTowersType() == EPikaTowersType::PikaTOWERS_Towers) { PikaTargetTarray.Add(PikaTheCharacter); } } } } //寻找离自己最近的主塔和普通塔,有主塔优先返回主塔为目标塔 APikaTowers* PikaMainTowers = PikaGetRecentlyTowers(PikaTargetMainTarray); APikaTowers* PikaNormalTowers = PikaGetRecentlyTowers(PikaTargetTarray); if (PikaMainTowers) { return PikaMainTowers; } else if (PikaNormalTowers) { return PikaNormalTowers; } return NULL; } //获取随机点 FVector APikaMonsterAIController::PikaGetRandomLoaction() { FVector PikaRandomPoint = FVector::ZeroVector; if (GetWorld()) { //第四个参数表示在多大范围内进行随机 UNavigationSystem::K2_GetRandomPointInNavigableRadius(GetWorld() , GetPawn()->GetActorLocation() , PikaRandomPoint , 2000.f); } return PikaRandomPoint; } //将角色的死亡信息传递到行为树 void APikaMonsterAIController::PikaSetCharacterDeathInfoSendBehaviorTree(bool BoolDeath) { UBlackboardComponent * PikaMyBlackBoard = GetBlackboardComponent(); if (PikaMyBlackBoard) { PikaMyBlackBoard->SetValueAsBool(PikaDeathName, BoolDeath); } } APikaTowers* APikaMonsterAIController::PikaGetRecentlyTowers(TArray<APikaTowers*>MyTowersArr) { //寻找离自己最近的敌对目标 if (MyTowersArr.Num() > 0) { float PikaTowerTargetDistance = 999999; int PikaTowerID = -2; //获取自己的位置 FVector PikaMyLocation = GetPawn()->GetActorLocation(); for (int32 i = 0; i < MyTowersArr.Num(); i++) { APikaTowers * PikaTowerChar = MyTowersArr[i]; if (PikaTowerChar) { FVector PikaTowerLocation = PikaTowerChar->GetActorLocation(); //距离 FVector TempVector = PikaTowerLocation - PikaMyLocation; float PikaTowerAndMonsterDistance = TempVector.Size(); if (PikaTowerAndMonsterDistance < PikaTowerTargetDistance) { //获取容器中最近的那个 PikaTowerID = i; //和下一个塔的位置做比较,寻找最近的那个 PikaTowerTargetDistance = PikaTowerAndMonsterDistance; } } } //找到的离自己最近的塔 if (PikaTowerID > -1) { return MyTowersArr[PikaTowerID]; } } return NULL; }
PikaMonsterBTServiceFindTarget.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "BehaviorTree/BTService.h" #include "PikaCharacterBase.h" #include "PikaMonsterBTServiceFindTarget.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaMonsterBTServiceFindTarget : public UBTService { GENERATED_BODY() APikaCharacterBase * PikaTargetTower; //是否终止循环 bool PikaIsStop; public: virtual void InitializeFromAsset(UBehaviorTree & Asset) override; /** update next tick interval * this function should be considered as const (don't modify state of object) if node is not instanced! */ virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; //下面的两个结构体会通过行为树的selector里选择和黑板对应的变量 //tower UPROPERTY(EditAnywhere, Category = "PikaBlackBoard") struct FBlackboardKeySelector PikaBlackBoardKeyTarget; //tower离Monster之间的距离 UPROPERTY(EditAnywhere, Category = "PikaBlackBoard") struct FBlackboardKeySelector PikaBlackBoardKeyDistance; public: /** Notify called after GameplayTask finishes initialization (not active yet) */ virtual void OnGameplayTaskInitialized(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state to Active (initial activation or resuming) */ virtual void OnGameplayTaskActivated(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state from Active (finishing or pausing) */ virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) {} };
PikaMonsterBTServiceFindTarget.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaMonsterBTServiceFindTarget.h" #include "BehaviorTree/BehaviorTreeComponent.h" #include "BehaviorTree/BlackboardComponent.h" #include "Public/PikaMonsterAIController.h" void UPikaMonsterBTServiceFindTarget::InitializeFromAsset(UBehaviorTree & Asset) { Super::InitializeFromAsset(Asset); PikaIsStop = false; } void UPikaMonsterBTServiceFindTarget::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) { Super::TickNode(OwnerComp , NodeMemory , DeltaSeconds); UBehaviorTreeComponent & PikaBehaveiorTree = OwnerComp; APikaMonsterAIController * PikaMonsAIController = Cast<APikaMonsterAIController>(PikaBehaveiorTree.GetOwner()); UBlackboardComponent * PikaBlackBoard = OwnerComp.GetBlackboardComponent(); if (!PikaBlackBoard) { return; } if (PikaMonsAIController) { //目标塔为空时 if (!PikaTargetTower) { //寻找离自己最近的目标塔 PikaTargetTower = Cast<APikaCharacterBase>(PikaMonsAIController->PikaFindTarget()); //存储目标塔到黑板里 //PikaBlackBoard->SetValueAsObject(PikaBlackBoardKeyTarget.SelectedKeyName, PikaTargetTower); } else { //目标塔死亡后,重新寻找目标 if (PikaTargetTower->PikaCharDataPre->PikaCharBaseData.PikaDeath) { //PikaIsStop = false; PikaTargetTower = NULL; } } //存储目标塔到黑板里 PikaBlackBoard->SetValueAsObject(PikaBlackBoardKeyTarget.SelectedKeyName, PikaTargetTower); //实时获取距离 if (PikaTargetTower) { //AI自己的位置 FVector PikaLocation = PikaMonsAIController->GetPawn()->GetActorLocation(); FVector PikaDsitance = PikaLocation - PikaTargetTower->GetActorLocation(); PikaBlackBoard->SetValueAsFloat(PikaBlackBoardKeyDistance.SelectedKeyName, PikaDsitance.Size()); } } }
PikaToolRangeOfCharacter.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/SphereComponent.h" #include "Components/TimelineComponent.h" #include "PikaToolRangeOfCharacter.generated.h" UCLASS() class PIKAGODSTONE_API APikaToolRangeOfCharacter : public AActor { GENERATED_BODY() //碰撞盒子 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class USphereComponent * PikaBoxDamage; public: // Sets default values for this actor's properties APikaToolRangeOfCharacter(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; //碰撞 UFUNCTION() void PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); void PikaPrint(FString PikaStr); //范围攻击,该曲线由蓝图载入 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UCurveFloat * PikaCurveFloat; UPROPERTY() FTimeline PikaRangeAttackTimeLine; //范围攻击球体的半径 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") float PikaBoxDamageTargetRadius; UFUNCTION() void PikaTimeLineRangeAttack(float PikaValue); UFUNCTION() void PikaTimeLineFinished(); //发起者(怪物死亡后,将自身的经验添加到离自己最近的塔上) UPROPERTY() AActor * PikaCastCharacter; //将检测到的敌人加入到容器 TArray<AActor*> PikaCharacterArray; };
PikaToolRangeOfCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaToolRangeOfCharacter.h" #include "Engine/Engine.h" #include "Public/PikaCharacterBase.h" // Sets default values APikaToolRangeOfCharacter::APikaToolRangeOfCharacter() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; PikaBoxDamage = CreateDefaultSubobject<USphereComponent>(TEXT("PikaBoxDamage")); PikaBoxDamage->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); } // Called when the game starts or when spawned void APikaToolRangeOfCharacter::BeginPlay() { Super::BeginPlay(); //碰撞绑定 if (PikaBoxDamage) { PikaBoxDamage->OnComponentBeginOverlap.AddUniqueDynamic(this, &APikaToolRangeOfCharacter::PikaBeginOverlapping); } if (GetWorld()) { //曲线存在,通过代理绑定处理函数 if (PikaCurveFloat) { FOnTimelineFloat PikaTimeLineDelegate; FOnTimelineEvent PikaFinishedEvent; PikaFinishedEvent.BindUFunction(this, FName("PikaTimeLineFinished")); PikaTimeLineDelegate.BindUFunction(this, FName("PikaTimeLineRangeAttack")); //添加曲线 PikaRangeAttackTimeLine.AddInterpFloat(PikaCurveFloat, PikaTimeLineDelegate); //设置停止循环 PikaRangeAttackTimeLine.SetLooping(false); //开始播放 PikaRangeAttackTimeLine.PlayFromStart(); //TimeLine结束时触发的事件 PikaRangeAttackTimeLine.SetTimelineFinishedFunc(PikaFinishedEvent); } } } // Called every frame void APikaToolRangeOfCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (PikaCurveFloat) { PikaRangeAttackTimeLine.TickTimeline(DeltaTime); } } void APikaToolRangeOfCharacter::PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { if (!OtherActor || !PikaCastCharacter) { return; } APikaCharacterBase * PikaTargetActor = Cast<APikaCharacterBase>(OtherActor); APikaCharacterBase * PikaCasterActor = Cast<APikaCharacterBase>(PikaCastCharacter); if (PikaTargetActor && PikaCasterActor) { if (PikaTargetActor->PikaIsActive() && (PikaTargetActor->PikaGetTeam() == PikaCasterActor->PikaGetTeam())) { PikaCharacterArray.AddUnique(PikaTargetActor); } } } void APikaToolRangeOfCharacter::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.f, FColor::Red, PikaStr); } } void APikaToolRangeOfCharacter::PikaTimeLineRangeAttack(float PikaValue) { float PikaBoxDamageCurentRadius = FMath::Lerp(PikaBoxDamage->GetScaledSphereRadius(), PikaBoxDamageTargetRadius, PikaValue); PikaBoxDamage->SetSphereRadius(PikaBoxDamageCurentRadius); } void APikaToolRangeOfCharacter::PikaTimeLineFinished() { APikaCharacterBase * PikaCasterActor = Cast<APikaCharacterBase>(PikaCastCharacter); if (PikaCasterActor) { PikaCasterActor->PikaUpdateLevelCharacterArray(PikaCharacterArray); } Destroy(true); }
PikaTowerAIController.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "AIController.h" #include "PikaTowerAIController.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaTowerAIController : public AAIController { GENERATED_BODY() };
PikaTowerAIController.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaTowerAIController.h"
PikaTowerDoll.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/StaticMeshComponent.h" #include "Components/SphereComponent.h" #include "Materials/MaterialInstanceDynamic.h" #include "PikaTowerDoll.generated.h" class APikaGodStonePlayerController; //记录空间信息 USTRUCT() struct FPikaComponentSpaceInfo { GENERATED_BODY() public: UPROPERTY() TArray<FVector> PikaComponentSize; UPROPERTY() TArray<FVector> PikaComponentLocation; UPROPERTY() TArray<FRotator> PikaComponentRotation; FPikaComponentSpaceInfo() { PikaComponentSize.Empty(); PikaComponentLocation.Empty(); PikaComponentRotation.Empty(); } FPikaComponentSpaceInfo& operator=(const FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { PikaComponentSize = MyPikaComponentSpaceInfo.PikaComponentSize; PikaComponentLocation = MyPikaComponentSpaceInfo.PikaComponentLocation; PikaComponentRotation = MyPikaComponentSpaceInfo.PikaComponentRotation; return *this; } //判断该序列号是不是在该容器内有效 bool PikaIsValuable(int32 ID) { return (PikaComponentLocation.IsValidIndex(ID) && PikaComponentSize.IsValidIndex(ID) && PikaComponentRotation.IsValidIndex(ID)) ? true : false; } //获取FComponentSpaceInformation最大的数量 //获取PikaComponentLocation.Num()、PikaComponentSize.Num()、PikaComponentLocation.Num()里的最大值 int32 PikaGetMax() { return(PikaComponentLocation.Num() >= PikaComponentSize.Num() ? PikaComponentLocation.Num() : PikaComponentSize.Num()) >= PikaComponentRotation.Num() ? (PikaComponentLocation.Num() >= PikaComponentSize.Num() ? PikaComponentLocation.Num() : PikaComponentSize.Num()) : PikaComponentRotation.Num(); } }; UCLASS() class PIKAGODSTONE_API APikaTowerDoll : public AActor { GENERATED_BODY() UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttrubte", meta = (AllowPrivateAccess = "true")) class USceneComponent * PikaHomingPoint; //运行建造范围检测 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttrubte", meta = (AllowPrivateAccess = "true")) class USphereComponent * PikaAllowBuildRange; //StaticMeshComponent组件集 TArray<UStaticMeshComponent*> PikaMeshComponentArray; //StaticMeshComponent基础材质集 TArray<UMaterialInstanceDynamic*> PikaTowerDollAllMatrial; //指向Doll材质的指针 UMaterialInterface* PikaTowerDollMaterial; //本地的游戏控制 APikaGodStonePlayerController* PikaLocalPlayerController; public: // Sets default values for this actor's properties APikaTowerDoll(); //将mesh添加到我们的MeshComponents中 void PikaSetMeshAddToMeshComponet(TArray<UStaticMesh*> MyMesh , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo); void PikaSetMeshColor(bool PermitConstruction); virtual void Destroyed() override; void PikaSetController(APikaGodStonePlayerController* OurPlayerController) { PikaLocalPlayerController = OurPlayerController; } //测试打印函数 void PikaPrint(FString PikaStr); //碰撞 UFUNCTION() void PikaDollAllowBuildBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); UFUNCTION() void PikaDollAllowBuildEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; APikaGodStonePlayerController* PikaGetTowerDefencePlayerController() { return PikaLocalPlayerController; } public: // Called every frame virtual void Tick(float DeltaTime) override; private: //初始化MeshComponent数量 void PikaSetMeshComponentSize(int32 ComponentNumber , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo); };
PikaTowerDoll.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaTowerDoll.h" #include "ConstructorHelpers.h" #include "Components/BoxComponent.h" // Sets default values APikaTowerDoll::APikaTowerDoll() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; static ConstructorHelpers::FObjectFinder<UMaterialInterface> PikaMyMaterial = (TEXT("/Game/TowerAI/TowerDollMat/MAT_TowersDoll")); PikaTowerDollMaterial = PikaMyMaterial.Object; PikaHomingPoint = CreateDefaultSubobject<USceneComponent>(TEXT("PikaTowerDollHominPoint")); PikaAllowBuildRange = CreateDefaultSubobject<USphereComponent>(TEXT("PikaTowerAllowBuildRange")); if (PikaHomingPoint && PikaAllowBuildRange) { RootComponent = PikaHomingPoint; PikaAllowBuildRange->AttachToComponent(PikaHomingPoint, FAttachmentTransformRules::KeepRelativeTransform); //设置通道类型,名字为DefaultEngine.ini文件里通道的Name="PikaAllowBuild" PikaAllowBuildRange->SetCollisionProfileName("PikaAllowBuild"); PikaAllowBuildRange->SetSphereRadius(250.0f); PikaAllowBuildRange->SetHiddenInGame(true); } } //获取Mesh的数量 void APikaTowerDoll::PikaSetMeshComponentSize(int32 ComponentNumber , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { if (PikaHomingPoint) { for (int32 i = 0; i < ComponentNumber; i++) { FString PikaStaticMeshComponentName = "Mesh_" + FString::FromInt(i); UStaticMeshComponent* PikaMyMeshComponent = NewObject<UStaticMeshComponent>(this , *PikaStaticMeshComponentName); if (PikaMyMeshComponent && MyPikaComponentSpaceInfo.PikaIsValuable(i)) { PikaMyMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); PikaMyMeshComponent->SetRelativeLocation(MyPikaComponentSpaceInfo.PikaComponentLocation[i]); PikaMyMeshComponent->SetRelativeRotation(MyPikaComponentSpaceInfo.PikaComponentRotation[i]); PikaMyMeshComponent->SetRelativeScale3D(MyPikaComponentSpaceInfo.PikaComponentSize[i]); PikaMyMeshComponent->AttachToComponent(PikaHomingPoint, FAttachmentTransformRules::KeepRelativeTransform); PikaMeshComponentArray.Add(PikaMyMeshComponent); //注册组件 PikaMyMeshComponent->RegisterComponent(); } } } } void APikaTowerDoll::PikaSetMeshAddToMeshComponet(TArray<UStaticMesh*> MyMesh , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { PikaSetMeshComponentSize(MyMesh.Num() , MyPikaComponentSpaceInfo); int32 i = 0; TArray<UMaterialInterface*> PikaTempMaterialInterfaceArray; if (PikaTowerDollMaterial) { for (UStaticMesh* SimMesh : MyMesh) { if(PikaMeshComponentArray[i]) PikaMeshComponentArray[i]->SetStaticMesh(SimMesh); //替换成我们自己的材质 for (int32 MatIndex = 0 ; MatIndex < PikaMeshComponentArray[i]->GetNumMaterials() ; MatIndex++) { PikaMeshComponentArray[i]->SetMaterial(MatIndex , PikaTowerDollMaterial); } //获取所有材质 for (int32 MeshIndex = 0 ; MeshIndex < PikaMeshComponentArray[i]->GetMaterials().Num(); MeshIndex++) { UMaterialInstanceDynamic* PikaMID = PikaMeshComponentArray[i]->CreateAndSetMaterialInstanceDynamic(MeshIndex); if (PikaMID) PikaTowerDollAllMatrial.Add(PikaMID); } i++; } } } void APikaTowerDoll::PikaSetMeshColor(bool PermitConstruction) { if (PermitConstruction) { for (UMaterialInstanceDynamic* PikaMyDynamicMat : PikaTowerDollAllMatrial) { FString test1 = PikaMyDynamicMat->GetName(); if (PikaMyDynamicMat->GetName() != "None" && PikaMyDynamicMat->GetName() != "Invalid") //显示绿色,ColorStatus为TowerAI下MAT_TowersDoll材质里,节点参数化后的变量名 PikaMyDynamicMat->SetScalarParameterValue("ColorStatus" , 0); } } else { for (UMaterialInstanceDynamic* PikaMyDynamicMat : PikaTowerDollAllMatrial) { if (PikaMyDynamicMat->GetName() != "None" && PikaMyDynamicMat->GetName() != "Invalid") //显示红色,ColorStatus为TowerAI下MAT_TowersDoll材质里,节点参数化后的变量名 PikaMyDynamicMat->SetScalarParameterValue("ColorStatus", 1); } } } void APikaTowerDoll::Destroyed() { for (UStaticMeshComponent* MyStaticMeshComponent : PikaMeshComponentArray) { if (MyStaticMeshComponent) MyStaticMeshComponent->DestroyComponent(true); MyStaticMeshComponent = NULL; } if (PikaTowerDollMaterial) PikaTowerDollMaterial->ConditionalBeginDestroy(); PikaTowerDollMaterial = NULL; PikaAllowBuildRange->DestroyComponent(true); Super::Destroyed(); } void APikaTowerDoll::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.f, FColor::Red, PikaStr); } } void APikaTowerDoll::PikaDollAllowBuildBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { if (OtherComp->IsA(UBoxComponent::StaticClass()) && PikaGetTowerDefencePlayerController()) { if (OtherComp->GetCollisionObjectType() == ECollisionChannel::ECC_GameTraceChannel6) { PikaSetMeshColor(false); PikaGetTowerDefencePlayerController()->PikaSetAllowBuillingTowers(false); } } } void APikaTowerDoll::PikaDollAllowBuildEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex) { if (OtherComp->IsA(UBoxComponent::StaticClass()) && PikaGetTowerDefencePlayerController()) { if (OtherComp->GetCollisionObjectType() == ECollisionChannel::ECC_GameTraceChannel6) { PikaSetMeshColor(true); PikaGetTowerDefencePlayerController()->PikaSetAllowBuillingTowers(true); } } } // Called when the game starts or when spawned void APikaTowerDoll::BeginPlay() { Super::BeginPlay(); if (PikaAllowBuildRange) { PikaAllowBuildRange->OnComponentBeginOverlap.AddUniqueDynamic(this, &APikaTowerDoll::PikaDollAllowBuildBeginOverlapping); PikaAllowBuildRange->OnComponentEndOverlap.AddUniqueDynamic(this, &APikaTowerDoll::PikaDollAllowBuildEndOverlapping); } } // Called every frame void APikaTowerDoll::Tick(float DeltaTime) { Super::Tick(DeltaTime); }
PikaTowerIcon.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "Public/PikaUI_InventorySlot.h" #include "PikaTowerIcon.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaTowerIcon : public UPikaUIWidgetBase { GENERATED_BODY() //控件实例的名字 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerImageName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCDImageName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerPrepareBuildingNumTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCompletionNumTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCDValueTextName; //CD材质的名字,该值为CD材质里参数化的变量ControllerCD UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCDMatName; public: void PikaInitTowreIcon(UTexture2D* TowresIcon); //相当于BeginPlay,用于解决BeginPlay执行时,有些资源可能还没加载完成的问题 //需要手动调用 virtual void PikaDrawUIToScreen() override; //每一个物品栏对应的单个数据 FPikaBulidingTowres PikaBuildingTowerStructIcon; //打印测试 void PikaPrint(FString piksStr); private: //控件实例 UImage* PikaTowerImage; UImage* PikaTowerCDImage; UTextBlock* PikaTowerPrepareBuildingNumText; UTextBlock* PikaTowerCompletionNumText; UTextBlock* PikaTowerCDValueText; //显示字体和CD void PikaDisplayNumber(UTextBlock* MyTextNumberBlock, int32 MyTextNumber); };
PikaTowerIcon.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaTowerIcon.h" void UPikaTowerIcon::PikaInitTowreIcon(UTexture2D* TowresIcon) { if (PikaTowerImage && TowresIcon) { PikaTowerImage->SetBrushFromTexture(TowresIcon); PikaTowerImage->SetVisibility(ESlateVisibility::Visible); } } void UPikaTowerIcon::PikaDrawUIToScreen() { PikaTowerImage = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowerImageName)); PikaTowerCDImage = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowerCDImageName)); PikaTowerPrepareBuildingNumText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerPrepareBuildingNumTextName)); PikaTowerCompletionNumText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerCompletionNumTextName)); PikaTowerCDValueText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerCDValueTextName)); //获取动态材质实例 if (PikaTowerCDImage) { UMaterialInstanceDynamic* PikaCDMaterialDynamic = PikaTowerCDImage->GetDynamicMaterial(); if (PikaCDMaterialDynamic) PikaCDMaterialDynamic->SetScalarParameterValue(PikaCDMatName, PikaBuildingTowerStructIcon.PikaGetTowerConstructionTimePercentage()); } //填充PikaTowerImage PikaInitTowreIcon(PikaBuildingTowerStructIcon.PikaTexture); //填充PikaTowerPrepareBuildingNumText if (PikaTowerPrepareBuildingNumText) PikaDisplayNumber(PikaTowerPrepareBuildingNumText , PikaBuildingTowerStructIcon.PikaTowerPerpareBuildingNumber); //填充PikaTowerCompletionNumText if (PikaTowerCompletionNumText) PikaDisplayNumber(PikaTowerCompletionNumText, PikaBuildingTowerStructIcon.PikaTowerConstructionNumber); //填充PikaTowerPrepareBuildingNumText if (PikaTowerCDValueText) PikaDisplayNumber(PikaTowerCDValueText, PikaBuildingTowerStructIcon.PikaCurrentConstructionTowerCD); } void UPikaTowerIcon::PikaPrint(FString piksStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr); } } void UPikaTowerIcon::PikaDisplayNumber(UTextBlock* MyTextNumberBlock, int32 MyTextNumber) { //物品栏上有道显示文本,没有道具则不显示文本 if (MyTextNumber < 1 || !PikaBuildingTowerStructIcon.PikaIsActive()) { MyTextNumberBlock->SetVisibility(ESlateVisibility::Hidden); } else { //格式输出里,%02d表示输出格式为00,%03d的输出格式为000 MyTextNumberBlock->SetText(FText::FromString(FString::Printf(TEXT("%02d"), MyTextNumber))); MyTextNumberBlock->SetVisibility(ESlateVisibility::Visible); } }
PikaTowers.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaCharacterBase.h" #include "PikaBulletBase.h" #include "Components/SphereComponent.h" #include "PikaTowers.generated.h" //塔类型 UENUM() namespace EPikaTowersType { enum Type { PikaTOWERS_Towers, PikaTOWERS_MainTowers, PikaTOWERS_Max }; } /** * */ UCLASS() class PIKAGODSTONE_API APikaTowers : public APikaCharacterBase { GENERATED_BODY() //Box组件,用于设置产生碰撞的Box UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttack" , meta = (AllowPrivateAccess = "true")) class UBoxComponent * PikaBoxCollision; //Box组件,用于允许建设的设置 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttack", meta = (AllowPrivateAccess = "true")) class UBoxComponent * PikaAllowBuildBox; //怪物数组 UPROPERTY() TArray<APikaMonster*> PikaTarrayMonster; //塔类型 UPROPERTY(EditDefaultsOnly, Category = "PikaTowerType") TEnumAsByte<EPikaTowersType::Type> PikaTowersType; //攻击范围 UPROPERTY(EditDefaultsOnly, Category = "PikaTowerType") float PikaAattakRange; //被动技能范围 UPROPERTY(EditDefaultsOnly, Category = "PikaTowerType") float PikaPassiveSkillRange; public: APikaTowers(); virtual void BeginPlay() override; virtual void Tick(float DeltaTime) override; //塔攻击逻辑 virtual void PikaAttackTarget(AActor * Target) override; /******************攻击前摇start*********************/ //攻击前摇时间 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PikaAttackFront") float PikaAttackFrontDelayTimeBP; //攻击前摇时间句柄 UPROPERTY() FTimerHandle PikaAttackFrontDelayTimeHandle; void PikaAttackType(); /******************攻击前摇end**********************/ //塔的持续性攻击,由定时器来模拟Tick //virtual void PikaAttackTick() override; //攻击时间句柄 FTimerHandle PikaAttackHandle; //链击的时间句柄 FTimerHandle PikaChainHandle; float PikaChainSave; //是否停止攻击检测 bool PikaStopAttackCheck; //子弹 APikaBulletBase * PikaMyBullet; //闪电攻击时,获取敌人的位置 bool PikaCheckAttackTick; //闪电攻击时,目标位置纠正 virtual void PiakGetParticlePostionCheckAttackTick(); APikaCharacterBase * PikaGetTargetActor(); //碰撞 UFUNCTION() void PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); UFUNCTION() void PikaEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex); //碰撞 UFUNCTION() void PikaAllowBuildBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); UFUNCTION() void PikaAllowBuildEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex); //防止碰撞多次触发 AActor * PikaLastActor; //链击伤害 void PikaChainDamage(); //塔死亡函数 virtual void PikaDestoryCharacter(float DelayTime = 0) override; //获取塔类型 FORCEINLINE EPikaTowersType::Type PikaGetTowersType() { return PikaTowersType; } /**********和范围相关Start**********/ //获取攻击范围内的敌人 void PikaBTServiceGetTarget(); //获取范围内的同伴 TArray<APikaTowers*> PikaBTServiceGetCompanion(); /**********和范围相关End**********/ /**********角色TickStart**********/ //攻击检测 virtual void PikaAttackTick() override; //被动技能 //void PikaPassiveSkill(float DeltaTime); /**********角色TickEnd**********/ //当前的时间 float PikaTimeSet; //当前攻击记时 float PikaCurrentAttackCountTime; };
PikaTowers.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaTowers.h" #include "Public/PikaMonster.h" #include "Kismet/GameplayStatics.h" #include "RotationMatrix.h" #include "EngineUtils.h" APikaTowers::APikaTowers() { PikaBoxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaBoxCollision")); PikaAllowBuildBox = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaAllowBuildBox")); if (PikaBoxCollision && PikaAllowBuildBox) { PikaBoxCollision->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaAllowBuildBox->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaAllowBuildBox->SetCollisionProfileName("PikaAllowBuild"); } //是否停止攻击检测 PikaStopAttackCheck = false; PikaMyBullet = NULL; PikaCheckAttackTick = false; //怪物数组初始化 PikaTarrayMonster.Empty(); PikaLastActor = nullptr; PikaChainSave = 0; //塔的攻击范围 PikaAattakRange = 820; //被动技能范围 PikaPassiveSkillRange = 1000.f; PikaTimeSet = 0; PikaAttackFrontDelayTimeBP = 0.1f; } void APikaTowers::BeginPlay() { Super::BeginPlay(); //将塔的Team设置为true,初始化时为false if(PikaCharDataPre) PikaCharDataPre->PikaCharBaseData.PikaTeam = true; } void APikaTowers::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (PikaEnemyTarget && PikaMyBullet && PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Chain) { //子弹攻击的目标 //PikaMyBullet->GetParticleMesh()->SetBeamTargetPoint(0, PikaEnemyTarget->GetActorLocation(), 0); APikaCharacterBase * PikaMyTarget = (APikaCharacterBase*)PikaEnemyTarget; if (PikaMyTarget) { PikaMyBullet->GetParticleMesh()->SetBeamTargetPoint(0 , PikaMyTarget->GetHomingPoint()->GetComponentLocation() , 0); } } //开始检测范围内周围敌人 if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGlobalConfigPre) { if (PikaTimeSet <= PikaGetPlayerController()->PikaGlobalConfigPre->PikaTowersData.PikaTimeInterval) { PikaTimeSet += DeltaTime; } else { PikaTimeSet = 0; //获取攻击范围内的敌人 PikaBTServiceGetTarget(); } } if (PikaCharDataPre) { //开始攻击 if (PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed != 0) { PikaCurrentAttackCountTime += DeltaTime; //攻击间隔 float PikaCurrentAttackIntervalTime = 1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed; //当前攻击时间如果大于攻击间隔,则开始攻击,并清空当前攻击时间 if (PikaCurrentAttackCountTime >= PikaCurrentAttackIntervalTime) { PikaCurrentAttackCountTime = 0; PikaAttackTick(); } } /*//开始被动技能 if (CurrentPassiveTime <= PASSIVE_SKILL_MAX_TIME) { CurrentPassiveTime += DeltaTime; } else { PassiveSkill(CurrentPassiveTime); CurrentPassiveTime = 0.f; }*/ } } void APikaTowers::PikaAttackTarget(AActor * Target) { Super::PikaAttackTarget(Target); //攻击动画 PikaCharacterMontage_Play(PikaCharacterAttackSkillMontage); //攻击前摇 if (GetWorld()) GetWorld()->GetTimerManager().SetTimer(PikaAttackFrontDelayTimeHandle , this , &APikaTowers::PikaAttackType , PikaAttackFrontDelayTimeBP); } void APikaTowers::PikaAttackType() { if (PikaAttackFrontDelayTimeHandle.IsValid()) GetWorld()->GetTimerManager().ClearTimer(PikaAttackFrontDelayTimeHandle); APikaCharacterBase * PikaEnemyTargetBase = (APikaCharacterBase *)PikaEnemyTarget; if (PikaCharacterBullet && GetWorld() && GetSpawnPoint() && PikaIsActive()) { FVector PikaBulletLocation = GetSpawnPoint()->GetComponentLocation(); //FRotator PikaBuletRotator = GetSpawnPoint()->GetComponentRotation(); //销毁上一次的子弹 /*if (PikaMyBullet) { PikaMyBullet->Destroy(true); PikaMyBullet = NULL; }*/ PikaMyBullet = GetWorld()->SpawnActor<APikaBulletBase>(PikaCharacterBullet, PikaBulletLocation, FRotationMatrix::MakeFromX(PikaEnemyTargetBase->GetHomingPoint()->GetComponentLocation() - PikaBulletLocation).Rotator()); if (PikaMyBullet) { //将自己赋值到子弹的施法者里 PikaMyBullet->PikaSetCasterCharacter(this); //跟踪子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Track) { APikaCharacterBase * PikaMyTarget = (APikaCharacterBase*)PikaEnemyTarget; if (PikaMyTarget) { //跟踪加速度大小 PikaMyBullet->GetProjectleMovment()->HomingAccelerationMagnitude = 4000.f; //跟踪组件 PikaMyBullet->GetProjectleMovment()->HomingTargetComponent = PikaMyTarget->GetHomingPoint(); //绑定伤害特效 /*if (PikaMyBullet->PikaDamageParticle) { UGameplayStatics::SpawnEmitterAttached(PikaMyBullet->PikaDamageParticle, PikaMyTarget->GetHomingPoint()); }*/ } return; } //直线飞行子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Line) { return; } //范围攻击型子弹 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Range) { //设置范围攻击的转向为0向量 //PikaMyBullet->SetActorRotation(FRotator::ZeroRotator); if (PikaMyBullet->GetParticleMesh()) { PikaMyBullet->GetParticleMesh()->SetWorldRotation(FRotator::ZeroRotator); } return; } //闪电型攻击 if (PikaMyBullet->PikaBulletTypeBP == PikaBulletType::PikaBULLET_Chain) { //SetBeamSourcePoint函数里,第一个参数为粒子系统发射器的index,第三个参数为源index if (PikaMyBullet->GetParticleMesh()) { //设置闪电攻击的初始点,目标点写在Tick里 PikaMyBullet->GetParticleMesh()->SetBeamSourcePoint(0, PikaBulletLocation, 0); //绑定伤害特效 if (PikaMyBullet->PikaDamageParticle && PikaEnemyTargetBase) { UGameplayStatics::SpawnEmitterAttached(PikaMyBullet->PikaDamageParticle, PikaEnemyTargetBase->GetHomingPoint()); //0.01表示即时执行该函数,如果换成1/攻击速度,特效上会有延迟 //持续费血 GetWorld()->GetTimerManager().SetTimer(PikaChainHandle, this, &APikaTowers::PikaChainDamage, 0.01, true); } } return; } } } } //连续攻击 /*void APikaTowers::PikaAttackTick() { Super::PikaAttackTick(); if (PikaAttackHandle.IsValid()) { //清除时间句柄 GetWorld()->GetTimerManager().ClearTimer(PikaAttackHandle); //关闭Tick里的检测 PikaCheckAttackTick = false; } //自身如果已经死亡,则返回空 if (!PikaIsActive()) { return; } //诊断攻击的目标是否死亡 if (PikaEnemyTarget) { APikaCharacterBase * PikaIsDeathTarget = (APikaCharacterBase*)PikaEnemyTarget; if (PikaIsDeathTarget && PikaIsDeathTarget->PikaCharDataPre->PikaCharBaseData.PikaDeath) { //目标已死亡,移除死亡目标,并获取新的目标 PikaTarrayMonster.Remove(PikaIsDeathTarget); PikaEnemyTarget = PikaGetTargetActor(); } } //是否停止检测攻击 //if (PikaStopAttackCheck) { return; } //没有敌对目标时停止检测 if (!PikaEnemyTarget) { //正在攻击的目标为null,但目标数组里还有值时,重新获取新的攻击目标 if (PikaTarrayMonster.Num() > 0) { PikaEnemyTarget = PikaGetTargetActor(); } else { return; } } if (PikaEnemyTarget) { //有敌对目标,进行攻击 PikaCheckAttackTick = true; PikaAttackTarget(PikaEnemyTarget); } if (GetWorld()) { float PikaAttackSpeedTime = 1 / (PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed); GetWorld()->GetTimerManager().SetTimer(PikaAttackHandle, this, &APikaTowers::PikaAttackTick, PikaAttackSpeedTime, true); } }*/ void APikaTowers::PiakGetParticlePostionCheckAttackTick() { } APikaCharacterBase * APikaTowers::PikaGetTargetActor() { if (PikaTarrayMonster.Num() > 0) { if (1 == PikaTarrayMonster.Num()) { return PikaTarrayMonster[0]; } else { //返回多个目标中离自己最近的目标 int32 PikaMonsterIndex = -1; FVector PikaMyLocation = GetActorLocation(); float PikaMyDistance = 999999999999; for (int32 i=0 ; i< PikaTarrayMonster.Num(); i++) { FVector PikaMonsterLocation = PikaTarrayMonster[i]->GetActorLocation(); FVector PikaTempDistance = PikaMonsterLocation - PikaMyLocation; if (PikaTempDistance.Size() < PikaMyDistance) { PikaMyDistance = PikaTempDistance.Size(); PikaMonsterIndex = i; } } if (PikaMonsterIndex < 0) { return NULL; } else { return PikaTarrayMonster[PikaMonsterIndex]; } } } return NULL; } void APikaTowers::PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { /*if (PikaLastActor == OtherActor) { PikaLastActor = nullptr; return; }*/ //触发碰撞事件的对象是否为APikaMonster类的实例 /*if (OtherActor->IsA(APikaMonster::StaticClass())) { APikaCharacterBase * PikaTempActor = (APikaCharacterBase*)OtherActor; //添加入侵攻击范围内的敌对目标 if (PikaTempActor) { if (PikaTempActor->PikaIsActive()) { PikaTarrayMonster.AddUnique(PikaTempActor); } //进入攻击范围的目标,每增加一个就进行一次查找当前离自己最近目标的逻辑 //诊断攻击的目标是否死亡 if (PikaEnemyTarget) { APikaCharacterBase * PikaIsDeathTarget = (APikaCharacterBase*)PikaEnemyTarget; if (PikaIsDeathTarget && PikaIsDeathTarget->PikaCharDataPre->PikaCharBaseData.PikaDeath) { //目标已死亡,移除死亡目标,并获取新的目标 PikaTarrayMonster.Remove(PikaIsDeathTarget); PikaEnemyTarget = PikaGetTargetActor(); } } else { PikaEnemyTarget = PikaGetTargetActor(); } //PikaLastActor = OtherActor; PikaAttackTick(); } }*/ } void APikaTowers::PikaEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex) { /*if (OtherActor->IsA(APikaMonster::StaticClass())) { APikaCharacterBase * PikaTempActor = Cast<APikaCharacterBase>(OtherActor); //移除入侵攻击范围内的敌对目标 if (PikaTempActor) { PikaTarrayMonster.Remove(PikaTempActor); //当前的攻击目标离开了攻击范围时,将当前攻击目标的值置为NULL if (PikaEnemyTarget == PikaTempActor) { PikaEnemyTarget = NULL; } } }*/ } void APikaTowers::PikaAllowBuildBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { } void APikaTowers::PikaAllowBuildEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex) { } void APikaTowers::PikaChainDamage() { if (!GetWorld()) { return; } if (PikaChainHandle.IsValid()) { GetWorld()->GetTimerManager().ClearTimer(PikaChainHandle); } float PikaTempFloat = (1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed) * 0.2; //PikaChainSave += (PikaTempFloat + 0.1); //攻击修正 PikaChainSave += ((1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed)*0.2 + 0.1*(1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed) / (1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeedMin)); if (PikaEnemyTarget) { APikaCharacterBase * EnemyTarget = Cast<APikaCharacterBase>(PikaEnemyTarget); if (EnemyTarget) { //0.2表示将伤害分割成5次,1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed*0.2 EnemyTarget->PikaGetCharacterState(EnemyTarget->PikaGetDefenceDamage(this) * 0.2); EnemyTarget->PikaUpdateUMGHealth(); } } if (PikaChainSave < (1 / PikaCharDataPre->PikaCharBaseData.PikaAttackSpeed)) { GetWorld()->GetTimerManager().SetTimer(PikaChainHandle, this, &APikaTowers::PikaChainDamage, PikaTempFloat, 1); } else { PikaChainSave = 0; } } void APikaTowers::PikaDestoryCharacter(float DelayTime) { //上传死亡的数据 if (PikaGetPlayerController()) PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaTowersDeathNumber++; Super::PikaDestoryCharacter(DelayTime); } //获取攻击范围内的敌人 void APikaTowers::PikaBTServiceGetTarget() { PikaTarrayMonster.Empty(); //获取我们全场景的ARuleOfTheCharacter的Actor for (TActorIterator<APikaMonster>it(GetWorld(), APikaMonster::StaticClass()); it; ++it) { APikaMonster* PikaTheCharacter = *it; if (PikaTheCharacter) { if (PikaTheCharacter->PikaIsActive()) { FVector PikaTDistance = PikaTheCharacter->GetActorLocation() - GetActorLocation(); if (PikaTDistance.Size() <= PikaAattakRange) PikaTarrayMonster.AddUnique(PikaTheCharacter); } } } } //获取范围内的同伴 TArray<APikaTowers*> APikaTowers::PikaBTServiceGetCompanion() { TArray<APikaTowers*> PikaTArrayATowers; //获取我们全场景的ARuleOfTheCharacter的Actor for (TActorIterator<APikaTowers>it(GetWorld(), APikaTowers::StaticClass()); it; ++it) { APikaTowers* PikaTheCharacter = *it; if (PikaTheCharacter && PikaTheCharacter != this) { if (PikaTheCharacter->PikaIsActive()) { FVector PikaTDistance = PikaTheCharacter->GetActorLocation() - GetActorLocation(); if (PikaTDistance.Size() <= PikaPassiveSkillRange) PikaTArrayATowers.Add(PikaTheCharacter); } } } return PikaTArrayATowers; } //攻击检测 void APikaTowers::PikaAttackTick() { Super::PikaAttackTick(); //关闭检测 PikaCheckAttackTick = false; //自己是否死亡 if (!PikaIsActive()) { return; } //检测玩家设定的目标敌人 if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGetTargetMonster()) { for (APikaMonster* PikaTargetMonsters : PikaTarrayMonster) { if (PikaTargetMonsters->PikaIsActive()) { if (PikaGetPlayerController()->PikaGetTargetMonster() == PikaTargetMonsters) { PikaEnemyTarget = PikaGetPlayerController()->PikaGetTargetMonster(); break; } } else if (PikaTargetMonsters == PikaEnemyTarget) { PikaEnemyTarget = nullptr; } } } //检查怪物是否死亡 if (PikaEnemyTarget) { //判断该角色是否在范围内 if ((PikaEnemyTarget->GetActorLocation() - GetActorLocation()).Size() > PikaAattakRange) { //重新确定目标 PikaEnemyTarget = PikaGetTargetActor(); } else { APikaMonster* PikaEnemyTargetPtr = Cast<APikaMonster>(PikaEnemyTarget); if (PikaEnemyTargetPtr) { if (!PikaEnemyTargetPtr->PikaIsActive()) { //移除目标死亡的怪物 PikaTarrayMonster.Remove(PikaEnemyTargetPtr); //重新搜索怪物 PikaEnemyTarget = PikaGetTargetActor(); } } } } else { //重新获取目标 PikaEnemyTarget = PikaGetTargetActor(); } //有没有目标 if (PikaEnemyTarget) { //攻击目标 PikaAttackTarget(PikaEnemyTarget); } }
PikaUI_InformationWeight.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "PikaUI_InformationWeight.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUI_InformationWeight : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaHealthTextBlockName; public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen() override; void PikaDrawSubtractionHealthInformation(float DamageValue, float DamagePercentage); void PikaDrawGoldformation(int32 GlodValue, float DamagePercentage); void PikaDrawAddHealthInformation(float AddHealthValue, float DamagePercentage); private: UTextBlock* PikaHealthTextBlock; };
PikaUI_InformationWeight.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUI_InformationWeight.h" void UPikaUI_InformationWeight::PikaDrawUIToScreen() { PikaHealthTextBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaHealthTextBlockName)); } void UPikaUI_InformationWeight::PikaDrawSubtractionHealthInformation(float DamageValue, float DamagePercentage) { int32 PikaMaxFontSize = 50; int32 PikaMinFontSize = 16; int32 PikaCurrentFontSize = PikaMinFontSize + (PikaMaxFontSize - PikaMinFontSize) * DamagePercentage; if (PikaHealthTextBlock && DamageValue != 0) { PikaHealthTextBlock->SetText(FText::FromString(FString::Printf(TEXT("-%0.f"), DamageValue))); PikaHealthTextBlock->Font.Size = PikaCurrentFontSize; //设置颜色为红色 PikaHealthTextBlock->SetColorAndOpacity(FSlateColor(FLinearColor::Red)); } } void UPikaUI_InformationWeight::PikaDrawGoldformation(int32 GlodValue, float DamagePercentage) { int32 PikaMaxFontSize = 50; int32 PikaMinFontSize = 16; int32 PikaCurrentFontSize = PikaMinFontSize + (PikaMaxFontSize - PikaMinFontSize) * DamagePercentage; if (PikaHealthTextBlock) { PikaHealthTextBlock->SetText(FText::FromString(FString::Printf(TEXT("+%d"), GlodValue))); PikaHealthTextBlock->Font.Size = PikaCurrentFontSize; //设置颜色为黄色 PikaHealthTextBlock->SetColorAndOpacity(FSlateColor(FLinearColor::Yellow)); } } void UPikaUI_InformationWeight::PikaDrawAddHealthInformation(float AddHealthValue, float DamagePercentage) { int32 PikaMaxFontSize = 50; int32 PikaMinFontSize = 16; int32 PikaCurrentFontSize = PikaMinFontSize + (PikaMaxFontSize - PikaMinFontSize) * DamagePercentage; if (PikaHealthTextBlock && AddHealthValue != 0) { PikaHealthTextBlock->SetText(FText::FromString(FString::Printf(TEXT("+%0.f"), AddHealthValue))); PikaHealthTextBlock->Font.Size = PikaCurrentFontSize; //设置颜色为绿色 PikaHealthTextBlock->SetColorAndOpacity(FSlateColor(FLinearColor::Green)); } }
PikaUI_Inventory.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUI_InventorySlot.h" #include "UniformGridPanel.h" #include "UniformGridSlot.h" #include "PikaUI_Inventory.generated.h" class UPikaMainInterface; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUI_Inventory : public UPikaUIWidgetBase { GENERATED_BODY() //用来载入PikaUI_InventorySlot的蓝图类 UPROPERTY(EditDefaultsOnly , Category = "PikaUI") TSubclassOf<UPikaUI_InventorySlot> PikaInventorySlotClass; //从蓝图中获取soltArray的名字 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoltArrayInventoryName; public: virtual void PikaDrawUIToScreen() override; void PikaLayoutInventorySlot(int32 PikaColumn , int32 PikaRow); /*********************************响应控制Start***************************************/ //绑定我们的鼠标中键响应 //以下两个函数是通过代理绑定的,需要加UFUNCTIO() UFUNCTION() void PikaSpawnTowerDollPressed(APikaGodStonePlayerController* MyPlayerController); UFUNCTION() void PikaSpawnTowerDollReleased(APikaGodStonePlayerController* MyPlayerController); /*********************************响应控制End***************************************/ /*********************************临时InventorySlot变量Start***************************************/ UPikaUI_InventorySlot* GetTempInventorySlot()const; void PikaSetTempInventorySlot(UPikaUI_InventorySlot* NewInventorySlot); //将InventorySlot置空 void PikaCancelTempInventorySlot(); //获取PikaTempInventorySlot UPikaUI_InventorySlot* PikaGetNewInventorySlot()const { return PikaTempInventorySlot; } /*********************************临时InventorySlot变量End***************************************/ //打印测试 void PikaPrint(FString piksStr); //负责打印GameLOG virtual void PikaLogPrintf(FString MyString)override; UPikaMainInterface* PikaGetMainInterface() const { return PikaMainInterfacePtr; } void PikaSetMainInterface(UPikaMainInterface* NewWidget) {PikaMainInterfacePtr = NewWidget;} //锁CD void PikaLockSlotCD(bool IsLock); private: UUniformGridPanel * PikaSlotArrayInventory; TArray<UPikaUI_InventorySlot*> PikaInventorySlotArray; UPikaUI_InventorySlot* PikaTempInventorySlot; UPikaMainInterface* PikaMainInterfacePtr; };
PikaUI_Inventory.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUI_Inventory.h" #include "Public/PikaCharacterBase.h" #include "Engine/Engine.h" void UPikaUI_Inventory::PikaDrawUIToScreen() { if (!GetWorld()) { return; } PikaSlotArrayInventory = Cast<UUniformGridPanel>(PikaqiuGetBlueprintWidget(PikaSoltArrayInventoryName)); //布局界面 if (PikaUIDataPtr) { PikaLayoutInventorySlot(PikaUIDataPtr->PikaInventoryColumn , PikaUIDataPtr->PikaInventoryRow); } //绑定我们的鼠标中建响应 if (PikaGetPlayerController()) { PikaGetPlayerController()->PikaEventMouseMiddlePressed.AddDynamic(this , &UPikaUI_Inventory::PikaSpawnTowerDollPressed); PikaGetPlayerController()->PikaEventFMouseMiddleReleased.AddDynamic(this, &UPikaUI_Inventory::PikaSpawnTowerDollReleased); } } void UPikaUI_Inventory::PikaLayoutInventorySlot(int32 PikaColumn, int32 PikaRow) { if (PikaInventorySlotClass && PikaSlotArrayInventory) { for (int32 MyRow = 0 ; MyRow < PikaRow; MyRow++) { for (int32 MyColumn=0 ; MyColumn< PikaColumn; MyColumn++) { UPikaUI_InventorySlot * PikaSlotWidget = CreateWidget<UPikaUI_InventorySlot>(GetWorld() , PikaInventorySlotClass); if(PikaSlotWidget) { //需要将我们的UMG添加进去 UUniformGridSlot * PikaGridSlot = PikaSlotArrayInventory->AddChildToUniformGrid(PikaSlotWidget); if (PikaGridSlot) { PikaGridSlot->SetColumn(MyColumn); PikaGridSlot->SetRow(MyRow); PikaGridSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill); PikaGridSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill); } PikaSlotWidget->PikaDrawUIToScreen(); //设置父类 PikaSlotWidget->PikaSetParentClass(this); //添加到容器内 PikaInventorySlotArray.Add(PikaSlotWidget); } } } if (PikaGetPlayerController()) { TArray<UTexture2D*> PikaMyTextureArray = PikaGetPlayerController()->PikaGetTowerIocn(); //塔的建造CD TArray<float> PikaMyTowerCD = PikaGetPlayerController()->PikaGetBuildCD(); //建造塔所需的金币 TArray<int32> PikaMyGoldArray = PikaGetPlayerController()->PikaGetTowerComsumeGold(); //信息的注册 TArray<FName> PikaTowersNameArray = PikaGetPlayerController()->PikaGetTowersName(); TArray<FText> PikaTowersIntroductionArray = PikaGetPlayerController()->PikaGetTowersIntroduction(); TArray<float> PikaTowersAttackArray = PikaGetPlayerController()->PikaGetTowerData(EPikaCharacterInfoDataTableType::DATA_PikaCharacterAttack); TArray<float> PikaTowersArmorArray = PikaGetPlayerController()->PikaGetTowerData(EPikaCharacterInfoDataTableType::DATA_PikaCharacterArm); TArray<float> PikaTowersAttackSpeedArray = PikaGetPlayerController()->PikaGetTowerData(EPikaCharacterInfoDataTableType::DATA_PikaCharacterAttackSpeed); TArray<float> PikaTowersHealthArray = PikaGetPlayerController()->PikaGetTowerData(EPikaCharacterInfoDataTableType::DATA_PikaCharacterHealth); int32 i = 0; for (UTexture2D* MyTexture: PikaMyTextureArray) { if (PikaInventorySlotArray.IsValidIndex(i) && PikaMyTowerCD.IsValidIndex(i) && PikaMyGoldArray.IsValidIndex(i) && PikaTowersNameArray.IsValidIndex(i) && PikaTowersArmorArray.IsValidIndex(i) && PikaTowersAttackArray.IsValidIndex(i) && PikaTowersAttackSpeedArray.IsValidIndex(i) && PikaTowersHealthArray.IsValidIndex(i) && PikaTowersIntroductionArray.IsValidIndex(i)) { //备份 PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaTexture = MyTexture; //激活 PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaSetActive(true); //初始化物品栏图片 PikaInventorySlotArray[i]->PikaInitTowerIcon(); //初始化塔的建造时间 PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaMaxConstructionTowerCD = PikaMyTowerCD[i]; //消费金币更新 //PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaNeedGold = PikaMyGoldArray[i]; //注册信息 PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterName = PikaTowersNameArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterArmor = PikaTowersArmorArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterAttack = PikaTowersAttackArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterAttackSpeed = PikaTowersAttackSpeedArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterHealth = PikaTowersHealthArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaComsumeGlod = PikaMyGoldArray[i]; PikaInventorySlotArray[i]->PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterIntroduction = PikaTowersIntroductionArray[i]; //为读写存档做准备 if (1) { //注册,保存建造的数量信息 PikaGetSaveGameData()->PikaTowerConstructionNumber.Add(0); PikaGetSaveGameData()->PikaTowerPrepareBuildingNumber.Add(0); } else { } } i++; } } } } void UPikaUI_Inventory::PikaSpawnTowerDollPressed(APikaGodStonePlayerController* MyPlayerController) { if (MyPlayerController && PikaTempInventorySlot && PikaTempInventorySlot->PikaBuildingTowerStruct.PikaIsActive() && PikaTempInventorySlot->PikaGetTowersIcon()) { if (PikaTempInventorySlot->PikaBuildingTowerStruct.PikaTowerConstructionNumber >= 1) { //通过图标寻找对应塔的序列位置 int32 PikaTowersIndex = MyPlayerController->PikaGetTowerIocn().Find(PikaTempInventorySlot->PikaGetTowersIcon()->PikaqiuGetTexture2D()); APikaTowerDoll* PikaTowersDoll = MyPlayerController->PikaSpawnTowerDoll(PikaTowersIndex); } else PikaLogPrintf("At least one tower to complete!"); } } void UPikaUI_Inventory::PikaSpawnTowerDollReleased(APikaGodStonePlayerController* MyPlayerController) { if (MyPlayerController && MyPlayerController->PikaGetTowersDoll() && MyPlayerController->PikaGetAllowBuillingTowers()) { if (MyPlayerController->PikaGetTowersDoll()->GetActorLocation() != FVector::ZeroVector) { //通过图标寻找对应塔的序列位置 int32 PikaTowersIndex = MyPlayerController->PikaGetTowerIocn().Find(PikaTempInventorySlot->PikaGetTowersIcon()->PikaqiuGetTexture2D()); APikaCharacterBase* PikaTowersMesh = Cast<APikaCharacterBase>(MyPlayerController->PikaSpawnTowers(PikaTowersIndex, 1)); if (PikaTowersMesh) { PikaTowersMesh->SetActorLocation(MyPlayerController->PikaGetTowersDoll()->GetActorLocation()); PikaTowersMesh->SetActorRotation(MyPlayerController->PikaGetTowersDoll()->GetActorRotation()); //减去建造数量 PikaTempInventorySlot->PikaBuildingTowerStruct.PikaTowerConstructionNumber--; //上传到我们的存储 PikaTempInventorySlot->PikaUpdateTowerCompletionNumText(PikaTempInventorySlot->PikaBuildingTowerStruct.PikaTowerConstructionNumber); //上传我们的位置信息数据 if (MyPlayerController->PikaGlobalConfigPrePlayerCon) { int32 PikaCharacterIndex = MyPlayerController->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaGetCurrentCharacterSpawnIDIndex(PikaTowersMesh->PikaGetCharacterSpawnID()); if (MyPlayerController->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsActive(PikaCharacterIndex)) { MyPlayerController->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterLocation[PikaCharacterIndex] = PikaTowersMesh->GetActorLocation(); MyPlayerController->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterRotator[PikaCharacterIndex] = PikaTowersMesh->GetActorRotation(); } } PikaLogPrintf("Tower Success"); } } else PikaLogPrintf("Prohibition of construction in the region!"); //销毁 PikaCancelTempInventorySlot(); MyPlayerController->PikaDestoryTowerDoll(); } else { PikaLogPrintf("UPikaUI_Inventory::PikaSpawnTowerDollReleased Error"); PikaCancelTempInventorySlot(); MyPlayerController->PikaDestoryTowerDoll(); } } UPikaUI_InventorySlot* UPikaUI_Inventory::GetTempInventorySlot() const { return PikaTempInventorySlot; } void UPikaUI_Inventory::PikaSetTempInventorySlot(UPikaUI_InventorySlot* NewInventorySlot) { PikaTempInventorySlot = NewInventorySlot; } void UPikaUI_Inventory::PikaCancelTempInventorySlot() { if (PikaTempInventorySlot) PikaTempInventorySlot = NULL; } void UPikaUI_Inventory::PikaPrint(FString piksStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Red, piksStr); } } void UPikaUI_Inventory::PikaLogPrintf(FString MyString) { if (PikaGetMainInterface()) PikaGetMainInterface()->PikaLogPrintf(MyString); } void UPikaUI_Inventory::PikaLockSlotCD(bool IsLock) { for (UPikaUI_InventorySlot* InventorySlot_E : PikaInventorySlotArray) { if (IsLock) InventorySlot_E->PikaCDLock(); else InventorySlot_E->PikaUnCDLock(); } }
PikaUI_InventorySlot.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "Image.h" #include "TextBlock.h" #include "Widget.h" #include "PikaUI_InventorySlot.generated.h" //前向声明 class UPikaUI_Inventory; USTRUCT() struct FPikaBulidingTowres { GENERATED_BODY() //需要消费的金币 int32 PikaNeedGold; //准备阶段塔的建造数量 int32 PikaTowerPerpareBuildingNumber; //塔已经建造的数量 int32 PikaTowerConstructionNumber; //当前塔最大建造CD float PikaMaxConstructionTowerCD; //当前建造中塔的CD float PikaCurrentConstructionTowerCD; //是否更新塔的CD bool PikaIsUpdateTowerCD; //作为图片指针 UTexture2D* PikaTexture; //是否拖拽图标 bool PikaIsDragIco; //锁 bool PikaIsLockCD; FPikaBulidingTowres() { PikaInitBuildingTower(); } ~FPikaBulidingTowres() { if (PikaTexture) PikaTexture = NULL; } //获取当前建造时间与最大建造时间的百分比 float PikaGetTowerConstructionTimePercentage() { return PikaMaxConstructionTowerCD ? PikaCurrentConstructionTowerCD / PikaMaxConstructionTowerCD : 0 ; } //重置CD void PikaSetCurrentCD() { PikaCurrentConstructionTowerCD = PikaMaxConstructionTowerCD; } //设置激活状态 void PikaSetActive(bool DeathInformation) { PikaIsSlotActive = DeathInformation; } //判断物品栏是否激活 bool PikaIsActive() const { return PikaIsSlotActive; } //存储角色信息 FPikaCharacterInformationWidget PikaCharacterInformationWidget; //重载操作符 FPikaBulidingTowres& operator = (const FPikaBulidingTowres& StructBuildingTower) { PikaNeedGold = StructBuildingTower.PikaNeedGold; PikaTowerPerpareBuildingNumber = StructBuildingTower.PikaTowerPerpareBuildingNumber; PikaTowerConstructionNumber = StructBuildingTower.PikaTowerConstructionNumber; PikaMaxConstructionTowerCD = StructBuildingTower.PikaMaxConstructionTowerCD; PikaCurrentConstructionTowerCD = StructBuildingTower.PikaCurrentConstructionTowerCD; PikaIsUpdateTowerCD = StructBuildingTower.PikaIsUpdateTowerCD; PikaSetActive(StructBuildingTower.PikaIsActive()); PikaTexture = StructBuildingTower.PikaTexture; PikaCharacterInformationWidget = StructBuildingTower.PikaCharacterInformationWidget; return *this; } //初始化结构体 void PikaInitBuildingTower() { PikaNeedGold = 0; PikaTowerPerpareBuildingNumber = 0; PikaTowerConstructionNumber = 0; PikaMaxConstructionTowerCD = 0; PikaCurrentConstructionTowerCD = 0; PikaIsUpdateTowerCD = false; PikaIsSlotActive = false; PikaTexture = nullptr; PikaIsDragIco = false; PikaIsLockCD = false; //初始化我们的显示信息 PikaCharacterInformationWidget.PikaClearCharacterInformationWidget(); } private: //判断本结构体是不是使用中 bool PikaIsSlotActive; }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUI_InventorySlot : public UPikaUIWidgetBase { GENERATED_BODY() //控件实例的名字 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerImageName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCDImageName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerPrepareBuildingNumTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCompletionNumTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowerCDValueTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaInventorySlotButtonName; //CD材质的名字,该值为CD材质里参数化的变量ControllerCD UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCDMatName; //物品栏上是否有道具 /*UPROPERTY() bool PikaIsExistItem;*/ //CD材质 UPROPERTY() UMaterialInstanceDynamic* PikaCDMaterialDynamic; public: UPikaUI_InventorySlot(); void PikaInitTowerIcon(); //相当于BeginPlay,用于解决BeginPlay执行时,有些资源可能还没加载完成的问题 //需要手动调用 virtual void PikaDrawUIToScreen() override; virtual void PikaOnClickedWidget(UWidget* PikaWidget) override; //NativeTick函数里会调用蓝图里的Tick virtual void NativeTick(const FGeometry& MyGeometry , float InDeltaTime) override; //每一个物品栏对应的单个数据 FPikaBulidingTowres PikaBuildingTowerStruct; //初始化,还原物品栏没有道具时的状态 void PikaInitInventorySlot(); //用当前的物品栏数据,刷新物品栏的状态,如图标、CD等 void PikaUpdateInventorySlotData(); //重新设置父类 void PikaSetParentClass(UPikaUI_Inventory* MyParentClass); //打印测试 void PikaPrint(FString piksStr); UImage* PikaGetTowersIcon() { return PikaTowerImage; } //更新物品栏上的文本 void PikaUpdateTowerCompletionNumText(int32 TowerImageIndex); //负责打印GameLOG virtual void PikaLogPrintf(FString MyString)override; FORCEINLINE void PikaCDLock() { PikaBuildingTowerStruct.PikaIsLockCD = true; } FORCEINLINE void PikaUnCDLock() { PikaBuildingTowerStruct.PikaIsLockCD = false; } private: //控件实例 UImage* PikaTowerImage; UImage* PikaTowerCDImage; UTextBlock* PikaTowerPrepareBuildingNumText; UTextBlock* PikaTowerCompletionNumText; UTextBlock* PikaTowerCDValueText; UButton* PikaInventorySlotButton; UPikaUI_Inventory* PikaInventoryPtr; //显示字体和CD void PikaDisplayNumber(UTextBlock* MyTextNumberBlock , int32 MyTextNumber); //更新物品栏上的文本 void PikaUpdateTowerPrepareBuildingNumText(int32 TowerImageIndex); void PikaUpdateTowerCDValueText(float MyTowerCDValueText); //绘制CD,CDParameter的取值范围为0-1 void PikaUpdateTowerCDImage(float CDParameter); //构造塔的CD void PikaUpdateTowerCD(float InDeltaTime); //注册图标 void PikaRegisterTowreIcon(UTexture2D* TowresIcon); protected: /*开启Slate和SlateCore模块后start*/ virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; //NativeOnMouseButtonDown里增加的拖拽事件的响应函数 virtual void NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) override; //NativeOnDragDetected激活后,如果将图标从一个物品栏拖拽到另外一个物品栏则会触发该事件 //接收拖拽信息,InOperation为空时,该函数不会被激活 virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override; //鼠标移动到物品栏时触发,前提条件是在没有按鼠标上任何键位时移动进入的,如拖拽时不会触发该函数 virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; //鼠标离开到物品栏时触发,前提条件是在没有按鼠标上任何键位时移动进入的,如拖拽时不会触发该函数 virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override; /*开启Slate和SlateCore模块后end*/ };
PikaUI_InventorySlot.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUI_InventorySlot.h" #include "Engine/Engine.h" #include "Components/Image.h" #include "Public/PikaTowerIcon.h" #include "Public/PikaDragDropOperation.h" UPikaUI_InventorySlot::UPikaUI_InventorySlot() { //PikaIsExistItem = false; } void UPikaUI_InventorySlot::PikaRegisterTowreIcon(UTexture2D* TowresIcon) { if (PikaTowerImage) { if (TowresIcon) { PikaTowerImage->SetBrushFromTexture(TowresIcon); PikaTowerImage->SetVisibility(ESlateVisibility::Visible); } else { PikaTowerImage->SetBrushFromTexture(TowresIcon); PikaTowerImage->SetVisibility(ESlateVisibility::Hidden); } } } void UPikaUI_InventorySlot::PikaUpdateInventorySlotData() { //还原图标 PikaInitTowerIcon(); //还原CD材质 PikaUpdateTowerCDImage(PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD); //还原准备建造的塔 PikaUpdateTowerPrepareBuildingNumText(PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber); //还原已经完成的塔 PikaUpdateTowerCompletionNumText(PikaBuildingTowerStruct.PikaTowerConstructionNumber); //还原CD显示 PikaUpdateTowerCDValueText(PikaBuildingTowerStruct.PikaGetTowerConstructionTimePercentage()); } void UPikaUI_InventorySlot::PikaSetParentClass(UPikaUI_Inventory* MyParentClass) { PikaInventoryPtr = MyParentClass; } void UPikaUI_InventorySlot::PikaInitTowerIcon() { PikaRegisterTowreIcon(PikaBuildingTowerStruct.PikaTexture); } void UPikaUI_InventorySlot::PikaDrawUIToScreen() { PikaTowerImage = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowerImageName)); PikaTowerCDImage = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowerCDImageName)); PikaTowerPrepareBuildingNumText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerPrepareBuildingNumTextName)); PikaTowerCompletionNumText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerCompletionNumTextName)); PikaTowerCDValueText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowerCDValueTextName)); /* * Button的获取方式是UButton * UPikaUIWidgetBase::PikaGetButtonFromBlueprint(FName BlueprintWidgetName) const * 而除Button之外的为UWidget* UUserWidget::PikaqiuGetBlueprintWidget(FName PikaBlueprintWidgetName) const */ PikaInventorySlotButton = PikaGetButtonFromBlueprint(PikaInventorySlotButtonName); //获取动态材质实例 if (PikaTowerCDImage) PikaCDMaterialDynamic = PikaTowerCDImage->GetDynamicMaterial(); //材质绘制CD旋转 PikaUpdateTowerCDImage(0); } void UPikaUI_InventorySlot::PikaOnClickedWidget(UWidget* PikaWidget) { if (PikaWidget == PikaInventorySlotButton) { if (PikaGetSaveGameData() && PikaBuildingTowerStruct.PikaIsActive() && PikaTowerImage->PikaqiuGetTexture2D()) { if (PikaGetSaveGameData()->PikaGetGlobalGold() >= PikaBuildingTowerStruct.PikaNeedGold) { //获取图片对应的序列号 int32 PikaTowerImageIndex = PikaGetPlayerController()->PikaGetTowerIocn().Find(PikaTowerImage->PikaqiuGetTexture2D()); //消费金币 PikaGetSaveGameData()->PikaConsumeGlobalGold(PikaBuildingTowerStruct.PikaNeedGold); //记录我们的塔 PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber++; //更新到界面并且上传到存储 PikaUpdateTowerPrepareBuildingNumText(PikaTowerImageIndex); //赋值CD if (PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD <= 0) { PikaBuildingTowerStruct.PikaSetCurrentCD(); } } else { PikaLogPrintf("Insufficient glod"); } } } } void UPikaUI_InventorySlot::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) { Super::NativeTick(MyGeometry , InDeltaTime); //构造塔的CD if (!PikaBuildingTowerStruct.PikaIsLockCD) { if (!PikaBuildingTowerStruct.PikaIsDragIco) PikaUpdateTowerCD(InDeltaTime); } } void UPikaUI_InventorySlot::PikaUpdateTowerPrepareBuildingNumText(int32 TowerImageIndex) { if (PikaTowerPrepareBuildingNumText) { //显示到界面 PikaDisplayNumber(PikaTowerPrepareBuildingNumText , PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber); //上传数据到存储类 if (PikaGetSaveGameData()->PikaTowerPrepareBuildingNumber.IsValidIndex(TowerImageIndex)) PikaGetSaveGameData()->PikaTowerPrepareBuildingNumber[TowerImageIndex] = PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber; } } void UPikaUI_InventorySlot::PikaUpdateTowerCompletionNumText(int32 TowerImageIndex) { if (PikaTowerCompletionNumText) { //显示到界面 PikaDisplayNumber(PikaTowerCompletionNumText, PikaBuildingTowerStruct.PikaTowerConstructionNumber); //上传数据到存储类 if (PikaGetSaveGameData()->PikaTowerConstructionNumber.IsValidIndex(TowerImageIndex)) PikaGetSaveGameData()->PikaTowerConstructionNumber[TowerImageIndex] = PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD; } } void UPikaUI_InventorySlot::PikaLogPrintf(FString MyString) { PikaInventoryPtr->PikaLogPrintf(MyString); } void UPikaUI_InventorySlot::PikaUpdateTowerCDValueText(float MyTowerCDValueText) { if (PikaTowerCDValueText) { PikaDisplayNumber(PikaTowerCDValueText, MyTowerCDValueText); } } //绘制CD,CDParameter的取值范围为0-1 void UPikaUI_InventorySlot::PikaUpdateTowerCDImage(float CDParameter) { if (PikaCDMaterialDynamic) { PikaCDMaterialDynamic->SetScalarParameterValue(PikaCDMatName, CDParameter); } } /**************************构建CD**************************/ void UPikaUI_InventorySlot::PikaUpdateTowerCD(float InDeltaTime) { //当前CD是否小于0 if (PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD > 0) { //绘制旋转的材质CD PikaUpdateTowerCDImage(PikaBuildingTowerStruct.PikaGetTowerConstructionTimePercentage()); //绘制数字CD显示 PikaUpdateTowerCDValueText(PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD); //用来呼叫完成事件 PikaBuildingTowerStruct.PikaIsUpdateTowerCD = true; //数字变化 PikaBuildingTowerStruct.PikaCurrentConstructionTowerCD -= InDeltaTime; return; } //等价于CD转完后呼叫一个完成事件 if (PikaBuildingTowerStruct.PikaIsUpdateTowerCD) { PikaBuildingTowerStruct.PikaIsUpdateTowerCD = false; //PikaTowerImage->Brush.GetResourceObject()可以返回图片资源 if (PikaTowerImage && PikaTowerImage->PikaqiuGetTexture2D()) { //获取图片对应的序列号 int32 PikaTowerImageIndex = PikaGetPlayerController()->PikaGetTowerIocn().Find(PikaTowerImage->PikaqiuGetTexture2D()); //准备构建的塔 PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber--; //建造完成的塔 PikaBuildingTowerStruct.PikaTowerConstructionNumber++; PikaUpdateTowerPrepareBuildingNumText(PikaTowerImageIndex); PikaUpdateTowerCompletionNumText(PikaTowerImageIndex); //让我们的建造会一直根据我们的输入而建造 if (PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber > 0) PikaBuildingTowerStruct.PikaSetCurrentCD(); //打印塔建造完成的信息 //获取游戏路径 FString gameDir = FPaths::ProjectDir(); FString path = gameDir + "111.txt"; FString string; TArray<FString> stringArray; FFileHelper::LoadFileToString(string, *path); string.ParseIntoArray(stringArray, TEXT(","), false); if(stringArray.IsValidIndex(0) && stringArray.IsValidIndex(1) && stringArray.IsValidIndex(2)) PikaLogPrintf(stringArray[0] + stringArray[1] + stringArray[2]); //PikaLogPrintf(PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterName.ToString() + string); //PikaLogPrintf(FString::Printf(TEXT("%s:%i has been done and %i 's in perparation for constriction!") , *PikaBuildingTowerStruct.PikaCharacterInformationWidget.PikaCharacterName.ToString() , PikaBuildingTowerStruct.PikaTowerConstructionNumber ,PikaBuildingTowerStruct.PikaTowerPerpareBuildingNumber)); } } } FReply UPikaUI_InventorySlot::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) { Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent); //InMouseEvent.IsTouchEvent()为触摸屏的判断 if (InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton || InMouseEvent.IsTouchEvent()) { //FReply::Handled()表示按键响应已经被处理 FReply PikaReply = FReply::Handled(); TSharedPtr<SWidget> PikaSlateWidgetDrag = GetCachedWidget(); if (PikaSlateWidgetDrag.IsValid()) { //PikaReply.DetectDrag()检测到拖拽后会触发一个UUserWidget类里的NativeOnDragDetected事件 PikaReply.DetectDrag(PikaSlateWidgetDrag.ToSharedRef() , EKeys::RightMouseButton); return PikaReply; } } //FReply::Unhandled()表示按键响应未被处理 return FReply::Unhandled(); } //NativeOnMouseButtonDown里增加的拖拽事件的响应函数 void UPikaUI_InventorySlot::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) { if (PikaBuildingTowerStruct.PikaIsActive() && GetWorld()) { TSubclassOf<UPikaTowerIcon> PikaIcoDragDrop = LoadClass<UPikaTowerIcon>(NULL , TEXT("WidgetBlueprint'/Game/HUD/GameUI/PikaTowerIconBP.PikaTowerIconBP_C'")); if (PikaIcoDragDrop) { UPikaTowerIcon* PikaCharactersIcoDragDrop = CreateWidget<UPikaTowerIcon>(GetWorld() , PikaIcoDragDrop); if (PikaCharactersIcoDragDrop) { //生成图标 UPikaDragDropOperation* PikaTowerDragOperation = nullptr; TSubclassOf<UPikaDragDropOperation> PikaTowerDragOperationClass = UPikaDragDropOperation::StaticClass(); if (PikaTowerDragOperationClass) { PikaTowerDragOperation = NewObject<UPikaDragDropOperation>(GetTransientPackage() , PikaTowerDragOperationClass); } else { PikaTowerDragOperation = NewObject<UPikaDragDropOperation>(); } if (PikaTowerDragOperation) PikaTowerDragOperation->SetFlags(RF_StrongRefOnFrame);//设置标识 //注册图标显示信息 PikaTowerDragOperation->PikaInventorySlot = this; PikaCharactersIcoDragDrop->PikaBuildingTowerStructIcon = PikaBuildingTowerStruct; PikaTowerDragOperation->DefaultDragVisual = PikaCharactersIcoDragDrop; OutOperation = PikaTowerDragOperation; //初始化我们的值(显示图标信息) PikaCharactersIcoDragDrop->PikaDrawUIToScreen(); //处于拖拽状态中,停止所有CD PikaBuildingTowerStruct.PikaIsDragIco = true; } } } Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation); } //NativeOnDragDetected激活后,拖拽完成时,如果将图标从一个物品栏拖拽到另外一个物品栏时,则会触发该事件 //接收拖拽信息,InOperation为空时,该函数不会被激活 bool UPikaUI_InventorySlot::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) { this; Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation); bool PikaIsDrop = false; UPikaDragDropOperation* PikaDragDropOperation = Cast<UPikaDragDropOperation>(InOperation); if (PikaDragDropOperation) { //PikaMyInventorySlot为拖拽前的物品栏,类本身为拖拽的目标物品栏 UPikaUI_InventorySlot* PikaMyInventorySlot = Cast<UPikaUI_InventorySlot>(PikaDragDropOperation->PikaInventorySlot); if (PikaMyInventorySlot) { PikaMyInventorySlot->PikaBuildingTowerStruct.PikaIsDragIco = false; PikaBuildingTowerStruct.PikaIsDragIco = false; if (PikaBuildingTowerStruct.PikaIsActive()) { //拖拽的目标物品栏处于激活状态,做物品栏交换操作 FPikaBulidingTowres PikaTempBulidTower; PikaTempBulidTower = PikaBuildingTowerStruct; PikaBuildingTowerStruct = PikaMyInventorySlot->PikaBuildingTowerStruct; PikaMyInventorySlot->PikaBuildingTowerStruct = PikaTempBulidTower; //更新数据显示 PikaMyInventorySlot->PikaUpdateInventorySlotData(); PikaUpdateInventorySlotData(); } else { //拖拽的目标物品栏处于未激活状态,做物品栏移动操作 PikaBuildingTowerStruct = PikaMyInventorySlot->PikaBuildingTowerStruct; //物品栏还原没有道具时的状态 PikaMyInventorySlot->PikaInitInventorySlot(); PikaUpdateInventorySlotData(); } PikaIsDrop = true; } PikaIsDrop = false; } else PikaIsDrop = false; //销毁,引擎会自动释放,下面的释放代码可以不写 /*if (InOperation) { if (InOperation->DefaultDragVisual) InOperation->DefaultDragVisual->RemoveFromParent(); InOperation->DefaultDragVisual = NULL; InOperation->ConditionalBeginDestroy(); }*/ return PikaIsDrop; } void UPikaUI_InventorySlot::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) { if (PikaInventoryPtr) { PikaInventoryPtr->PikaSetTempInventorySlot(this); //显示塔信息 if (PikaInventoryPtr->PikaGetMainInterface() && PikaBuildingTowerStruct.PikaIsActive()) { if (PikaInventoryPtr->PikaGetMainInterface()->PikaGetUITowerInfo()) PikaInventoryPtr->PikaGetMainInterface()->PikaGetUITowerInfo()->SetVisibility(ESlateVisibility::Visible); } } } void UPikaUI_InventorySlot::NativeOnMouseLeave(const FPointerEvent& InMouseEvent) { if (PikaInventoryPtr) { //PikaInventoryPtr->PikaCancelTempInventorySlot(); //隐藏塔信息 if (PikaInventoryPtr->PikaGetMainInterface()) { if (PikaInventoryPtr->PikaGetMainInterface()->PikaGetUITowerInfo()) PikaInventoryPtr->PikaGetMainInterface()->PikaGetUITowerInfo()->SetVisibility(ESlateVisibility::Hidden); } } } void UPikaUI_InventorySlot::PikaInitInventorySlot() { //初始化结构体 PikaBuildingTowerStruct.PikaInitBuildingTower(); PikaUpdateInventorySlotData(); } void UPikaUI_InventorySlot::PikaPrint(FString piksStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr); } } //显示字体和CD void UPikaUI_InventorySlot::PikaDisplayNumber(UTextBlock* MyTextNumberBlock, int32 MyTextNumber) { //物品栏上有道显示文本,没有道具则不显示文本 if (MyTextNumber < 1 || !PikaBuildingTowerStruct.PikaIsActive()) { MyTextNumberBlock->SetVisibility(ESlateVisibility::Hidden); } else { //格式输出里,%02d表示输出格式为00,%03d的输出格式为000 MyTextNumberBlock->SetText(FText::FromString(FString::Printf(TEXT("%02d") , MyTextNumber))); MyTextNumberBlock->SetVisibility(ESlateVisibility::Visible); } }
PikaUICharacterAttribute.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaCharacterData.h" #include "TextBlock.h" #include "ProgressBar.h" #include "MultiLineEditableTextBox.h" #include "Image.h" #include "PikaMainInterface.h" #include "PikaUICharacterAttribute.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUICharacterAttribute : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterNameBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaComsumeGlodBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterLevelName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterHealthBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterAttackBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterArmorBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterAttackSpeedBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterEmpiricalValueBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterEmpiricalValueBarName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaIntroductionName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTowersIcoName; //角色的信息数据 UPikaCharacterData* PikaCharacterDataPtr; public: //作为初始化实例 virtual void NativePreConstruct()override; virtual void PikaDrawUIToScreen() override; //设置我们的数据 void PikaSetGameCharacterData(UPikaCharacterData* NewCharacterData) { PikaCharacterDataPtr = NewCharacterData; } //只要角色值变动就会更新 void PikaUpdateCharacterInformation(); //角色升级后更新 void PikaUpdateLevelCharacterElement(); void PikaUpdataAll(); //游戏初始化进行更新(只更新一次) void PikaUpdatecharacterElement(); void PikaSetMianScreen(UPikaMainInterface* NewMianScreen) { PikaMianScreen = NewMianScreen; } private: UTextBlock* PikaCharacterNameBlock; UTextBlock* PikaComsumeGlodBlock; UTextBlock* PikaCharacterLevelBlock; UTextBlock* PikaCharacterHealthBlock; UTextBlock* PikaCharacterAttackBlock; UTextBlock* PikaCharacterArmorBlock; UTextBlock* PikaCharacterAttackSpeedBlock; UTextBlock* PikaCharacterEmpiricalValueBlock; UProgressBar* PikaCharacterEmpiricalValueBar; UMultiLineEditableTextBox* PikaIntroduction; UImage* PikaTowersIco; UPikaMainInterface* PikaMianScreen; protected: virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent)override; };
PikaUICharacterAttribute.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUICharacterAttribute.h" void UPikaUICharacterAttribute::NativePreConstruct() { Super::NativePreConstruct(); if (!PikaCharacterNameBlock) PikaCharacterNameBlock = Cast<UTextBlock>(GetWidgetFromName(PikaCharacterNameBlockName)); if (!PikaComsumeGlodBlock) PikaComsumeGlodBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaComsumeGlodBlockName)); if (!PikaCharacterLevelBlock) PikaCharacterLevelBlock = Cast<UTextBlock>(GetWidgetFromName(PikaCharacterLevelName)); if (!PikaCharacterHealthBlock) PikaCharacterHealthBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterHealthBlockName)); if (!PikaCharacterAttackBlock) PikaCharacterAttackBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackBlockName)); if (!PikaCharacterArmorBlock) PikaCharacterArmorBlock = Cast<UTextBlock>(GetWidgetFromName(PikaCharacterArmorBlockName)); if (!PikaCharacterAttackSpeedBlock) PikaCharacterAttackSpeedBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackSpeedBlockName)); if (!PikaCharacterEmpiricalValueBlock) PikaCharacterEmpiricalValueBlock = Cast<UTextBlock>(GetWidgetFromName(PikaCharacterEmpiricalValueBlockName)); if (!PikaCharacterEmpiricalValueBar) PikaCharacterEmpiricalValueBar = Cast<UProgressBar>(PikaqiuGetBlueprintWidget(PikaCharacterEmpiricalValueBarName)); if (!PikaIntroduction) PikaIntroduction = Cast<UMultiLineEditableTextBox>(GetWidgetFromName(PikaIntroductionName)); if (!PikaTowersIco) PikaTowersIco = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowersIcoName)); } void UPikaUICharacterAttribute::PikaDrawUIToScreen() { if (!PikaCharacterNameBlock) PikaCharacterNameBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterNameBlockName)); if (!PikaComsumeGlodBlock) PikaComsumeGlodBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaComsumeGlodBlockName)); if (!PikaCharacterLevelBlock) PikaCharacterLevelBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterLevelName)); if (!PikaCharacterHealthBlock) PikaCharacterHealthBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterHealthBlockName)); if (!PikaCharacterAttackBlock) PikaCharacterAttackBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackBlockName)); if (!PikaCharacterArmorBlock) PikaCharacterArmorBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterArmorBlockName)); if (!PikaCharacterAttackSpeedBlock) PikaCharacterAttackSpeedBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackSpeedBlockName)); if (!PikaCharacterEmpiricalValueBlock) PikaCharacterEmpiricalValueBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterEmpiricalValueBlockName)); if (!PikaCharacterEmpiricalValueBar) PikaCharacterEmpiricalValueBar = Cast<UProgressBar>(PikaqiuGetBlueprintWidget(PikaCharacterEmpiricalValueBarName)); if (!PikaIntroduction) PikaIntroduction = Cast<UMultiLineEditableTextBox>(PikaqiuGetBlueprintWidget(PikaIntroductionName)); if (!PikaTowersIco) PikaTowersIco = Cast<UImage>(PikaqiuGetBlueprintWidget(PikaTowersIcoName)); } //只要角色值变动就会更新 void UPikaUICharacterAttribute::PikaUpdateCharacterInformation() { if (PikaCharacterDataPtr) { //生命值 if (PikaCharacterHealthBlock) PikaCharacterHealthBlock->SetText(FText::FromString(FString::Printf(TEXT("%0.f / %0.f"), PikaCharacterDataPtr->PikaCharBaseData.PikaMaxHealth, PikaCharacterDataPtr->PikaCharBaseData.PikaCurrentHealth))); //经验数值 if (PikaCharacterEmpiricalValueBlock) PikaCharacterEmpiricalValueBlock->SetText(FText::FromString(FString::Printf(TEXT("%0.f / %0.f"), PikaCharacterDataPtr->PikaCharBaseData.PikaMaxExperienceValue, PikaCharacterDataPtr->PikaCharBaseData.PikaCurrentExperienceValue))); //经验值百分百Bar if (PikaCharacterEmpiricalValueBar) PikaCharacterEmpiricalValueBar->SetPercent(PikaCharacterDataPtr->PikaCharBaseData.PikaGetEmpircalValuePercentage()); } } //角色升级后更新 void UPikaUICharacterAttribute::PikaUpdateLevelCharacterElement() { if (PikaCharacterDataPtr) { //攻击力 if (PikaCharacterAttackBlock) PikaCharacterAttackBlock->SetText(FText::AsNumber(PikaCharacterDataPtr->PikaCharBaseData.PikaPhysicalAttack)); //防御力 if (PikaCharacterArmorBlock) PikaCharacterArmorBlock->SetText(FText::AsNumber(PikaCharacterDataPtr->PikaCharBaseData.PikaArmor)); //攻击速度 if (PikaCharacterAttackSpeedBlock) PikaCharacterAttackSpeedBlock->SetText(FText::AsNumber(PikaCharacterDataPtr->PikaCharBaseData.PikaAttackSpeed)); //等级 if (PikaCharacterLevelBlock) PikaCharacterLevelBlock->SetText(FText::FromString(FString::Printf(TEXT("Lv- %02d"), PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterLevel))); //生命值 if (PikaCharacterHealthBlock) PikaCharacterHealthBlock->SetText(FText::FromString(FString::Printf(TEXT("%0.f / %0.f"), PikaCharacterDataPtr->PikaCharBaseData.PikaMaxHealth, PikaCharacterDataPtr->PikaCharBaseData.PikaCurrentHealth))); //经验数值 if (PikaCharacterEmpiricalValueBlock) PikaCharacterEmpiricalValueBlock->SetText(FText::FromString(FString::Printf(TEXT("%0.f / %0.f"), PikaCharacterDataPtr->PikaCharBaseData.PikaMaxExperienceValue, PikaCharacterDataPtr->PikaCharBaseData.PikaCurrentExperienceValue))); //经验值百分百Bar if (PikaCharacterEmpiricalValueBar) PikaCharacterEmpiricalValueBar->SetPercent(PikaCharacterDataPtr->PikaCharBaseData.PikaGetEmpircalValuePercentage()); } } void UPikaUICharacterAttribute::PikaUpdataAll() { this->PikaUpdatecharacterElement(); this->PikaUpdateCharacterInformation(); this->PikaUpdateLevelCharacterElement(); } //游戏初始化进行更新(只更新一次) void UPikaUICharacterAttribute::PikaUpdatecharacterElement() { if (PikaGetPlayerController() && PikaCharacterDataPtr) { //更新名字 if (PikaCharacterNameBlock) PikaCharacterNameBlock->SetText(FText::FromName(PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterName)); //花费 if (PikaComsumeGlodBlock) PikaComsumeGlodBlock->SetText(FText::AsNumber(PikaCharacterDataPtr->PikaCharBaseData.PikaComsumeGold)); if (PikaCharacterDataPtr->PikaCharBaseData.PikaTeam) { int32 PikaIndexTowerName = PikaGetPlayerController()->PikaGetTowersName().Find(PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterName); if (PikaIndexTowerName >= 0 && PikaIndexTowerName < PikaGetPlayerController()->PikaGetTowersIntroduction().Num()) { if (PikaTowersIco) PikaTowersIco->SetBrushFromTexture(PikaGetPlayerController()->PikaGetTowerIocn()[PikaIndexTowerName]); if (PikaIntroduction) PikaIntroduction->SetText(PikaGetPlayerController()->PikaGetTowersIntroduction()[PikaIndexTowerName]); } } else { int32 PikaIndexMonsterName = PikaGetPlayerController()->PikaGetMonsterName().Find(PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterName); if (PikaIndexMonsterName >= 0 && PikaIndexMonsterName < PikaGetPlayerController()->PikaGetMonsterName().Num()) { if (PikaTowersIco) PikaTowersIco->SetBrushFromTexture(PikaGetPlayerController()->PikaGetMonsterIocn()[PikaIndexMonsterName]); if (PikaIntroduction) PikaIntroduction->SetText(PikaGetPlayerController()->PikaGetMonsterIntroduction()[PikaIndexMonsterName]); } } } } void UPikaUICharacterAttribute::NativeOnMouseLeave(const FPointerEvent& InMouseEvent) { //将自己隐藏 if (PikaMianScreen && PikaMianScreen->PikaGetCharacterAttribute() && PikaMianScreen->PikaGetCharacterAttribute()->GetVisibility() != ESlateVisibility::Hidden) { PikaMianScreen->PikaGetCharacterAttribute()->SetVisibility(ESlateVisibility::Hidden); } }
PikaUIData.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "PikaUIData.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIData : public UObject { GENERATED_BODY() public: //物品栏的格子数 int32 PikaInventoryColumn, PikaInventoryRow; float PikaLogDisplayTime; UPikaUIData(); };
PikaUIData.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIData.h" UPikaUIData::UPikaUIData() { PikaInventoryColumn = 3; PikaInventoryRow = 6; PikaLogDisplayTime = 2.f; }
PikaUIGameCount.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "ProgressBar.h" #include "TextBlock.h" #include "PikaUIGameCount.generated.h" class UPikaMainInterface; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIGameCount : public UPikaUIWidgetBase { GENERATED_BODY() //控件示例的名字 UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameGlobName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaTowersDeathNumberName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameCountName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameLevelScheduleName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameLevelScheduleSginName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaKillSoldierName; UPROPERTY(EditDefaultsOnly, Category = UI) FString PikaBaseIamgeFadeInName; UPROPERTY(EditDefaultsOnly, Category = UI) FString PikaBaseIamgeFadeOutName; public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen() override; //void PikaPlayIamgeAnimationState(bool IsBegin); //负责打印GameLOG virtual void PikaLogPrintf(FString MyString) override; void PikaUpdateInformation(); //更新数字显示 25/5 void PikaUpdateMonsterMaximum(int32 MaxValue, int32 Surplus); //获取时间格式 FString PikaGetCurrentCount(float NewTimeCount); //Tick virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; UPikaMainInterface* PikaGetMianScreen()const { return PikaMainInterface; } void PikaSetMainInterface(UPikaMainInterface* NewWidget) { PikaMainInterface = NewWidget; } private: UTextBlock* PikaGameGlob; UTextBlock* PikaTowersDeathNumber; UTextBlock* PikaGameCount; UTextBlock* PikaKillSoldier; UTextBlock* PikaGameLevelScheduleTexrSgin; UProgressBar* PikaGameLevelSchedule; UPikaMainInterface* PikaMainInterface; //动画 //UWidgetAnimation* PikaBaseIamgeFadeIn; //UWidgetAnimation* PikaBaseIamgeFadeOut; protected: //virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent); //virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent); };
PikaUIGameCount.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIGameCount.h" void UPikaUIGameCount::PikaDrawUIToScreen() { PikaGameGlob = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaGameGlobName)); PikaTowersDeathNumber = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTowersDeathNumberName)); PikaGameLevelScheduleTexrSgin = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaGameLevelScheduleSginName)); PikaGameCount = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaGameCountName)); PikaKillSoldier = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaKillSoldierName)); PikaGameLevelSchedule = Cast<UProgressBar>(PikaqiuGetBlueprintWidget(PikaGameLevelScheduleName)); //PikaBaseIamgeFadeIn = GetNameWidgetAnimation(PikaBaseIamgeFadeInName); //PikaBaseIamgeFadeOut = GetNameWidgetAnimation(PikaBaseIamgeFadeOutName); } void UPikaUIGameCount::PikaLogPrintf(FString MyString) { if (PikaMainInterface) PikaMainInterface->PikaLogPrintf(MyString); } void UPikaUIGameCount::PikaUpdateInformation() { if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGlobalConfigPre) { //显示游戏的倒计时 if (PikaGameCount) PikaGameCount->SetText(FText::FromString(PikaGetCurrentCount(PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaGameCount))); //显示金币 if (PikaGameGlob) PikaGameGlob->SetText(FText::AsNumber(PikaGetSaveGameData()->PikaGetGlobalGold())); //显示塔死亡 if (PikaTowersDeathNumber) PikaTowersDeathNumber->SetText(FText::AsNumber(PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaTowersDeathNumber)); //显示击杀小兵信息 if (PikaKillSoldier) PikaKillSoldier->SetText(FText::AsNumber(PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaKillSoldierNumber)); //显示关卡进度 if (PikaGameLevelSchedule) PikaGameLevelSchedule->SetPercent(PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData.PikaGetLevelPercentage()); //关卡信号标记 PikaUpdateMonsterMaximum(PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameLevelManangenment.PikaMaxStagesAreMonsters, PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameLevelManangenment.PikaCurrentStagesAreMonsters); } } void UPikaUIGameCount::PikaUpdateMonsterMaximum(int32 MaxValue, int32 Surplus) { //调整系数 Surplus += 1; if (Surplus > MaxValue) Surplus = MaxValue; //显示当前波段 if (PikaGameLevelScheduleTexrSgin) PikaGameLevelScheduleTexrSgin->SetText(FText(FText::FromString(FString::Printf(TEXT("%2d / %2d"), MaxValue, Surplus)))); } //获取时间格式 FString UPikaUIGameCount::PikaGetCurrentCount(float NewTimeCount) { const int32 NewOurTime = FMath::Max(0, FMath::TruncToInt(NewTimeCount)); const int32 NewMinrutes = NewOurTime / 60; const int32 NewSeconds = NewOurTime % 60; return FString::Printf(TEXT("%02d:%02d"), NewMinrutes, NewSeconds); } void UPikaUIGameCount::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) { Super::NativeTick(MyGeometry, InDeltaTime); //更新我们的显示数据 PikaUpdateInformation(); }
PikaUIGameMenu.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUIGameMenu.generated.h" class UPikaMainInterface; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIGameMenu : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = UI) FString PikaGameBeginAnimationName; UPROPERTY(EditDefaultsOnly, Category = UI) FString PikaGameEndAnimationName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaReturnGameButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaSaveGameButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameSettingButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaGameQuitButtonName; public: UPikaUIGameMenu(); virtual void PikaDrawUIToScreen() override; //负责打印GameLOG virtual void PikaLogPrintf(FString MyString)override; //敲击 virtual void PikaOnClickedWidget(UWidget* MyWidget)override; virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) override; UPikaMainInterface* PikaGetMainInterface()const { return PikaMainInterface; } void PikaSetMainInterface(UPikaMainInterface* NewWidget) { PikaMainInterface = NewWidget; } /////////////////////////////////动画相关///////////////////////////////////////// void PikaGameMenuFadeInAndFadeOut(bool IsOut); private: UButton* PikaReturnGameButton; UButton* PikaSaveGameButton; UButton* PikaGameSettingButtonButton; UButton* PikaGameQuitButtonButton; UPikaMainInterface* PikaMainInterface; //动画相关 UWidgetAnimation* PikaGameBeginAnimation; UWidgetAnimation* PikaGameEndAnimation; };
PikaUIGameMenu.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIGameMenu.h" UPikaUIGameMenu::UPikaUIGameMenu() { } void UPikaUIGameMenu::PikaDrawUIToScreen() { PikaReturnGameButton = PikaGetButtonFromBlueprint(PikaReturnGameButtonName); PikaSaveGameButton = PikaGetButtonFromBlueprint(PikaSaveGameButtonName); PikaGameSettingButtonButton = PikaGetButtonFromBlueprint(PikaGameSettingButtonName); PikaGameQuitButtonButton = PikaGetButtonFromBlueprint(PikaGameQuitButtonName); //PikaGameBeginAnimation = GetNameWidgetAnimation(GameBeginAnimationName); //PikaGameEndAnimation = GetNameWidgetAnimation(GameEndAnimationName); } void UPikaUIGameMenu::PikaLogPrintf(FString MyString) { if (PikaMainInterface) PikaMainInterface->PikaLogPrintf(MyString); } //onclick事件是通过父类UPikaUIWidgetBase里的PikaGetButtonFromBlueprint方法绑定的 void UPikaUIGameMenu::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaReturnGameButton) { SetVisibility(ESlateVisibility::Hidden); //开始淡出 if (PikaMainInterface && PikaGetPlayerController()) { PikaMainInterface->PikaShieldedInteractiveOperation(true); //PikaMainInterface->GameMenuFadeInAndFadeOut(false); //设置全局时间 if (PikaGetGameInstance()) { //设置全局时间的增量为1 PikaGetGameInstance()->PikaSetGlobalGameTime(PIKA_STANDARD_VALUE); } } } if (MyWidget == PikaSaveGameButton) { if (PikaMainInterface) { //打开存储列表 PikaMainInterface->PikaSetBoxListDisplayOrder(PikaBoxListType::BOXLIST_SaveList); PikaMainInterface->PikaGetBoxSaveGameArray()->SetVisibility(ESlateVisibility::Visible); //PikaMainInterface->ClickedMenuFadeInAndFadeOut(true); } } if (MyWidget == PikaGameSettingButtonButton) { /*if (PikaMainInterface) { //打开设置列表列表 PikaMainInterface->SetBoxListDisplayOrder(EBoxListType::BOXLIST_GameSettings); PikaMainInterface->ClickedMenuFadeInAndFadeOut(true); }*/ } if (MyWidget == PikaGameQuitButtonButton) { /*//打开提示菜单 SetWarningWindowsState(true, 0, FString::Printf(TEXT("Return to the menu, unsaved data will be lost. do you want to exit?")), EButtonSureType::BST_QuitMeun); //设置面板状态 if (PikaMainInterface) PikaMainInterface->SetWindowsState(true);*/ } } void UPikaUIGameMenu::PikaSetWarningWindowsState(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= PikaEButtonSureType::BST_None*/) { if (PikaMainInterface) { PikaMainInterface->PikaSetWarningWindowsState(IsVisibles, StateTime, MyWidget, MyButtonSureType); } } void UPikaUIGameMenu::PikaGameMenuFadeInAndFadeOut(bool IsOut) { /*if (IsOut) { if (PikaGameBeginAnimation) PlayAnimation(PikaGameBeginAnimation); } else { if (PikaGameEndAnimation) PlayAnimation(PikaGameEndAnimation); }*/ }
PikaUIGameWarning.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "MultiLineEditableTextBox.h" #include "PikaUIGameWarning.generated.h" class UPikaMainInterface; class UPikaUIMainHall; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIGameWarning : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSureButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCancelButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaEditableTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FString PikaOpenContorllerColorName; UPROPERTY(EditDefaultsOnly, Category = UI) FString PikaCloseContorllerColorName; public: UPikaUIGameWarning(); //存储游戏的编号 int32 PikaCurrentGameArchiveNumber; //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; virtual void PikaOnClickedWidget(UWidget* MyWidget) override; //设置字体显示 void PikaSetText(FString FSInformation); //设置MianScreen void PikaSetMainInterface(UPikaMainInterface* NewMianScreen); //设置MainHall void PikaSetMainHall(UPikaUIMainHall* NewMainHall); //virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None)override; //取消显示 void PikaCancelWarningDisplay(); ///////////////////////////////动画/////////////////////////////////////////// //void GameWarningFadeInAndFadeOut(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<EButtonSureType::Type> MyButtonSureType = EButtonSureType::BST_None); //动画完成播放后执行该函数 //virtual void OnAnimationFinished_Implementation(const UWidgetAnimation* Animation) override; //动画开始播放后执行该函数 //virtual void OnAnimationStarted_Implementation(const UWidgetAnimation* Animation) override; private: //界面 UPikaMainInterface* PikaMianInterfacePtr; UPikaUIMainHall* PikaMainHallPtr; //按键 UButton* PikaSureButton; UButton* PikaCancelButton; UMultiLineEditableTextBox* PikaEditableText; //动画相关 UWidgetAnimation* PikaOpenContorllerColor; UWidgetAnimation* PikaCloseContorllerColor; };
PikaUIGameWarning.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIGameWarning.h" UPikaUIGameWarning::UPikaUIGameWarning() { PikaCurrentGameArchiveNumber = INDEX_NONE; } void UPikaUIGameWarning::PikaDrawUIToScreen() { PikaSureButton = PikaGetButtonFromBlueprint(PikaSureButtonName); PikaCancelButton = PikaGetButtonFromBlueprint(PikaCancelButtonName); PikaEditableText = Cast<UMultiLineEditableTextBox>(GetWidgetFromName(PikaEditableTextName)); /*//动画 OpenContorllerColor = GetNameWidgetAnimation(OpenContorllerColorName); CloseContorllerColor = GetNameWidgetAnimation(CloseContorllerColorName); //默认关闭 if (CloseContorllerColor) PlayAnimation(CloseContorllerColor, 0.5);*/ } void UPikaUIGameWarning::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaSureButton) { /*//覆盖之发生在游戏中,不发生在大厅内 if (PikaGameButtonSureType == PikaEButtonSureType::BST_CoverSave) { if (PikaMianInterfacePtr && PikaMianInterfacePtr->GetReadAndWrite() && GetTowerDefencePlayerController() && GetTowerDefencePlayerController()->Confo) { //覆盖存档 MianScreen->GetReadAndWrite()->SaveArchiveSlot(true); } }*/ //游戏删除 if (PikaGameButtonSureType == PikaEButtonSureType::BST_DeleteSave) { if (PikaCurrentGameArchiveNumber != INDEX_NONE) { //游戏场景内 if (PikaMianInterfacePtr && PikaMianInterfacePtr->PikaGetReadAndWrite()) { //还原显示设置 PikaMianInterfacePtr->PikaGetReadAndWrite()->PikaClearNumberSave(PikaCurrentGameArchiveNumber); //隐藏自己 PikaMianInterfacePtr->PikaSetWarningWindowsState(false); if (PikaGetGameInstance()) { bool DeleData = PikaGetGameInstance()->PikaDeleteGameData(PikaCurrentGameArchiveNumber); if (DeleData) { PIKA_LOG("Delete Successfully"); } else { PIKA_LOG("Delete Failure"); } } } //大厅内 if (PikaMainHallPtr && PikaMainHallPtr->PikaGetReadAndWrite()) { //清除显示并且还原 PikaMainHallPtr->PikaGetReadAndWrite()->PikaClearNumberSave(PikaCurrentGameArchiveNumber); //隐藏自己 PikaMainHallPtr->PikaSetWarningWindowsState(false); if (PikaGetGameInstance()) { bool PikaDeleData = PikaGetGameInstance()->PikaDeleteGameData(PikaCurrentGameArchiveNumber); if (PikaDeleData) { PIKA_LOG("Delete Successfully"); } else { PIKA_LOG("Delete Failure"); } } } } else { PIKA_LOG("CurrentGameArchiveNumber == INDEX_NONE"); } } /*//返回主菜单 if (GameButtonSureType == EButtonSureType::BST_QuitMeun) { //通知游戏菜单播放动画 MianScreen->SetGameButtonSureType(EButtonSureType::BST_QuitMeun); MianScreen->MainUMGFadeInAndFadeOut(false, EAnimationState::BST_QuitMeun); }*/ /*//退出游戏 if (GameButtonSureType == EButtonSureType::BST_QuitGame) { ////考虑不同的场景所以使用这种办法 if (MainHall) { MainHall->MainUMGFadeInAndFadeOut(false, EAnimationState::EA_GameQuit); } //播放离游戏开动画 //只能在菜单界面播放 if (GetTowerDefenceHallGameMode()) { GetTowerDefenceHallGameMode()->PlayCurrentCameraAnimation(ECameraArray::Camera_Leave, EMatineeArray::Matinee_Max, TD_CAMARE_BLENDTIME + 2); } }*/ } if (MyWidget == PikaCancelButton) { //取消 //隐藏自己 if(PikaMianInterfacePtr) PikaMianInterfacePtr->PikaSetWarningWindowsState(false); //隐藏自己 if(PikaMainHallPtr) { PikaMainHallPtr->PikaSetWarningWindowsState(false); PikaMainHallPtr->PikaWindowsFadeInAndFadeOut(false); } } } void UPikaUIGameWarning::PikaSetText(FString FSInformation) { //更新显示字体 if (PikaEditableText) PikaEditableText->SetText(FText::FromString(FSInformation)); } void UPikaUIGameWarning::PikaSetMainInterface(UPikaMainInterface* NewMianScreen) { PikaMianInterfacePtr = NewMianScreen; } void UPikaUIGameWarning::PikaSetMainHall(UPikaUIMainHall* NewMainHall) { PikaMainHallPtr = NewMainHall; } void UPikaUIGameWarning::PikaCancelWarningDisplay() { }
PikaUIHallGameSetting.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaGameSettingsAudio.h" #include "PikaGameSettingsGameSettings.h" #include "PikaGameSettingsOtherSettings.h" #include "PikaGameSettingsVideo.h" #include "CheckBox.h" #include "WidgetSwitcher.h" #include "PikaUIGameMenu.h" #include "PikaUIHallGameSetting.generated.h" class UPikaUIMainHall; UENUM() namespace PikaGameSettingsType { enum Type { GAMESETTINGS_Sound, GAMESTETTINGS_Graphics, GAMESTETTINGS_Game, GAMESTETTINGS_Other, GAMESETTINGS_Max }; } /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIHallGameSetting : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoundSettingBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGraphicsSettingsBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGameSettingsBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaOtherGameSettingsBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSaveBarButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaReturnMenuButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSettingsListWitcherName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaGameSettingsAudio> PikaGameSettingsAudioClass; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaGameSettingsGameSettings> PikaGameSettingsGameSettingsClass; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaGameSettingsOtherSettings> PikaGameSettingsOtherSettingsClass; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaGameSettingsVideo> PikaGameSettingsVideoClass; public: UPikaUIHallGameSetting(); //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; //返回和存储设置按钮 virtual void PikaOnClickedWidget(UWidget* MyWidget)override; virtual void PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget)override; void PikaShowOneCheckBox(PikaGameSettingsType::Type GameSettingsType); void PikaSetMainHall(UPikaUIMainHall* NewWidget) { PikaMainHall = NewWidget; } void PikaSetGameMenu(UPikaUIGameMenu* NewWidget) { PikaMyGameMenu = NewWidget; } FORCEINLINE UPikaUIMainHall* PikaGetMainHall()const { return PikaMainHall; } protected: void PikaSaveGameSettings(); void PikaLoadGameSettings(); private: UCheckBox* PikaSoundSettingBox; UCheckBox* PikaGraphicsSettingsBox; UCheckBox* PikaGameSettingsBox; UCheckBox* PikaOtherGameSettingsBox; UButton* PikaSaveBarButton; UButton* PikaReturnMenuButton; //设置选项列表 UWidgetSwitcher* PikaSettingsListWitcher; UPikaUIMainHall* PikaMainHall; UPikaUIGameMenu* PikaMyGameMenu; UPikaGameSettingsAudio* PikaGameSettingsAudio; UPikaGameSettingsGameSettings* PikaGameSettingsGameSettings; UPikaGameSettingsOtherSettings* PikaGameSettingsOtherSettings; UPikaGameSettingsVideo* PikaGameSettingsVideo; TArray<UCheckBox*> PikaCheckBoxArray; };
PikaUIHallGameSetting.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIHallGameSetting.h" #include "Public/PikaGameUserSettings.h" #include "Public/PikaWorldSettings.h" UPikaUIHallGameSetting::UPikaUIHallGameSetting() { } void UPikaUIHallGameSetting::PikaDrawUIToScreen() { PikaSettingsListWitcher = Cast<UWidgetSwitcher>(GetWidgetFromName(PikaSettingsListWitcherName)); PikaSoundSettingBox = PikaGetCheckBoxFormBlueprint(PikaSoundSettingBoxName); PikaGraphicsSettingsBox = PikaGetCheckBoxFormBlueprint(PikaGraphicsSettingsBoxName); PikaGameSettingsBox = PikaGetCheckBoxFormBlueprint(PikaGameSettingsBoxName); PikaOtherGameSettingsBox = PikaGetCheckBoxFormBlueprint(PikaOtherGameSettingsBoxName); PikaReturnMenuButton = PikaGetButtonFromBlueprint(PikaReturnMenuButtonName); PikaSaveBarButton = PikaGetButtonFromBlueprint(PikaSaveBarButtonName); if (PikaSettingsListWitcher && GetWorld()) { //添加Audio if (PikaGameSettingsAudioClass) { PikaGameSettingsAudio = CreateWidget<UPikaGameSettingsAudio>(GetWorld(), PikaGameSettingsAudioClass); if (PikaGameSettingsAudio) { PikaSettingsListWitcher->AddChild(PikaGameSettingsAudio); PikaGameSettingsAudio->PikaDrawUIToScreen(); PikaGameSettingsAudio->PikaSetHallGameSettings(this); } } //添加图像设置 if (PikaGameSettingsVideoClass) { //添加图像设置 PikaGameSettingsVideo = CreateWidget<UPikaGameSettingsVideo>(GetWorld(), PikaGameSettingsVideoClass); if (PikaGameSettingsVideo) { PikaSettingsListWitcher->AddChild(PikaGameSettingsVideo); PikaGameSettingsVideo->PikaDrawUIToScreen(); PikaGameSettingsVideo->PikaSetHallGameSettings(this); } } //添加游戏设置 if (PikaGameSettingsGameSettingsClass) { //添加游戏设置 PikaGameSettingsGameSettings = CreateWidget<UPikaGameSettingsGameSettings>(GetWorld(), PikaGameSettingsGameSettingsClass); if (PikaGameSettingsGameSettings) { PikaSettingsListWitcher->AddChild(PikaGameSettingsGameSettings); PikaGameSettingsGameSettings->PikaDrawUIToScreen(); PikaGameSettingsGameSettings->PikaSetHallGameSettings(this); } } //添加其他设置 if (PikaGameSettingsOtherSettingsClass) { //添加其他设置 PikaGameSettingsOtherSettings = CreateWidget<UPikaGameSettingsOtherSettings>(GetWorld(), PikaGameSettingsOtherSettingsClass); if (PikaGameSettingsOtherSettings) { PikaSettingsListWitcher->AddChild(PikaGameSettingsOtherSettings); PikaGameSettingsOtherSettings->PikaDrawUIToScreen(); PikaGameSettingsOtherSettings->PikaSetHallGameSettings(this); } } } //添加我们的敲击盒子和绑定它 if (PikaSoundSettingBox) PikaCheckBoxArray.Add(PikaSoundSettingBox); if (PikaGraphicsSettingsBox) PikaCheckBoxArray.Add(PikaGraphicsSettingsBox); if (PikaGameSettingsBox) PikaCheckBoxArray.Add(PikaGameSettingsBox); if (PikaOtherGameSettingsBox) PikaCheckBoxArray.Add(PikaOtherGameSettingsBox); //读取本地的配置 PikaLoadGameSettings(); } //返回和存储设置按钮 void UPikaUIHallGameSetting::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaSaveBarButton) { PikaSaveGameSettings(); } if (MyWidget == PikaReturnMenuButton) { if (PikaGetMainHall() && PikaGetMainHall()->PikaGetBoxList()) //PikaGetMainHall()->PikaGetBoxList()->ClearChildren(); PikaGetMainHall()->PikaGetBoxList()->SetVisibility(ESlateVisibility::Hidden); } } void UPikaUIHallGameSetting::PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget) { if (MyWidget == PikaSoundSettingBox) { if (PikaSettingsListWitcher) { PikaSettingsListWitcher->SetActiveWidgetIndex(PikaGameSettingsType::GAMESETTINGS_Sound); PikaShowOneCheckBox(PikaGameSettingsType::GAMESETTINGS_Sound); } } if (MyWidget == PikaGraphicsSettingsBox) { if (PikaSettingsListWitcher) { PikaSettingsListWitcher->SetActiveWidgetIndex(PikaGameSettingsType::GAMESTETTINGS_Graphics); PikaShowOneCheckBox(PikaGameSettingsType::GAMESTETTINGS_Graphics); } } if (MyWidget == PikaGameSettingsBox) { if (PikaSettingsListWitcher) { PikaSettingsListWitcher->SetActiveWidgetIndex(PikaGameSettingsType::GAMESTETTINGS_Game); PikaShowOneCheckBox(PikaGameSettingsType::GAMESTETTINGS_Game); } } if (MyWidget == PikaOtherGameSettingsBox) { if (PikaSettingsListWitcher) { PikaSettingsListWitcher->SetActiveWidgetIndex(PikaGameSettingsType::GAMESTETTINGS_Other); PikaShowOneCheckBox(PikaGameSettingsType::GAMESTETTINGS_Other); } } } void UPikaUIHallGameSetting::PikaShowOneCheckBox(PikaGameSettingsType::Type GameSettingsType) { for (int32 i = 0; i < PikaGameSettingsType::GAMESETTINGS_Max; i++) { if (i != GameSettingsType && PikaCheckBoxArray.IsValidIndex(i)) PikaCheckBoxArray[i]->SetCheckedState(ECheckBoxState::Checked); else PikaCheckBoxArray[i]->SetCheckedState(ECheckBoxState::Unchecked); } } void UPikaUIHallGameSetting::PikaSaveGameSettings() { if (UPikaGameUserSettings::PikaGetGameUserSettings()) { //音乐存储 if (PikaGameSettingsAudio) { if (PikaGameSettingsAudio->PikaGetSoundControllSlider()) UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuTotalSoundControl = PikaGameSettingsAudio->PikaGetSoundControllSlider()->GetValue(); if (PikaGameSettingsAudio->PikaGetMusicSlider()) UPikaGameUserSettings::PikaGetGameUserSettings()->PikaBackgroundSoundControl = PikaGameSettingsAudio->PikaGetMusicSlider()->GetValue(); if (PikaGameSettingsAudio->PikaGetSoundEffectSlider()) UPikaGameUserSettings::PikaGetGameUserSettings()->PikaEffectsSoundControl = PikaGameSettingsAudio->PikaGetSoundEffectSlider()->GetValue(); if (PikaGameSettingsAudio->PikaGetAudioSlider()) UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuButtonSoundControl = PikaGameSettingsAudio->PikaGetAudioSlider()->GetValue(); } if (PikaGameSettingsVideo) { //保存分辨率 if (PikaGameSettingsVideo->PikaGetResolutionBoxString()) { FString PikaResolution_H; FString PikaResolution_W; FString PikaResolutionString = PikaGameSettingsVideo->PikaGetResolutionBoxString()->GetSelectedOption(); PikaResolutionString.Split(TEXT("x"), &PikaResolution_W, &PikaResolution_H); FIntPoint PikaResolutionInt; PikaResolutionInt.X = FCString::Atoi(*PikaResolution_W); PikaResolutionInt.Y = FCString::Atoi(*PikaResolution_H); UPikaGameUserSettings::PikaGetGameUserSettings()->SetScreenResolution(PikaResolutionInt); } /*//语言 if (GameSettingsVideo->GetLanguageString()) { FString LanguageTmp = GameSettingsVideo->GetLanguageString()->GetSelectedOption(); UTowerDefenceGameUserSettings::GetTowerDefenceGameUserSettings()->SetCuurrLanguage(LanguageTmp); }*/ //设置屏幕模式 if (PikaGameSettingsVideo->PikaGetFullScreenCheckBox() && PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()) { if (PikaGameSettingsVideo->PikaGetFullScreenCheckBox()->IsChecked()) { if (!PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()->IsChecked()) { UPikaGameUserSettings::PikaGetGameUserSettings()->SetFullscreenMode(EWindowMode::WindowedFullscreen); } } else if (PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()->IsChecked()) { UPikaGameUserSettings::PikaGetGameUserSettings()->SetFullscreenMode(EWindowMode::Windowed); } } //默认级别 int32 PikaScalabilityQualityLevel = 5.0f; //贴图质量 if (PikaGameSettingsVideo->PikaGetTextureQualitySlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetTextureQualitySlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.TextureQuality = PikaCurrentQualityLevel; } //阴影质量 if (PikaGameSettingsVideo->PikaGetShadowQualitySlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetShadowQualitySlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.ShadowQuality = PikaCurrentQualityLevel; } //锯齿质量 if (PikaGameSettingsVideo->PikaGetAntiAliasingSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetAntiAliasingSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.AntiAliasingQuality = PikaCurrentQualityLevel; } //后期质量 if (PikaGameSettingsVideo->PikaGetPostProcessingSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetPostProcessingSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.PostProcessQuality = PikaCurrentQualityLevel; } //特效质量 if (PikaGameSettingsVideo->PikaGetEffectsSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetEffectsSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.EffectsQuality = PikaCurrentQualityLevel; } //Foliage质量 if (PikaGameSettingsVideo->PikaGetFoliageSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetFoliageSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.FoliageQuality = PikaCurrentQualityLevel; } //视距离质量 if (PikaGameSettingsVideo->PikaGetViewDistanceSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetViewDistanceSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.ViewDistanceQuality = PikaCurrentQualityLevel; } //摄像机FOV设置 if (PikaGameSettingsVideo->PikaGetFOVSlider()) { //载入摄像机FOV if (GetWorld() && GetWorld()->GetWorldSettings()) { APikaWorldSettings* PikaWorldSettings = Cast<APikaWorldSettings>(GetWorld()->GetWorldSettings()); if (PikaWorldSettings && PikaWorldSettings->PikaCurrentLevel != INDEX_NONE) { if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGetTowreCamera()) { float PikaCurrentFOV = PikaGameSettingsVideo->PikaGetFOVSlider()->GetValue() * PIKA_FOVMAX_VALUE + 40; if (PikaCurrentFOV >= 40 && PikaCurrentFOV <= 240) { //大厅里设置该值会崩 //PikaGetPlayerController()->PikaGetTowreCamera()->PikaSetCameraFOV(PikaCurrentFOV); UPikaGameUserSettings::PikaGetGameUserSettings()->PikaCameraFOV = PikaCurrentFOV; } } } } } //总级别控制, /*总级别控制这项一定要放到所有其它设置的最后面,否则读取不到值*/ if (PikaGameSettingsVideo->PikaGetOverallScalabilityLevelSlider()) { float PikaCurrentValue = PikaGameSettingsVideo->PikaGetOverallScalabilityLevelSlider()->GetValue(); int32 PikaCurrentQualityLevel = PikaCurrentValue * PikaScalabilityQualityLevel; if (PikaCurrentQualityLevel != UPikaGameUserSettings::PikaGetGameUserSettings()->GetOverallScalabilityLevel()) { UPikaGameUserSettings::PikaGetGameUserSettings()->SetOverallScalabilityLevel(PikaCurrentQualityLevel); } } } UPikaGameUserSettings::PikaGetGameUserSettings()->ApplySettings(true); } } void UPikaUIHallGameSetting::PikaLoadGameSettings() { if ((UPikaGameUserSettings::PikaGetGameUserSettings())) { //读取配置 UPikaGameUserSettings::PikaGetGameUserSettings()->LoadSettings(); //读取音乐配置 if (PikaGameSettingsAudio) { if (PikaGameSettingsAudio->PikaGetSoundControllSlider()) PikaGameSettingsAudio->PikaGetSoundControllSlider()->SetValue(UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuTotalSoundControl); if (PikaGameSettingsAudio->PikaGetMusicSlider()) PikaGameSettingsAudio->PikaGetMusicSlider()->SetValue(UPikaGameUserSettings::PikaGetGameUserSettings()->PikaBackgroundSoundControl); if (PikaGameSettingsAudio->PikaGetSoundEffectSlider()) PikaGameSettingsAudio->PikaGetSoundEffectSlider()->SetValue(UPikaGameUserSettings::PikaGetGameUserSettings()->PikaEffectsSoundControl); if (PikaGameSettingsAudio->PikaGetAudioSlider()) PikaGameSettingsAudio->PikaGetAudioSlider()->SetValue(UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuButtonSoundControl); //更新属性 PikaGameSettingsAudio->PikaUpdateAttibe(); } //关于显示设置 if (PikaGameSettingsVideo) { //载入分辨率 if (PikaGameSettingsVideo->PikaGetResolutionBoxString()) { FIntPoint PikaResolutionPoint = UPikaGameUserSettings::PikaGetGameUserSettings()->GetScreenResolution(); FString PikaResolutionString = FString::Printf(TEXT("%ix%i"), PikaResolutionPoint.X, PikaResolutionPoint.Y); PikaGameSettingsVideo->PikaGetResolutionBoxString()->SetSelectedOption(PikaResolutionString); } /*//本地语言 if (GameSettingsVideo->GetLanguageString()) { FString LanguageString = UTowerDefenceGameUserSettings::GetTowerDefenceGameUserSettings()->GetCurrentLanguageType(); GameSettingsVideo->GetLanguageString()->SetSelectedOption(LanguageString); }*/ //载入窗口模式 if (PikaGameSettingsVideo->PikaGetFullScreenCheckBox() && PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()) { EWindowMode::Type PikaWindowMode = UPikaGameUserSettings::PikaGetGameUserSettings()->GetLastConfirmedFullscreenMode(); switch (PikaWindowMode) { case EWindowMode::Fullscreen: PikaGameSettingsVideo->PikaGetFullScreenCheckBox()->SetCheckedState(ECheckBoxState::Checked); PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()->SetCheckedState(ECheckBoxState::Unchecked); break; case EWindowMode::Windowed: PikaGameSettingsVideo->PikaGetFullScreenCheckBox()->SetCheckedState(ECheckBoxState::Unchecked); PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()->SetCheckedState(ECheckBoxState::Checked); break; case EWindowMode::NumWindowModes: break; case EWindowMode::WindowedFullscreen: PikaGameSettingsVideo->PikaGetFullScreenCheckBox()->SetCheckedState(ECheckBoxState::Unchecked); PikaGameSettingsVideo->PikaGetWindowScreenCheckBox()->SetCheckedState(ECheckBoxState::Checked); break; } } //默认级别 float PikaScalabilityQualityLevel = 5.0f; //贴图质量 if (PikaGameSettingsVideo->PikaGetTextureQualitySlider()) { float PikaTextureQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.TextureQuality; PikaGameSettingsVideo->PikaGetTextureQualitySlider()->SetValue(PikaTextureQualityLevel / PikaScalabilityQualityLevel); } //阴影质量 if (PikaGameSettingsVideo->PikaGetShadowQualitySlider()) { float PikaShadowQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.ShadowQuality; PikaGameSettingsVideo->PikaGetShadowQualitySlider()->SetValue(PikaShadowQualityLevel / PikaScalabilityQualityLevel); } //锯齿质量 if (PikaGameSettingsVideo->PikaGetAntiAliasingSlider()) { float PikaAntiAliasingQuality = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.AntiAliasingQuality; PikaGameSettingsVideo->PikaGetAntiAliasingSlider()->SetValue(PikaAntiAliasingQuality / PikaScalabilityQualityLevel); } //后期质量 if (PikaGameSettingsVideo->PikaGetPostProcessingSlider()) { float PikaCurrentQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.PostProcessQuality; PikaGameSettingsVideo->PikaGetPostProcessingSlider()->SetValue(PikaCurrentQualityLevel / PikaScalabilityQualityLevel); } //特效质量 if (PikaGameSettingsVideo->PikaGetEffectsSlider()) { float PikaCurrentQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.EffectsQuality; PikaGameSettingsVideo->PikaGetEffectsSlider()->SetValue(PikaCurrentQualityLevel / PikaScalabilityQualityLevel); } //Foliage质量 if (PikaGameSettingsVideo->PikaGetFoliageSlider()) { float PikaCurrentQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.FoliageQuality; PikaGameSettingsVideo->PikaGetFoliageSlider()->SetValue(PikaCurrentQualityLevel / PikaScalabilityQualityLevel); } //视距离质量 if (PikaGameSettingsVideo->PikaGetViewDistanceSlider()) { float PikaCurrentViewDistanceQuality = UPikaGameUserSettings::PikaGetGameUserSettings()->ScalabilityQuality.ViewDistanceQuality; PikaGameSettingsVideo->PikaGetViewDistanceSlider()->SetValue(PikaCurrentViewDistanceQuality / PikaScalabilityQualityLevel); } //摄像机FOV设置 if (PikaGameSettingsVideo->PikaGetFOVSlider()) { //能够滑块 PikaGameSettingsVideo->PikaGetFOVSlider()->SetIsEnabled(true); //载入摄像机FOV if (GetWorld() && GetWorld()->GetWorldSettings()) { APikaWorldSettings* PikaWorldSettings = Cast<APikaWorldSettings>(GetWorld()->GetWorldSettings()); if (PikaWorldSettings && PikaWorldSettings->PikaCurrentLevel != INDEX_NONE) { if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGetTowreCamera()) { PikaGetPlayerController()->PikaGetTowreCamera()->PikaSetCameraFOV(UPikaGameUserSettings::PikaGetGameUserSettings()->PikaCameraFOV); } } else { PikaGameSettingsVideo->PikaGetFOVSlider()->SetIsEnabled(false); } } //显示FOV //FOV 40 - 240 ,取中间数 //FOVMAX_VALUE float PikaCurrentFOV = UPikaGameUserSettings::PikaGetGameUserSettings()->PikaCameraFOV - 40; if (PikaCurrentFOV >= 0 && PikaCurrentFOV <= 200) { PikaGameSettingsVideo->PikaGetFOVSlider()->SetValue(PikaCurrentFOV / PIKA_FOVMAX_VALUE); } } //全局质量 if (PikaGameSettingsVideo->PikaGetOverallScalabilityLevelSlider()) { float PikaCurrentQualityLevel = UPikaGameUserSettings::PikaGetGameUserSettings()->GetOverallScalabilityLevel(); if (PikaCurrentQualityLevel < 0) PikaCurrentQualityLevel = 0; PikaGameSettingsVideo->PikaGetOverallScalabilityLevelSlider()->SetValue(PikaCurrentQualityLevel / PikaScalabilityQualityLevel); } //更新显示 PikaGameSettingsVideo->PikaUpdateAttibe(); } /*//游戏的设置 if (GameSettingsGameSettings) { //读取鼠标设置 if (GameSettingsGameSettings->GetMouseSpeedSlider()) GameSettingsGameSettings->GetMouseSpeedSlider()->SetValue((UTowerDefenceGameUserSettings::GetTowerDefenceGameUserSettings()->MouseSpeed / 500)); //读取模型角度设置 if (GameSettingsGameSettings->GetAngleOfRotationSlider()) GameSettingsGameSettings->GetAngleOfRotationSlider()->SetValue(UTowerDefenceGameUserSettings::GetTowerDefenceGameUserSettings()->AngleOfRotation / 180); GameSettingsGameSettings->UpdateAttibe(); } //其他设置(该设置,不会在本地进行存储,只为了显示,只读不可修改) if (GameSettingsOtherSettings && GameUIData) { //物品栏 if (GameSettingsOtherSettings->GetInventoryColumSlider()) GameSettingsOtherSettings->GetInventoryColumSlider()->SetValue(GameUIData->InventoryColumn / 10); //物品栏 if (GameSettingsOtherSettings->GetInventoryRowSlider()) GameSettingsOtherSettings->GetInventoryRowSlider()->SetValue(GameUIData->InventoryRow / 10); //Log持续时间 if (GameSettingsOtherSettings->GetLogContinueTimeSlider()) GameSettingsOtherSettings->GetLogContinueTimeSlider()->SetValue(GameUIData->LogDisplayTime / 10); GameSettingsOtherSettings->UpdateAttibe(); }*/ } }
PikaUIHallKey.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUIHallKey.generated.h" class UPikaUIMainHall; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIHallKey : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaNewWarButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaHistoryButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaMySettingsButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaTutorialWebsiteButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaAuthorButtonName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaQuitGameButtonName; //当前摄像机序列 uint8 PikaCurrentCameraType; public: UPikaUIHallKey(); //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; virtual void PikaOnClickedWidget(UWidget* MyWidget) override; //播放音效 virtual void PikaOnHoveredWidget(UWidget* CurrentButton) override; virtual void PikaOnUnHoveredWidget() override; UPikaUIMainHall* PikaGetMainHall()const { return PikaMainHall; } //关闭Button Hov //void PikaCloseButtonHov(); void PikaSetMainHall(UPikaUIMainHall* NewWidget) { PikaMainHall = NewWidget; } //virtual void SetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<EButtonSureType::Type> MyButtonSureType = EButtonSureType::BST_None) override; private: UButton* PikaNewWarButton; UButton* PikaHistoryButton; UButton* PikaMySettingsButton; UButton* PikaTutorialWebsiteButton; UButton* PikaAuthorButton; UButton* PikaQuitGameButton; UPikaUIMainHall* PikaMainHall; TArray<UButton*> PikaButtonArray; };
PikaUIHallKey.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIHallKey.h" #include "WidgetSwitcher.h" #include "Kismet/GameplayStatics.h" #include "WidgetAnimation.h" UPikaUIHallKey::UPikaUIHallKey() { PikaCurrentCameraType = INDEX_NONE; } void UPikaUIHallKey::PikaDrawUIToScreen() { PikaNewWarButton = PikaGetButtonFromBlueprint(PikaNewWarButtonName); PikaHistoryButton = PikaGetButtonFromBlueprint(PikaHistoryButtonName); PikaMySettingsButton = PikaGetButtonFromBlueprint(PikaMySettingsButtonName); PikaTutorialWebsiteButton = PikaGetButtonFromBlueprint(PikaTutorialWebsiteButtonName); PikaQuitGameButton = PikaGetButtonFromBlueprint(PikaQuitGameButtonName); PikaAuthorButton = PikaGetButtonFromBlueprint(PikaAuthorButtonName); //记录按键 if (PikaNewWarButton) PikaButtonArray.Add(PikaNewWarButton); if (PikaHistoryButton) PikaButtonArray.Add(PikaHistoryButton); if (PikaMySettingsButton) PikaButtonArray.Add(PikaMySettingsButton); if (PikaTutorialWebsiteButton) PikaButtonArray.Add(PikaTutorialWebsiteButton); if (PikaQuitGameButton) PikaButtonArray.Add(PikaQuitGameButton); if (PikaAuthorButton) PikaButtonArray.Add(PikaAuthorButton); } void UPikaUIHallKey::PikaOnClickedWidget(UWidget* MyWidget) { //新游戏 if (MyWidget == PikaNewWarButton) { //打开新关卡 if (GetWorld()) UGameplayStatics::OpenLevel(GetWorld(), "PikaGodStone_Level_Main_01"); /*if (GetMainHall()) { //提示游戏开始关卡 GetMainHall()->MainUMGFadeInAndFadeOut(false, EAnimationState::EA_GameStart); } //播放开始游戏动画 if (GetTowerDefenceHallGameMode()) { GetTowerDefenceHallGameMode()->PlayCurrentCameraAnimation(ECameraArray::Camera_IntoGame, EMatineeArray::Matinee_Max, TD_CAMARE_BLENDTIME + 1); } //设置不可敲击 SetVisibility(ESlateVisibility::HitTestInvisible); //关闭其他按键 CloseButtonHov();*/ } //游戏存储 if (MyWidget == PikaHistoryButton) { if (PikaGetMainHall() && PikaGetMainHall()->PikaGetBoxList()) { if (PikaGetMainHall()->PikaGetBoxList()->GetVisibility() == ESlateVisibility::Visible) { if (PikaGetMainHall()->PikaGetBoxListDisplayOrder() != PikaBoxListType::BOXLIST_SaveList) { //设置显示界面类型 PikaGetMainHall()->PikaSetBoxListDisplayOrder(PikaBoxListType::BOXLIST_SaveList); } //隐藏和显示界面 PikaGetMainHall()->PikaClickedMenuFadeInAndFadeOut(false , PikaqiuEAnimationState::BST_QuitMeun); } else { PikaGetMainHall()->PikaGetBoxList()->SetVisibility(ESlateVisibility::Visible); //隐藏和显示界面 PikaGetMainHall()->PikaClickedMenuFadeInAndFadeOut(true); //设置显示界面类型 PikaGetMainHall()->PikaSetBoxListDisplayOrder(PikaBoxListType::BOXLIST_SaveList); } } } //游戏设置 if (MyWidget == PikaMySettingsButton) { if (PikaGetMainHall() && PikaGetMainHall()->PikaGetBoxList()) { //关闭网站 //if (!GetMainHall()->IsWeb()) //GetMainHall()->CloseWeb(); if (PikaGetMainHall()->PikaGetBoxList()->GetVisibility() == ESlateVisibility::Visible) { if (PikaGetMainHall()->PikaGetBoxListDisplayOrder() == PikaBoxListType::BOXLIST_GameSettings) { //设置显示界面类型 PikaGetMainHall()->PikaSetBoxListDisplayOrder(PikaBoxListType::BOXLIST_GameSettings); } //隐藏和显示界面 PikaGetMainHall()->PikaClickedMenuFadeInAndFadeOut(false, PikaqiuEAnimationState::BST_QuitMeun); } else { PikaGetMainHall()->PikaGetBoxList()->SetVisibility(ESlateVisibility::Visible); //隐藏和显示界面 PikaGetMainHall()->PikaClickedMenuFadeInAndFadeOut(true); //设置显示界面类型 PikaGetMainHall()->PikaSetBoxListDisplayOrder(PikaBoxListType::BOXLIST_GameSettings); } } } //教程网站 if (MyWidget == PikaTutorialWebsiteButton) { if (PikaGetMainHall() && PikaGetMainHall()->PikaGetBoxList()) { PikaGetMainHall()->PikaGetBoxList()->SetVisibility(ESlateVisibility::Hidden); //隐藏和显示界面 /*if (GetMainHall()->GetBoxList()->GetVisibility() == ESlateVisibility::Visible) GetMainHall()->ClickedMenuFadeInAndFadeOut(false); if (GetMainHall()->IsWeb()) { //打开网站 GetMainHall()->OpenWeb(); } else { //关闭网站 GetMainHall()->CloseWeb(); }*/ } } //游戏秘境 if (MyWidget == PikaAuthorButton) { /*if (GetMainHall() && GetMainHall()->GetBoxList()) { //关闭网站 if (!GetMainHall()->IsWeb()) GetMainHall()->CloseWeb(); if (GetMainHall()->GetBoxList()->GetVisibility() == ESlateVisibility::Visible) { //隐藏和显示界面 GetMainHall()->ClickedMenuFadeInAndFadeOut(false); } //提示游戏开始关卡 GetMainHall()->MainUMGFadeInAndFadeOut(false, EAnimationState::EA_SteamGameStart); //播放开始游戏动画 if (GetTowerDefenceHallGameMode()) { GetTowerDefenceHallGameMode()->PlayCurrentCameraAnimation(ECameraArray::Camera_IntoGame, EMatineeArray::Matinee_Max, TD_CAMARE_BLENDTIME + 1); } //关闭其他按键 CloseButtonHov(); }*/ } //游戏退出 if (MyWidget == PikaQuitGameButton) { if (PikaGetPlayerController()) PikaGetPlayerController()->ConsoleCommand(FString(TEXT("exit"))); /*if (MainHall) { if (TD_WText.IsValidIndex(0)) { SetWarningWindowsState(true, 0, TD_WText[0].ToString(), EButtonSureType::BST_QuitGame); } }*/ } } void UPikaUIHallKey::PikaOnHoveredWidget(UWidget* CurrentButton) { //播放声音 if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGameResourcePtr) { PikaGetPlayerController()->PikaPlaySoundAtVetor(PikaGetPlayerController()->PikaGameResourcePtr->PikaHoverSound, FVector::ZeroVector, PikaETowerDefenceSoundType::SOUND_KEY_SOUND); } } void UPikaUIHallKey::PikaOnUnHoveredWidget() { //播放声音 if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGameResourcePtr) { PikaGetPlayerController()->PikaPlaySoundAtVetor(PikaGetPlayerController()->PikaGameResourcePtr->PikaUnHoverSound, FVector::ZeroVector, PikaETowerDefenceSoundType::SOUND_KEY_SOUND); } }
PikaUIHealthShow.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "ProgressBar.h" #include "PikaCharacterData.h" #include "PikaUIHealthShow.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIHealthShow : public UPikaUIWidgetBase { GENERATED_BODY() //血条栏 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaHealthValueBarName; //角色名称和等级 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaCharacterNameAndLVName; //角色的信息数据 UPikaCharacterData* PikaCharacterDataPtr; public: UPikaUIHealthShow(); virtual void PikaDrawUIToScreen() override; //只要角色值变动机会更新 void PikaUpdateCharacterInformation(); //设置我们的数据 void PikaSetGameCharacterData(UPikaCharacterData* NewCharacterData) { PikaCharacterDataPtr = NewCharacterData; } private: UTextBlock* PikaCharacterNameAndLV; UProgressBar* PikaHealthValueBar; };
PikaUIHealthShow.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIHealthShow.h" UPikaUIHealthShow::UPikaUIHealthShow() { } void UPikaUIHealthShow::PikaDrawUIToScreen() { if (!PikaCharacterNameAndLV) PikaCharacterNameAndLV = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterNameAndLVName)); if (!PikaHealthValueBar) PikaHealthValueBar = Cast<UProgressBar>(PikaqiuGetBlueprintWidget(PikaHealthValueBarName)); } void UPikaUIHealthShow::PikaUpdateCharacterInformation() { if (PikaCharacterDataPtr) { if (PikaCharacterNameAndLV) PikaCharacterNameAndLV->SetText(FText::FromString(FString::Printf(TEXT("Lv - %i %s"), PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterLevel, *PikaCharacterDataPtr->PikaCharBaseData.PikaCharacterName.ToString()))); if (PikaHealthValueBar) PikaHealthValueBar->SetPercent(PikaCharacterDataPtr->PikaCharBaseData.PikaGetHealthValuePercentage()); } }
PikaUILoading.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUILoading.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUILoading : public UPikaUIWidgetBase { GENERATED_BODY() };
PikaUILoading.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUILoading.h"
PikaUIMainHall.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUIWebBrowser.h" #include "PikaUIGameWarning.h" #include "PikaUIHallGameSetting.h" #include "PikaUIReadAndWrite.h" #include "PikaUIHallKey.h" #include "PikaGameErrorHint.h" #include "WidgetSwitcher.h" #include "WidgetAnimation.h" #include "PikaUIMainHall.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FEventPikaHallLog, FString, MyString); /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIMainHall : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaSaveSettingAnimationBeginName; UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaSaveSettingAnimationEndName; UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaMaskAnimationBeginName; UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaMaskAnimationEndName; UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaGradualChangeAnimationBeginName; UPROPERTY(EditDefaultsOnly, Category = "PikaAnimation") FString PikaGradualChangeAnimationEndName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaBoxKeyHallListName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaBoxWindowListName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaBoxWarningListName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaBoxListName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaBoxWebName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaMoveToLogName; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaGameErrorHint> PikaGamePromptErrorClass; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaUIHallKey> PikaHallKeyClass; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaUIReadAndWrite> PikaReadAndWriteClass; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaUIHallGameSetting> PikaHallGameSettingsClass; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaUIGameWarning> PikaGameWarningClass; UPROPERTY(EditDefaultsOnly, Category = UI) TSubclassOf<UPikaUIWebBrowser> PikaWebBrowserClass; public: FGeometry PikaHallGeometry; UPikaUIMainHall(); FEventPikaHallLog PikaHallLog; //调用去初始化我们的UI virtual void PikaDrawUIToScreen() override; //virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime)override; //负责打印GameLOG //virtual void PikaLogPrintf(FString MyString) override; //移除相应设置 virtual void RemoveFromViewport()override; /*void SetMoveToLogPostion(FVector2D NewPostion);*/ //提示窗口显示 virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) override; //存档与游戏设置切换 void PikaSetBoxListDisplayOrder(PikaBoxListType::Type BoxListType); PikaBoxListType::Type PikaGetBoxListDisplayOrder() const; /*********************Web***********************/ //void PikaSetWebListState(bool IsWebState); //打开网站 //void PikaOpenWeb(); //关闭网站 //void PikaCloseWeb(); //是不是网站 //bool PikaIsWeb(); FORCEINLINE UWidgetSwitcher* PikaGetBoxList() const { return PikaBoxList; } FORCEINLINE UPikaUIReadAndWrite* PikaGetReadAndWrite() const { return PikaReadAndWritePtr; } FORCEINLINE UPikaUIHallGameSetting* PikaGetHallGameSettings()const { return PikaHallGameSettingsPtr; } FORCEINLINE UPikaUIGameWarning* PikaGetGameWarning() const { return PikaGameWarningPtr; } FORCEINLINE UPikaUIWebBrowser* PikaGetCurrentWebBrowser() const { return PikaCurrentWebBrowserPtr; } public: /***********************动画相关**************************/ void PikaInitAnimation(); //主UMG淡入淡出 void PikaMainUMGFadeInAndFadeOut(bool IsOut, PikaqiuEAnimationState NewAnimationState = PikaqiuEAnimationState::EA_Empty); //敲击动画淡入淡出 void PikaClickedMenuFadeInAndFadeOut(bool IsOut, PikaqiuEAnimationState NewAnimationState = PikaqiuEAnimationState::EA_Empty); //窗口状态 /*void PikaSetWindowsState(bool IsState); //获取淡入淡出列表设置 FORCEINLINE UWidgetAnimation* PikaGetBeginAndEndSaveAndSettingUMGFadeInAndFadeOut(bool IsBeign = true) const { return IsBeign ? GameSaveSettingsBeginAnimation : GameSaveSettingsEndAnimation; }*/ //窗口淡入淡出 void PikaWindowsFadeInAndFadeOut(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None); private: //动画完成播放后执行该函数 virtual void OnAnimationFinished_Implementation(const UWidgetAnimation* Animation) override; //动画开始播放后执行该函数 virtual void OnAnimationStarted_Implementation(const UWidgetAnimation* Animation) override; private: //控件相关 USizeBox* PikaBoxKeyHallList; USizeBox* PikaBoxWebList; USizeBox* PikaBoxWarningList; USizeBox* PikaBoxWindowList; UWidgetSwitcher* PikaBoxList; //UMG类相关 UPikaUIHallGameSetting* PikaHallGameSettingsPtr; UPikaUIReadAndWrite* PikaReadAndWritePtr; UPikaUIHallKey* PikaHallKeyPtr; UPikaGameErrorHint* PikaGamePromptErrorPtr; UPikaUIGameWarning* PikaGameWarningPtr; UPikaUIWebBrowser* PikaCurrentWebBrowserPtr; //UUI_MoveToLog* MoveToLogPtr; //动画相关 UWidgetAnimation* PikaSaveSettingAnimationBegin; UWidgetAnimation* PikaSaveSettingAnimationEnd; UWidgetAnimation* PikaMaskAnimationBegin; UWidgetAnimation* PikaMaskAnimationEnd; UWidgetAnimation* PikaGradualChangeAnimationBegin; UWidgetAnimation* PikaGradualChangeAnimationEnd; };
PikaUIMainHall.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIMainHall.h" UPikaUIMainHall::UPikaUIMainHall() { } void UPikaUIMainHall::PikaDrawUIToScreen() { //UE控件相关 PikaBoxKeyHallList = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaBoxKeyHallListName)); PikaBoxList = Cast<UWidgetSwitcher>(GetWidgetFromName(PikaBoxListName)); PikaBoxWarningList = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaBoxWarningListName)); PikaBoxWindowList = Cast<USizeBox>(GetWidgetFromName(PikaBoxWindowListName)); PikaBoxWebList = Cast<USizeBox>(PikaqiuGetBlueprintWidget(PikaBoxWebName)); //PikaMoveToLog = Cast<UUI_MoveToLog>(GetWidgetFromName(MoveToLogName)); //动画相关 PikaSaveSettingAnimationBegin = PikaqiuGetNameWidgetAnimation(PikaSaveSettingAnimationBeginName); PikaSaveSettingAnimationEnd = PikaqiuGetNameWidgetAnimation(PikaSaveSettingAnimationEndName); PikaMaskAnimationBegin = PikaqiuGetNameWidgetAnimation(PikaMaskAnimationBeginName); PikaMaskAnimationEnd = PikaqiuGetNameWidgetAnimation(PikaMaskAnimationEndName); PikaGradualChangeAnimationBegin = PikaqiuGetNameWidgetAnimation(PikaGradualChangeAnimationBeginName); PikaGradualChangeAnimationEnd = PikaqiuGetNameWidgetAnimation(PikaGradualChangeAnimationEndName); ////////////////////////////////////////////////////////////////////////// if (GetWorld()) { //添加我们的打印 if (PikaGamePromptErrorClass && PikaBoxWindowList) { PikaGamePromptErrorPtr = CreateWidget<UPikaGameErrorHint>(GetWorld(), PikaGamePromptErrorClass); check(PikaGamePromptErrorPtr); PikaGamePromptErrorPtr->PikaUIDataPtr = PikaUIDataPtr; //将PikaGamePromptErrorPtr添加到size Box里 PikaAddSizeBox(PikaBoxWindowList, PikaGamePromptErrorPtr); PikaGamePromptErrorPtr->PikaSetMainHall(this); PikaGamePromptErrorPtr->PikaDrawUIToScreen(); } //添加我们的HallKey if (PikaHallKeyClass && PikaBoxKeyHallList) { PikaHallKeyPtr = CreateWidget<UPikaUIHallKey>(GetWorld(), PikaHallKeyClass); check(PikaHallKeyPtr); PikaHallKeyPtr->PikaUIDataPtr = PikaUIDataPtr; //将PikaHallKeyPtr添加到WidgetSwitcher类的实例PikaBoxList里 PikaAddSizeBox(PikaBoxKeyHallList, PikaHallKeyPtr); PikaHallKeyPtr->PikaSetMainHall(this); PikaHallKeyPtr->PikaDrawUIToScreen(); } //添加Box列表 if (PikaBoxList) { //隐藏自己 PikaBoxList->SetVisibility(ESlateVisibility::Hidden); //获取存储 if (PikaReadAndWriteClass) { PikaReadAndWritePtr = CreateWidget<UPikaUIReadAndWrite>(GetWorld(), PikaReadAndWriteClass); check(PikaReadAndWritePtr); PikaReadAndWritePtr->PikaUIDataPtr = PikaUIDataPtr; //将PikaReadAndWritePtr添加到WidgetSwitcher类的实例PikaBoxList里 PikaBoxList->AddChild(PikaReadAndWritePtr); PikaReadAndWritePtr->PikaSetMainHall(this); PikaReadAndWritePtr->PikaDrawUIToScreen(); //ReadAndWrite->SetButtonText(TD_WText[0], TD_WText[1]); PikaReadAndWritePtr->PikaSetNewButtonType(PikaETDButtonType::LoadingGame); } //游戏设置 if (PikaHallGameSettingsClass) { PikaHallGameSettingsPtr = CreateWidget<UPikaUIHallGameSetting>(GetWorld(), PikaHallGameSettingsClass); check(PikaHallGameSettingsPtr); PikaHallGameSettingsPtr->PikaUIDataPtr = PikaUIDataPtr; //将PikaHallGameSettingsPtr添加到WidgetSwitcher里 PikaBoxList->AddChild(PikaHallGameSettingsPtr); PikaHallGameSettingsPtr->PikaSetMainHall(this); PikaHallGameSettingsPtr->PikaDrawUIToScreen(); } } //游戏提示 if (PikaGameWarningClass, PikaBoxWarningList) { //隐藏自己 PikaBoxWarningList->SetVisibility(ESlateVisibility::Hidden); PikaGameWarningPtr = CreateWidget<UPikaUIGameWarning>(GetWorld(), PikaGameWarningClass); check(PikaGameWarningPtr); PikaGameWarningPtr->PikaUIDataPtr = PikaUIDataPtr; //将PikaGameWarningPtr添加到WidgetSwitcher类的实例PikaBoxList里 PikaAddSizeBox(PikaBoxWarningList, PikaGameWarningPtr); PikaGameWarningPtr->PikaSetMainHall(this); PikaGameWarningPtr->PikaDrawUIToScreen(); } /*//添加网络web浏览功能 if (WebBrowserClass, BoxWebList) { CurrentWebBrowser = CreateWidget<UUI_WebBrowser>(GetWorld(), WebBrowserClass); check(CurrentWebBrowser); CurrentWebBrowser->GameUIData = GameUIData; //添加进去 AddUSizeBox(BoxWebList, CurrentWebBrowser); CurrentWebBrowser->SetMainHall(this); CurrentWebBrowser->DrawUIToSrceen(); BoxWebList->SetVisibility(ESlateVisibility::Hidden); } if (MoveToLog) { MoveToLog->SetMianHall(this); }*/ } //初始化动画 PikaInitAnimation(); } void UPikaUIMainHall::RemoveFromViewport() { //UMG类相关 if (PikaHallGameSettingsPtr) PikaHallGameSettingsPtr->RemoveFromViewport(); PikaHallGameSettingsPtr = NULL; if (PikaReadAndWritePtr) PikaReadAndWritePtr->RemoveFromViewport(); PikaReadAndWritePtr = NULL; if (PikaHallKeyPtr) PikaHallKeyPtr->RemoveFromViewport(); PikaHallKeyPtr = NULL; if (PikaGamePromptErrorPtr) PikaGamePromptErrorPtr->RemoveFromViewport(); PikaGamePromptErrorPtr = NULL; if (PikaGameWarningPtr) PikaGameWarningPtr->RemoveFromViewport(); PikaGameWarningPtr = NULL; if (PikaCurrentWebBrowserPtr) PikaCurrentWebBrowserPtr->RemoveFromViewport(); PikaCurrentWebBrowserPtr = NULL; Super::RemoveFromViewport(); } void UPikaUIMainHall::PikaSetWarningWindowsState(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= PikaEButtonSureType::BST_None*/) { if (IsVisibles) { //显示警告框 PikaGameWarningPtr->PikaSetText(MyWidget); PikaBoxWarningList->SetVisibility(ESlateVisibility::Visible); } else { PikaBoxWarningList->SetVisibility(ESlateVisibility::Hidden); } } void UPikaUIMainHall::PikaSetBoxListDisplayOrder(PikaBoxListType::Type BoxListType) { if (PikaBoxList) PikaBoxList->SetActiveWidgetIndex(BoxListType); } PikaBoxListType::Type UPikaUIMainHall::PikaGetBoxListDisplayOrder() const { if (PikaBoxList) return (PikaBoxListType::Type)PikaBoxList->GetActiveWidgetIndex(); return (PikaBoxListType::Type)INDEX_NONE; } void UPikaUIMainHall::PikaInitAnimation() { PikaMainUMGFadeInAndFadeOut(true); if (PikaBoxWindowList) PikaBoxWindowList->SetVisibility(ESlateVisibility::Hidden); if (PikaBoxList) PikaBoxList->SetVisibility(ESlateVisibility::Hidden); } void UPikaUIMainHall::PikaMainUMGFadeInAndFadeOut(bool IsOut, PikaqiuEAnimationState NewAnimationState /*= PikaqiuEAnimationState::EA_Empty*/) { if (IsOut) { if (PikaGradualChangeAnimationBegin) { PlayAnimation(PikaGradualChangeAnimationBegin); PikaGradualChangeAnimationBegin->PikaqiuSetAnimationState(NewAnimationState); } } else { if (PikaGradualChangeAnimationEnd) { PlayAnimation(PikaGradualChangeAnimationEnd); PikaGradualChangeAnimationEnd->PikaqiuSetAnimationState(NewAnimationState); } } } void UPikaUIMainHall::PikaClickedMenuFadeInAndFadeOut(bool IsOut, PikaqiuEAnimationState NewAnimationState /*= EAnimationState::EA_Empty*/) { if (IsOut) { if (PikaSaveSettingAnimationBegin) { //设置动画状态 if (NewAnimationState != PikaqiuEAnimationState::EA_Empty) PikaSaveSettingAnimationBegin->PikaqiuSetAnimationState(NewAnimationState); //开始动画开始 PlayAnimation(PikaSaveSettingAnimationBegin); } } else { if (PikaSaveSettingAnimationEnd) { //设置动画状态 if (NewAnimationState != PikaqiuEAnimationState::EA_Empty) PikaSaveSettingAnimationEnd->PikaqiuSetAnimationState(NewAnimationState); //开始动画结束 PlayAnimation(PikaSaveSettingAnimationEnd); } } } void UPikaUIMainHall::PikaWindowsFadeInAndFadeOut(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= EButtonSureType::BST_None*/) { if (IsVisibles) { if (PikaMaskAnimationBegin) PlayAnimation(PikaMaskAnimationBegin); } else { if (PikaMaskAnimationEnd) PlayAnimation(PikaMaskAnimationEnd); } } void UPikaUIMainHall::OnAnimationFinished_Implementation(const UWidgetAnimation* Animation) { if (PikaSaveSettingAnimationEnd == Animation) { //PikaSaveSettingAnimationEnd动画播放完成 if (Animation->PikaqiuGetAnimationState() == PikaqiuEAnimationState::BST_QuitMeun) { PikaGetBoxList()->SetVisibility(ESlateVisibility::Hidden); } } } void UPikaUIMainHall::OnAnimationStarted_Implementation(const UWidgetAnimation* Animation) { }
PikaUIReadAndWrite.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUISaveLoadBar.h" #include "ScrollBox.h" #include "PikaUIGameMenu.h" #include "TextBlock.h" #include "PikaUIReadAndWrite.generated.h" class UPikaUIMainHall; class UPikaUIGameMenu; namespace PikaEClickedSaveType { enum Type { CST_UnClicked, CST_HasStruck, CST_Max }; } enum class PikaETDButtonType : uint8 { LoadingGame, SaveGame, Max }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIReadAndWrite : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaLoadingListTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaReturnListTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaReturnListButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaLoadingGameButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSaveListButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TSubclassOf<UPikaUISaveLoadBar> PikaSaveLoadBarClass; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FText PikaCoverText; //准备读取该进度 uint8 PikaIsLoading : 1; //当前类型 PikaETDButtonType PikaButtonType; public: //存储界面上,按钮是显示存储还是载入 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") TArray<FText> Pika_WText; UPikaUIReadAndWrite(); //checkBox存储类型,表示是否产生了checkBox的点击事件 TEnumAsByte<PikaEClickedSaveType::Type> PikaClickedSaveType; //当前游戏存储区域Bar号码 (SaveBarNumber) int32 PikaCurrentSaveGameBoxNumber; //存储游戏的编号 int32 PikaCurrentGameArchiveNumber; //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) override; //设置显示字体 void PikaSetButtonText(FText Text_A); void PikaReadArchive(); //负责打印GameLOG virtual void PikaLogPrintf(FString MyString) override; virtual void PikaOnClickedWidget(UWidget* MyWidget) override; //存储游戏,参数为存储内容时是覆盖操作还是新建操作 void PikaSaveArchiveSlot(bool IsCopy); FORCEINLINE UPikaUIMainHall* PikaGetMainHall()const { return PikaMainHall; } FORCEINLINE UPikaUIGameMenu* PikaGetGameMenu()const { return PikaUIGameMenu; } void PikaSetMainHall(UPikaUIMainHall* NewWidget) { PikaMainHall = NewWidget; } void PikaSetGameMenu(UPikaUIGameMenu* NewWidget) { PikaUIGameMenu = NewWidget; } //checkBox显示 void PikaShowOneClickButton(int32 NumberBIndex); void PikaShowOneClickButton(); //设置按键类型 void PikaSetNewButtonType(PikaETDButtonType NewButtonType) { PikaButtonType = NewButtonType; } //清除第几号存储 void PikaClearNumberSave(int32 CurrentDelectNumber = INDEX_NONE); private: UPikaUIMainHall* PikaMainHall; UButton* PikaReturnListButton; UButton* PikaLoadingGameButton; UTextBlock* PikaReturnListText; UTextBlock* PikaLoadingListText; UScrollBox* PikaSaveListButton; TArray<UPikaUISaveLoadBar*> PikaSaveLoadBarArrayEnter; UPikaUIGameMenu* PikaUIGameMenu; };
PikaUIReadAndWrite.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIReadAndWrite.h" UPikaUIReadAndWrite::UPikaUIReadAndWrite() { PikaCurrentGameArchiveNumber = INDEX_NONE; PikaCurrentSaveGameBoxNumber = INDEX_NONE; PikaIsLoading = false; PikaButtonType = PikaETDButtonType::Max; PikaClickedSaveType = PikaEClickedSaveType::CST_UnClicked; } void UPikaUIReadAndWrite::PikaDrawUIToScreen() { PikaReturnListButton = PikaGetButtonFromBlueprint(PikaReturnListButtonName); PikaLoadingGameButton = PikaGetButtonFromBlueprint(PikaLoadingGameButtonName); PikaSaveListButton = Cast<UScrollBox>(PikaqiuGetBlueprintWidget(PikaSaveListButtonName)); PikaReturnListText = Cast<UTextBlock>(GetWidgetFromName(PikaReturnListTextName)); PikaLoadingListText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaLoadingListTextName)); //读取存档 PikaReadArchive(); } void UPikaUIReadAndWrite::PikaSetWarningWindowsState(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= PikaEButtonSureType::BST_None*/) { if (PikaMainHall) { PikaMainHall->PikaSetWarningWindowsState(IsVisibles, StateTime, MyWidget, MyButtonSureType); } if (PikaUIGameMenu) { PikaUIGameMenu->PikaSetWarningWindowsState(IsVisibles, StateTime, MyWidget, MyButtonSureType); } } void UPikaUIReadAndWrite::PikaSetButtonText(FText Text_A) { if (PikaLoadingListText) PikaLoadingListText->SetText(Text_A); } void UPikaUIReadAndWrite::PikaReadArchive() { if (PikaGetGameInstance() && GetWorld()) { //创建20可以存档的区域 if (PikaSaveLoadBarClass) { //注册 for (int32 i = 0; i < Pika_SAVE_SaveBarNumber; i++) { UPikaUISaveLoadBar* PikaSlotBar = CreateWidget<UPikaUISaveLoadBar>(GetWorld(), PikaSaveLoadBarClass); if (PikaSlotBar) { //初始化绘制信息 PikaSlotBar->PikaDrawUIToScreen(); //显示默认的存储的信息 PikaSlotBar->PikaClearSaveGameSlot(); //传递自己 PikaSlotBar->PikaSetReadAndWrite(this); //存储游戏序列 PikaSlotBar->PikaSaveGameBoxNumber = i; //添加如容器 PikaSaveLoadBarArrayEnter.Add(PikaSlotBar); //添加到列表 if (PikaSaveListButton) { PikaSaveListButton->AddChild(PikaSlotBar); } else { PIKA_LOG(FString::Printf(TEXT("SaveListButton == NULL ,Failed to create %i storage"), i)); } } else { PIKA_LOG(FString::Printf(TEXT("Failed to create %i storage"), i)); } } } //游戏开始读取我们的存档 if (PIKA_ISSAVE_SLOT(PIKA_SAVE_SLOT_NAME, 0)) { //读取游戏存档在本地,并且验证存档 UPikaGameSaveData* PikaGameSaveData = PikaGetGameInstance()->PikaVerificationSaveData(); //获取存档信息 if (PikaGameSaveData) { int32 PikaCurrentIndex = 0; //用读取的本地存档还原bar里的数据 for (int32 PikaCurrentSaveValue : PikaGameSaveData->PikaReadGameData.PikaSaveGameBoxNumberArray) { if (PikaCurrentSaveValue != INDEX_NONE) { if (PikaSaveLoadBarArrayEnter.IsValidIndex(PikaCurrentIndex)) { PikaSaveLoadBarArrayEnter[PikaCurrentIndex]->PikaSetSaveGameText(PikaCurrentSaveValue, FText::FromString(PikaGameSaveData->PikaReadGameData.PikaSaveDataText[PikaCurrentSaveValue])); } else { PIKA_LOG(FString::Printf(TEXT("Nothingness %i"), PikaCurrentIndex)); } } PikaCurrentIndex++; } } else { PIKA_LOG("GameSaveData read failed!!"); } } else { PIKA_LOG("There is no stored data!!"); } } else { PIKA_LOG("Not obtained TowerDefenceGameInstance!!"); } } void UPikaUIReadAndWrite::PikaLogPrintf(FString MyString) { } //通过PikaGetButtonFromBlueprint获取的Button,在本类的基类UPikaUIWidgetBase里绑定 void UPikaUIReadAndWrite::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaLoadingGameButton) { check(PikaLoadingListText); //必须是敲击状态 if (PikaClickedSaveType == PikaEClickedSaveType::CST_HasStruck) { //是读取界面 if (PikaButtonType == PikaETDButtonType::LoadingGame) { if (PikaGetGameInstance()) { //检查当选中的PikaUISaveLoadBar里,是否能读取成功 PikaIsLoading = PikaGetGameInstance()->PikaIsLoadingGameData(PikaCurrentGameArchiveNumber); if (PikaIsLoading) { //存档读取成功 PIKA_LOG("Loading Successfully"); //激活关闭菜单功能 if (PikaGetMainHall() && PikaGetMainHall()->PikaGetBoxList()) { //GetMainHall()->ClickedMenuFadeInAndFadeOut(false, EAnimationState::EA_ReadyLoading); //设置界面不可敲击 PikaGetMainHall()->SetVisibility(ESlateVisibility::HitTestInvisible); } /*//播放开始游戏动画 if (GetTowerDefenceHallGameMode()) { GetTowerDefenceHallGameMode()->PlayCurrentCameraAnimation(ECameraArray::Camera_IntoGame, EMatineeArray::Matinee_Max, TD_CAMARE_BLENDTIME + 1); }*/ //存储读档序列 PikaGetGameInstance()->PikaTmpArchive = PikaCurrentGameArchiveNumber; if (GetWorld()) UGameplayStatics::OpenLevel(GetWorld(), "PikaGodStone_Level_Main_01"); } else { PIKA_LOG("Loading Failure"); } } else { PIKA_LOG("GetTowerDefenceGameInstance() = NULL!"); } }//是存储界面 else if (PikaButtonType == PikaETDButtonType::SaveGame) { if (PikaGetPlayerController() && PikaGetGameInstance()) { //游戏存储 if (PikaCurrentGameArchiveNumber == INDEX_NONE)//存储到一个空的存储条里面 { PikaSaveArchiveSlot(false); } else//需要覆盖一个存档,这个时候会跳出一个弹窗,确定是否要覆盖 { PikaSaveArchiveSlot(true); /*//打开在大厅 if (GetMainHall() && GetMainHall()->GetGameWarning()) { //弹窗状态设置为显示 SetWarningWindowsState(true, 0, FString::Printf(TEXT("%s # %i?"), *CoverText.ToString(), CurrentGameArchiveNumber), EButtonSureType::BST_CoverSave); } //打开在游戏 if (GetGameMenu() && GetGameMenu()->GetMianScreen() && GetGameMenu()->GetMianScreen()->GetGameWarning()) { SetWarningWindowsState(true, 0, FString::Printf(TEXT("%s # %i?"), *CoverText.ToString(), CurrentGameArchiveNumber), EButtonSureType::BST_CoverSave); }*/ } } else { PIKA_LOG("GetTowerDefencePlayerController() = NULL!"); } } } } if (MyWidget == PikaReturnListButton) { //取消 //隐藏自己 if (PikaUIGameMenu) PikaUIGameMenu->PikaGetMainInterface()->PikaGetBoxSaveGameArray()->SetVisibility(ESlateVisibility::Hidden);; //隐藏自己 if (PikaMainHall) PikaMainHall->PikaGetBoxList()->SetVisibility(ESlateVisibility::Hidden);; /*if (TDButtonType == ETDButtonType::LoadingGame) { if (GetMainHall() && GetMainHall()->GetBoxList()) { GetMainHall()->ClickedMenuFadeInAndFadeOut(false); } } else if (TDButtonType == ETDButtonType::SaveGame) { if (GetGameMenu() && GetGameMenu()->GetMianScreen()) { GetGameMenu()->GetMianScreen()->ClickedMenuFadeInAndFadeOut(false); } }*/ } } //存储游戏,参数为存储内容时是覆盖操作还是新建操作 void UPikaUIReadAndWrite::PikaSaveArchiveSlot(bool IsCopy) { //标记存档序列 if (PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon) PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaSaveCount++; if (IsCopy) { //覆盖,指定要覆盖的存档 //PikaCurrentSaveGameBoxNumber的值为点击了某个存档bar类PikaUISaveLoadBar后,在PikaUISaveLoadBar类里设置的 //------------------------------------ //在已有的存档上进行覆盖存档时,由PikaUIReadAndWrite::PikaReadArchive读取的本地存档, //并将PikaCurrentGameArchiveNumber的值保存在PikaUISaveLoadBar里的PikaGameArchiveNumber属性里 //点击某个PikaUISaveLoadBar类的按钮后, //通过读取PikaUISaveLoadBar类里的PikaGameArchiveNumber属性就能得到PikaCurrentGameArchiveNumber的值 bool PikaIsSave = PikaGetPlayerController()->PikaSaveGameData(PikaFSaveSlotDataChannel(PikaCurrentSaveGameBoxNumber, PikaCurrentGameArchiveNumber)); if (PikaIsSave) { //更新显示日期 //上面的PikaSaveGameData成功时,新的日期已经存档,此处再次读取存档,用来更新界面 FText PikaNewText = PikaGetPlayerController()->PikaGetSaveInformation(PikaCurrentGameArchiveNumber); if (PikaCurrentSaveGameBoxNumber >= 0 && PikaCurrentSaveGameBoxNumber < PikaSaveLoadBarArrayEnter.Num()) { PikaSaveLoadBarArrayEnter[PikaCurrentSaveGameBoxNumber]->PikaSetSaveGameText(PikaCurrentGameArchiveNumber, PikaNewText); PikaSaveLoadBarArrayEnter[PikaCurrentSaveGameBoxNumber]->PikaUpdateClickState(); } PIKA_LOG("Save Successfully"); } else { PIKA_LOG("Save Failure"); } } else//新建 { //PikaGetCurrentSaveArchiveNumber:获取当前存档的编号 int32 PikaCurrenMaxArchiveNumber = PikaGetGameInstance()->PikaGetCurrentSaveArchiveNumber(); if (PikaCurrenMaxArchiveNumber == INDEX_NONE) { PIKA_LOG(" GetTowerDefenceGameInstance()->GetCurrentSaveArchiveNumber() = INDEX_NONE,Is error!!"); return; } //将最新的存档数PikaCurrenMaxArchiveNumber作为下一个存档的一个序列号角标 //PikaCurrentSaveGameBoxNumber的值为点击了某个存档bar类PikaUISaveLoadBar后,在PikaUISaveLoadBar类里设置的 bool PikaIsSave = PikaGetPlayerController()->PikaSaveGameData(PikaFSaveSlotDataChannel(PikaCurrentSaveGameBoxNumber, PikaCurrenMaxArchiveNumber)); if (PikaIsSave) { //更新显示日期 FText PikaNewTDText = PikaGetPlayerController()->PikaGetSaveInformation(PikaCurrenMaxArchiveNumber); if (PikaCurrentSaveGameBoxNumber >= 0 && PikaCurrentSaveGameBoxNumber < PikaSaveLoadBarArrayEnter.Num()) { PikaSaveLoadBarArrayEnter[PikaCurrentSaveGameBoxNumber]->PikaSetSaveGameText(PikaCurrenMaxArchiveNumber, PikaNewTDText); PikaSaveLoadBarArrayEnter[PikaCurrentSaveGameBoxNumber]->PikaUpdateClickState(); } PIKA_LOG("Save Successfully"); } else { PIKA_LOG("Save Failure"); } } } //checkBox显示 void UPikaUIReadAndWrite::PikaShowOneClickButton(int32 NumberBIndex) { for (int32 i = 0; i < PikaSaveLoadBarArrayEnter.Num(); i++) { if (PikaSaveLoadBarArrayEnter[i]->PikaSaveGameBoxNumber == NumberBIndex) PikaSaveLoadBarArrayEnter[i]->PikaShowOneCheckBox(true); else PikaSaveLoadBarArrayEnter[i]->PikaShowOneCheckBox(false); } } //checkBox显示 void UPikaUIReadAndWrite::PikaShowOneClickButton() { for (int32 i = 0; i < PikaSaveLoadBarArrayEnter.Num(); i++) { if (PikaSaveLoadBarArrayEnter.IsValidIndex(i)) { PikaSaveLoadBarArrayEnter[i]->PikaShowOneCheckBox(false); } } } //还原 void UPikaUIReadAndWrite::PikaClearNumberSave(int32 CurrentDelectNumber /*= INDEX_NONE*/) { for (int32 i = 0; i < PikaSaveLoadBarArrayEnter.Num(); i++) { if (PikaSaveLoadBarArrayEnter.IsValidIndex(i)) { if (PikaSaveLoadBarArrayEnter[i]->PikaGameArchiveNumber == CurrentDelectNumber) { //还原数据显示 PikaSaveLoadBarArrayEnter[i]->PikaClearSaveGameSlot(); break; } } } PikaCurrentSaveGameBoxNumber = INDEX_NONE; PikaCurrentGameArchiveNumber = INDEX_NONE; PikaClickedSaveType = PikaEClickedSaveType::CST_UnClicked; PikaShowOneClickButton(); }
PikaUISaveLoadBar.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "CheckBox.h" #include "Button.h" #include "PikaUISaveLoadBar.generated.h" class UPikaUIReadAndWrite; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUISaveLoadBar : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGameTextBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaClickedBoxButtonName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSaveGameDataBlockName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaDeleteMyDataButtonName; //删除存档时,警告框上显示的文件 //确定删除该存档吗,皮卡~~~ UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FText PikadeleteText; //无存档时的默认显示文本 UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FText PikaDefaultNoDataText; public: //游戏bar序列,在PikaUIReadAndWrite::PikaReadArchive里循环生成本类时,将循环的index存入该值 int32 PikaSaveGameBoxNumber; //游戏存储后,本存档存档编号,默认值为-1 int32 PikaGameArchiveNumber; UPikaUISaveLoadBar(); //调用去初始化我们的UI virtual void PikaDrawUIToScreen() override; //负责打印GameLOG virtual void PikaLogPrintf(FString MyString) override; UFUNCTION() virtual void PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget); void PikaShowOneCheckBox(bool ClickedWidget); void PikaUpdateClickState(); virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) override; virtual void PikaOnClickedWidget(UWidget* MyWidget) override; //设置字体数据信息显示 void PikaSetSaveGameText(int32 IndexSaveData, FText MySaveText); //清除游戏存储显示节点 void PikaClearSaveGameSlot(); void PikaSetReadAndWrite(UPikaUIReadAndWrite* NewReadAndWrite) { PikaReadAndWrite = NewReadAndWrite; } private: UTextBlock* PikaGameTextBlock; UTextBlock* PikaSaveGameDataBlock; UButton* PikaDeleteMyDataButton; UCheckBox* PikaClickedBoxButton; UPikaUIReadAndWrite* PikaReadAndWrite; };
PikaUISaveLoadBar.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUISaveLoadBar.h" UPikaUISaveLoadBar::UPikaUISaveLoadBar() { PikaGameArchiveNumber = -1; PikaSaveGameBoxNumber = -1; } void UPikaUISaveLoadBar::PikaDrawUIToScreen() { PikaGameTextBlock = Cast<UTextBlock>(GetWidgetFromName(PikaGameTextBlockName)); PikaSaveGameDataBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaSaveGameDataBlockName)); PikaDeleteMyDataButton = PikaGetButtonFromBlueprint(PikaDeleteMyDataButtonName); PikaClickedBoxButton = Cast<UCheckBox>(PikaqiuGetBlueprintWidget(PikaClickedBoxButtonName)); //绑定按键 if (PikaClickedBoxButton) PikaClickedBoxButton->PikaqiuOnCheckStateChanged.AddDynamic(this, &UPikaUISaveLoadBar::PikaClickedCheckBox); } void UPikaUISaveLoadBar::PikaLogPrintf(FString MyString) { } void UPikaUISaveLoadBar::PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget) { if (MyWidget == PikaClickedBoxButton) { if (PikaReadAndWrite) { //显示当前游戏敲击显示 //PikaSaveGameBoxNumber的值为PikaUIReadAndWrite类循环加载本类里时用循环的index设置的 PikaReadAndWrite->PikaShowOneClickButton(PikaSaveGameBoxNumber); //设置当前存储游戏的载体数字 PikaUpdateClickState(); //打印选择第几个存储 PIKA_LOG(FString::Printf(TEXT("Select archive # %i"), PikaGameArchiveNumber)); } } } void UPikaUISaveLoadBar::PikaShowOneCheckBox(bool ClickedWidget) { if (PikaClickedBoxButton) { if (ClickedWidget) PikaClickedBoxButton->SetCheckedState(ECheckBoxState::Checked); else PikaClickedBoxButton->SetCheckedState(ECheckBoxState::Unchecked); } } void UPikaUISaveLoadBar::PikaUpdateClickState() { if (PikaReadAndWrite) { PikaReadAndWrite->PikaCurrentSaveGameBoxNumber = PikaSaveGameBoxNumber; //游戏存储后,本存档存档编号,默认值为-1 //PikaGameArchiveNumber该值由PikaUIReadAndWrite类调用PikaDrawUIToScreen函数进行加载时, //由PikaUIReadAndWrite::PikaReadArchive函数调用本类里的PikaSetSaveGameText函数进行设置 //PikaUIReadAndWrite::PikaSaveArchiveSlot的新建逻辑时,PikaGameArchiveNumber为-1 PikaReadAndWrite->PikaCurrentGameArchiveNumber = PikaGameArchiveNumber; PikaReadAndWrite->PikaClickedSaveType = PikaEClickedSaveType::CST_HasStruck; } } void UPikaUISaveLoadBar::PikaSetWarningWindowsState(bool IsVisibles, float StateTime /*= 0*/, FString MyWidget /*= ""*/, TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType /*= PikaEButtonSureType::BST_None*/) { if (PikaReadAndWrite) { PikaReadAndWrite->PikaSetWarningWindowsState(IsVisibles, StateTime, MyWidget, MyButtonSureType); } } void UPikaUISaveLoadBar::PikaOnClickedWidget(UWidget* MyWidget) { if (MyWidget == PikaDeleteMyDataButton) { if (PikaGameArchiveNumber != INDEX_NONE) { //游戏大厅 if (PikaReadAndWrite && PikaReadAndWrite->PikaGetMainHall() && PikaReadAndWrite->PikaGetMainHall()->PikaGetGameWarning()) { //弹窗状态设置为显示 PikaSetWarningWindowsState(true, 0, FString::Printf(TEXT("%s %i"), *PikadeleteText.ToString(), PikaGameArchiveNumber), PikaEButtonSureType::BST_DeleteSave); //设置是哪个控件 PikaReadAndWrite->PikaGetMainHall()->PikaGetGameWarning()->PikaCurrentGameArchiveNumber = PikaGameArchiveNumber; PikaReadAndWrite->PikaGetMainHall()->PikaGetGameWarning()->PikaSetGameButtonSureType(PikaEButtonSureType::BST_DeleteSave); //播放背景模糊动画 PikaReadAndWrite->PikaGetMainHall()->PikaWindowsFadeInAndFadeOut(true); } //游戏 if (PikaReadAndWrite && PikaReadAndWrite->PikaGetGameMenu() && PikaReadAndWrite->PikaGetGameMenu()->PikaGetMainInterface() && PikaReadAndWrite->PikaGetGameMenu()->PikaGetMainInterface()->PikaGetGameWarning()) { //弹窗状态设置为显示 PikaSetWarningWindowsState(true, 0, FString::Printf(TEXT("%s %i"), *PikadeleteText.ToString(), PikaGameArchiveNumber), PikaEButtonSureType::BST_DeleteSave); //设置是哪个控件 PikaReadAndWrite->PikaGetGameMenu()->PikaGetMainInterface()->PikaGetGameWarning()->PikaCurrentGameArchiveNumber = PikaGameArchiveNumber; PikaReadAndWrite->PikaGetGameMenu()->PikaGetMainInterface()->PikaGetGameWarning()->PikaSetGameButtonSureType(PikaEButtonSureType::BST_DeleteSave); } } else { PIKA_LOG("No archive"); } } } //设置字体数据信息显示 void UPikaUISaveLoadBar::PikaSetSaveGameText(int32 IndexSaveData, FText MySaveText) { //赋值我们的存档序列 PikaGameArchiveNumber = IndexSaveData; //第几个存档 if (PikaGameTextBlock) PikaGameTextBlock->SetText(FText::FromString(FString::Printf(TEXT("Storage number %i"), IndexSaveData))); //存档日期 if (PikaSaveGameDataBlock) PikaSaveGameDataBlock->SetText(MySaveText); } void UPikaUISaveLoadBar::PikaClearSaveGameSlot() { if(!(PikaDefaultNoDataText.IsEmpty())) PikaSetSaveGameText(INDEX_NONE, PikaDefaultNoDataText); }
PikaUITowerInfo.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "MultiLineEditableTextBox.h" #include "PikaUITowerInfo.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUITowerInfo : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaCharacterNameBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaComsumeGlodBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaCharacterHealthBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaCharacterAttackBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaCharacterArmorBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaCharacterAttackSpeedBlockName; UPROPERTY(EditDefaultsOnly, Category = UI) FName PikaIntroductionName; public: FPikaCharacterInformationWidget* PikaCharacterInformationWidget; //作为初始化实例 virtual void PikaDrawUIToScreen() override; //只要角色值变动机会更新 void PikaUpdateCharacterInformation(); private: UTextBlock* PikaCharacterNameBlock; UTextBlock* PikaComsumeGlodBlock; UTextBlock* PikaCharacterHealthBlock; UTextBlock* PikaCharacterAttackBlock; UTextBlock* PikaCharacterArmorBlock; UTextBlock* PikaCharacterAttackSpeedBlock; UMultiLineEditableTextBox* PikaIntroduction; protected: //virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent)override; };
PikaUITowerInfo.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUITowerInfo.h" void UPikaUITowerInfo::PikaDrawUIToScreen() { if (!PikaCharacterNameBlock) PikaCharacterNameBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterNameBlockName)); if (!PikaComsumeGlodBlock) PikaComsumeGlodBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaComsumeGlodBlockName)); if (!PikaCharacterHealthBlock) PikaCharacterHealthBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterHealthBlockName)); if (!PikaCharacterAttackBlock) PikaCharacterAttackBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackBlockName)); if (!PikaCharacterArmorBlock) PikaCharacterArmorBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterArmorBlockName)); if (!PikaCharacterAttackSpeedBlock) PikaCharacterAttackSpeedBlock = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaCharacterAttackSpeedBlockName)); if (!PikaIntroduction) PikaIntroduction = Cast<UMultiLineEditableTextBox>(PikaqiuGetBlueprintWidget(PikaIntroductionName)); } void UPikaUITowerInfo::PikaUpdateCharacterInformation() { if (PikaCharacterInformationWidget) { if (PikaCharacterNameBlock) PikaCharacterNameBlock->SetText(FText::FromName(PikaCharacterInformationWidget->PikaCharacterName)); if (PikaComsumeGlodBlock) PikaComsumeGlodBlock->SetText(FText::AsNumber(PikaCharacterInformationWidget->PikaComsumeGlod)); if (PikaCharacterHealthBlock) PikaCharacterHealthBlock->SetText(FText::AsNumber(PikaCharacterInformationWidget->PikaCharacterHealth)); if (PikaCharacterAttackBlock) PikaCharacterAttackBlock->SetText(FText::AsNumber(PikaCharacterInformationWidget->PikaCharacterAttack)); if (PikaCharacterArmorBlock) PikaCharacterArmorBlock->SetText(FText::AsNumber(PikaCharacterInformationWidget->PikaCharacterArmor)); if (PikaCharacterAttackSpeedBlock) PikaCharacterAttackSpeedBlock->SetText(FText::AsNumber(PikaCharacterInformationWidget->PikaCharacterAttackSpeed)); if (PikaIntroduction) PikaIntroduction->SetText(PikaCharacterInformationWidget->PikaCharacterIntroduction); } }
PikaUIWebBrowser.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaUIWebBrowser.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIWebBrowser : public UPikaUIWidgetBase { GENERATED_BODY() };
PikaUIWebBrowser.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIWebBrowser.h"
PikaUIWidgetBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "Button.h" #include "PikaUIData.h" #include "SizeBox.h" #include "Public/PikaGodStonePlayerController.h" #include "PikaGameSaveData.h" #include "Slider.h" #include "ComboBoxString.h" #include "CheckBox.h" #include "PikaUIWidgetBase.generated.h" //日志打印 #define PikaLOG(Cen) PikaLogPrintf(Cen) UENUM() namespace PikaEButtonSureType { enum Type { BST_None, BST_DeleteSave, //删除游戏存储 BST_CoverSave, //覆盖游戏存储 BST_QuitMeun, //退到主菜单 BST_QuitGame, BST_MAX }; } //面板Box类型 namespace PikaBoxListType { //枚举的定义顺序对应于UPikaUIMainHall::PikaDrawUIToScreen里添加到PikaBoxList的顺序 enum Type { BOXLIST_SaveList,//对应PikaBoxList里第一个被添加进去的控件 BOXLIST_GameSettings,//对应PikaBoxList里第二个被添加进去的控件 BOXLIST_Max, }; } //作为角色的基础信息现实 USTRUCT() struct FPikaCharacterInformationWidget { GENERATED_BODY() //角色名字 FName PikaCharacterName; //金币消费 int32 PikaComsumeGlod; //生命值 float PikaCharacterHealth; //攻击力 float PikaCharacterAttack; //防御力 float PikaCharacterArmor; //攻击速度 float PikaCharacterAttackSpeed; //角色简介 FText PikaCharacterIntroduction; FPikaCharacterInformationWidget() : PikaComsumeGlod(0), PikaCharacterHealth(0), PikaCharacterAttack(0), PikaCharacterArmor(0), PikaCharacterAttackSpeed(0), PikaCharacterIntroduction(FText::FromString("NoData")), PikaCharacterName(FName(*FString("None"))) {} //重载等号操作符 FORCEINLINE FPikaCharacterInformationWidget& operator=(const FPikaCharacterInformationWidget& CharacterInformationWidget) { PikaComsumeGlod = CharacterInformationWidget.PikaComsumeGlod; PikaCharacterHealth = CharacterInformationWidget.PikaCharacterHealth; PikaCharacterAttack = CharacterInformationWidget.PikaCharacterAttack; PikaCharacterArmor = CharacterInformationWidget.PikaCharacterArmor; PikaCharacterAttackSpeed = CharacterInformationWidget.PikaCharacterAttackSpeed; PikaCharacterName = CharacterInformationWidget.PikaCharacterName; PikaCharacterIntroduction = CharacterInformationWidget.PikaCharacterIntroduction; return *this; } FORCEINLINE bool operator==(const FPikaCharacterInformationWidget& NewCharacterInformation) { return (PikaComsumeGlod == NewCharacterInformation.PikaComsumeGlod && PikaCharacterHealth == NewCharacterInformation.PikaCharacterHealth && PikaCharacterAttack == NewCharacterInformation.PikaCharacterAttack && PikaCharacterArmor == NewCharacterInformation.PikaCharacterArmor && PikaCharacterAttackSpeed == NewCharacterInformation.PikaCharacterAttackSpeed && PikaCharacterName == NewCharacterInformation.PikaCharacterName); } //还原出厂设置 void PikaClearCharacterInformationWidget() { PikaComsumeGlod = 0; PikaCharacterHealth = 0; PikaCharacterAttack = 0; PikaCharacterArmor = 0; PikaCharacterAttackSpeed = 0; PikaCharacterName = FName(*FString("None")); PikaCharacterIntroduction = FText::FromString("NoData"); } }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaUIWidgetBase : public UUserWidget { GENERATED_BODY() public: //存储弹窗类型 UPROPERTY() TEnumAsByte<PikaEButtonSureType::Type> PikaGameButtonSureType; //设置弹窗类型 //ButtonSureType: 弹窗类型 void PikaSetGameButtonSureType(TEnumAsByte<PikaEButtonSureType::Type> MewButtonSureType); //UIData的指针 UPikaUIData * PikaUIDataPtr; //直接获取Button UButton * PikaGetButtonFromBlueprint(FName BlueprintWidgetName) const; UButton * PikaGetButtonFromBlueprint(FString BlueprintWidgetName) const; USlider* PikaGetSliderFormBlueprint(FString BlueprintWidgetName) const; USlider* PikaGetSliderFormBlueprint(FName BlueprintWidgetName) const; UFUNCTION() virtual void PikaChangedValue(float Val) {} virtual void PikaUpdateAttibe() {} UComboBoxString* PikaGetComboBoxStringFormBlueprint(FName BlueprintWidgetName) const; UComboBoxString* PikaGetComboBoxStringFormBlueprint(FString BlueprintWidgetName) const; UCheckBox* PikaGetCheckBoxFormBlueprint(FName BlueprintWidgetName) const; UCheckBox* PikaGetCheckBoxFormBlueprint(FString BlueprintWidgetName) const; UFUNCTION() virtual void PikaSelectionChangedBySelf(UWidget* MyWidget, FString SelectedItem, ESelectInfo::Type SelectionType) {} //调用后去初始化自已的UI,需要手动调用 //相当于BeginPlay,用于解决BeginPlay执行时,有些资源可能还没加载完成的问题 //继承自本类的UI类里,会在主界面类里手动调用本函数 virtual void PikaDrawUIToScreen() {} //负责打印GameLOG virtual void PikaLogPrintf(FString MyString) {} void PikaAddSizeBox(USizeBox* TargetWidget , UWidget* BaseWidget); //获取PlayerController APikaGodStonePlayerController* PikaGetPlayerController(); //获取PlayerState APikaGodStonePlayerState* PikaGetPlayerState(); //获取GameInstance UPikaGodStoneGameInstance* PikaGetGameInstance(); //获取SaveGameData FPikaGodStoneSaveGameData* PikaGetSaveGameData(); ///////////////////////////////Button/////////////////////////////////////////// UFUNCTION() virtual void PikaOnClickedWidget(UWidget* MyWidget) {} UFUNCTION() virtual void PikaOnHoveredWidget(UWidget* CurrentButton) {} UFUNCTION() virtual void PikaOnUnHoveredWidget() {} UFUNCTION() virtual void PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget) {} virtual void PikaSetWarningWindowsState(bool IsVisibles, float StateTime = 0, FString MyWidget = "", TEnumAsByte<PikaEButtonSureType::Type> MyButtonSureType = PikaEButtonSureType::BST_None) {} };
PikaUIWidgetBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaUIWidgetBase.h" void UPikaUIWidgetBase::PikaSetGameButtonSureType(TEnumAsByte<PikaEButtonSureType::Type> MewButtonSureType) { PikaGameButtonSureType = MewButtonSureType; } UButton * UPikaUIWidgetBase::PikaGetButtonFromBlueprint(FName BlueprintWidgetName) const { /* * 修改了引擎后,除了Button,所有widget都可以用Cast进行强转 */ UButton * PikaMyButton = Cast<UButton>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaMyButton) { PikaMyButton->PikaqiuClickedWidget.AddDynamic(this , &UPikaUIWidgetBase::PikaOnClickedWidget); PikaMyButton->PikaqiuHoverWidget.AddDynamic(this, &UPikaUIWidgetBase::PikaOnHoveredWidget); PikaMyButton->OnUnhovered.AddDynamic(this, &UPikaUIWidgetBase::PikaOnUnHoveredWidget); } return PikaMyButton; } UButton * UPikaUIWidgetBase::PikaGetButtonFromBlueprint(FString BlueprintWidgetName) const { UButton * PikaMyButton = Cast<UButton>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaMyButton) { PikaMyButton->PikaqiuClickedWidget.AddDynamic(this, &UPikaUIWidgetBase::PikaOnClickedWidget); PikaMyButton->PikaqiuHoverWidget.AddDynamic(this, &UPikaUIWidgetBase::PikaOnHoveredWidget); PikaMyButton->OnUnhovered.AddDynamic(this, &UPikaUIWidgetBase::PikaOnUnHoveredWidget); } return PikaMyButton; } USlider* UPikaUIWidgetBase::PikaGetSliderFormBlueprint(FString BlueprintWidgetName) const { USlider* TmpSlider = Cast<USlider>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (TmpSlider) { TmpSlider->OnValueChanged.AddDynamic(this, &UPikaUIWidgetBase::PikaChangedValue); } return TmpSlider; } USlider* UPikaUIWidgetBase::PikaGetSliderFormBlueprint(FName BlueprintWidgetName) const { USlider* TmpSlider = Cast<USlider>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (TmpSlider) { TmpSlider->OnValueChanged.AddDynamic(this, &UPikaUIWidgetBase::PikaChangedValue); } return TmpSlider; } UComboBoxString* UPikaUIWidgetBase::PikaGetComboBoxStringFormBlueprint(FName BlueprintWidgetName) const { UComboBoxString* PikaComboBoxString = Cast<UComboBoxString>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaComboBoxString) { PikaComboBoxString->PikaqiuOnSelectionChangedBySelf.AddDynamic(this, &UPikaUIWidgetBase::PikaSelectionChangedBySelf); } return PikaComboBoxString; } UComboBoxString* UPikaUIWidgetBase::PikaGetComboBoxStringFormBlueprint(FString BlueprintWidgetName) const { UComboBoxString* PikaComboBoxString = Cast<UComboBoxString>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaComboBoxString) { PikaComboBoxString->PikaqiuOnSelectionChangedBySelf.AddDynamic(this, &UPikaUIWidgetBase::PikaSelectionChangedBySelf); } return PikaComboBoxString; } UCheckBox* UPikaUIWidgetBase::PikaGetCheckBoxFormBlueprint(FName BlueprintWidgetName) const { UCheckBox* PikaCheckBoxWidget = Cast<UCheckBox>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaCheckBoxWidget) { PikaCheckBoxWidget->PikaqiuOnCheckStateChanged.AddDynamic(this, &UPikaUIWidgetBase::PikaClickedCheckBox); } return PikaCheckBoxWidget; } UCheckBox* UPikaUIWidgetBase::PikaGetCheckBoxFormBlueprint(FString BlueprintWidgetName) const { UCheckBox* PikaCheckBoxWidget = Cast<UCheckBox>(PikaqiuGetBlueprintWidget(BlueprintWidgetName)); if (PikaCheckBoxWidget) { PikaCheckBoxWidget->PikaqiuOnCheckStateChanged.AddDynamic(this, &UPikaUIWidgetBase::PikaClickedCheckBox); } return PikaCheckBoxWidget; } void UPikaUIWidgetBase::PikaAddSizeBox(USizeBox* TargetWidget, UWidget* BaseWidget) { if (TargetWidget && BaseWidget) { TargetWidget->AddChild(BaseWidget); } } APikaGodStonePlayerController* UPikaUIWidgetBase::PikaGetPlayerController() { return GetWorld() ? ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController()) : NULL; } APikaGodStonePlayerState* UPikaUIWidgetBase::PikaGetPlayerState() { return PikaGetPlayerController() ? PikaGetPlayerController()->PikaGetTowerPlayerState() : NULL ; } UPikaGodStoneGameInstance* UPikaUIWidgetBase::PikaGetGameInstance() { return PikaGetPlayerState() ? PikaGetPlayerState()->PikaGetGameInstance() : NULL; } /*FPikaGodStoneSaveGameData* UPikaUIWidgetBase::PikaGetSaveGameData() { return (PikaGetGameInstance() && PikaGetGameInstance()->PikaGetGameSaveData()) ? &(PikaGetGameInstance()->PikaGetGameSaveData()->PikaGodStongSaveData) : NULL; }*/ FPikaGodStoneSaveGameData* UPikaUIWidgetBase::PikaGetSaveGameData() { return PikaGetPlayerController() != nullptr ? (PikaGetPlayerController()->PikaGlobalConfigPre ? &PikaGetPlayerController()->PikaGlobalConfigPre->PikaGameData : nullptr) : nullptr; }
PikaWorldSettings.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/WorldSettings.h" #include "PikaWorldSettings.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaWorldSettings : public AWorldSettings { GENERATED_BODY() public: APikaWorldSettings(); //当前关卡的序列ID UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "PikaBaseSettings", meta = (DisplayName = "Level Number")) int32 PikaCurrentLevel; };
PikaWorldSettings.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaWorldSettings.h" //PikaGameUserSettings属于ini配置类,该构造函数只会在代码编译时以及启动游戏时分别调用一次,在运行中不会再次执行 APikaWorldSettings::APikaWorldSettings() { PikaCurrentLevel = 1; }
11
22