阶段暂存
This commit is contained in:
@ -27,4 +27,5 @@ r.DefaultFeature.MotionBlur=False
|
|||||||
+PropertyRedirects=(OldName="/Script/BusyRabbit.TerrainTileSetConfig.TerrainTileMapping",NewName="/Script/BusyRabbit.TerrainTileSetConfig.n")
|
+PropertyRedirects=(OldName="/Script/BusyRabbit.TerrainTileSetConfig.TerrainTileMapping",NewName="/Script/BusyRabbit.TerrainTileSetConfig.n")
|
||||||
+PropertyRedirects=(OldName="/Script/BusyRabbit.TerrainLayerComponent.TerrainLayers",NewName="/Script/BusyRabbit.TerrainLayerComponent.TerrainMeshes")
|
+PropertyRedirects=(OldName="/Script/BusyRabbit.TerrainLayerComponent.TerrainLayers",NewName="/Script/BusyRabbit.TerrainLayerComponent.TerrainMeshes")
|
||||||
+ClassRedirects=(OldName="/Script/BusyRabbit.LevelPlayerController",NewName="/Script/BusyRabbit.LevelPlayerController")
|
+ClassRedirects=(OldName="/Script/BusyRabbit.LevelPlayerController",NewName="/Script/BusyRabbit.LevelPlayerController")
|
||||||
|
+ClassRedirects=(OldName="/Script/BusyRabbit.StaticResource",NewName="/Script/BusyRabbit.BusyStaticResource")
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
BIN
Content/Blueprint/Level/Actor/RoamingCamera.uasset
Normal file
BIN
Content/Blueprint/Level/Actor/RoamingCamera.uasset
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/Blueprint/Level/Actor/Static/BP_Campsite.uasset
Normal file
BIN
Content/Blueprint/Level/Actor/Static/BP_Campsite.uasset
Normal file
Binary file not shown.
BIN
Content/Blueprint/Level/Actor/Static/BP_Tree.uasset
Normal file
BIN
Content/Blueprint/Level/Actor/Static/BP_Tree.uasset
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/Blueprint/Level/GameMode/BP_BusyLevelGameState.uasset
Normal file
BIN
Content/Blueprint/Level/GameMode/BP_BusyLevelGameState.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Data/Input/Level/IA_CameraDetach.uasset
Normal file
BIN
Content/Data/Input/Level/IA_CameraDetach.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
Content/Lua/@types/BusyGameplayLibrary.d.lua
Normal file
3
Content/Lua/@types/BusyGameplayLibrary.d.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
--- @class BusyGameplayLibrary
|
||||||
|
--- @field K2_GetWorld fun(obj:table):table
|
||||||
|
local BusyGameplayLibrary = {}
|
||||||
@ -27,3 +27,9 @@ slua = {
|
|||||||
KismetSystemLibrary = {
|
KismetSystemLibrary = {
|
||||||
K2_ClearTimerHandle = function() end
|
K2_ClearTimerHandle = function() end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- @class GameplayStatics
|
||||||
|
--- @field GetPlayerController fun(uobj:table,idx:number):table
|
||||||
|
--- @field GetGameState fun(uobj:table):table
|
||||||
|
local GameplayStatics
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
local BusyPlayerRole = {}
|
|
||||||
|
|
||||||
function BusyPlayerRole:UpdateMoveDirection(InDirection)
|
|
||||||
if(InDirection.Y > 0) then
|
|
||||||
self["SpineAnimationComponent"]:SetSkin("front/move")
|
|
||||||
else
|
|
||||||
self["SpineAnimationComponent"]:SetSkin("back/move")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Class(nil, nil, BusyPlayerRole)
|
|
||||||
4
Content/Lua/Level/Actor/LevelFoxRole.lua
Normal file
4
Content/Lua/Level/Actor/LevelFoxRole.lua
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
local LevelFoxRole = {}
|
||||||
|
|
||||||
|
|
||||||
|
return Class(nil, nil, LevelFoxRole)
|
||||||
58
Content/Lua/Level/Actor/LevelRabbitRole.lua
Normal file
58
Content/Lua/Level/Actor/LevelRabbitRole.lua
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
local LevelRabbitRole = {}
|
||||||
|
|
||||||
|
function LevelRabbitRole:ctor()
|
||||||
|
self.last_animation = "back/move"
|
||||||
|
end
|
||||||
|
|
||||||
|
function LevelRabbitRole:ReceiveBeginPlay()
|
||||||
|
self["SpineAnimationComponent"]:SetSkin("back/move");
|
||||||
|
self["SpineAnimationComponent"]:SetAnimation(0, "animation", true);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function LevelRabbitRole:OnMove(location)
|
||||||
|
-- 控制器移动相应函数
|
||||||
|
self["MovementComponent"]:MoveTo(location)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function LevelRabbitRole:UpdateMoveDirection(InDirection)
|
||||||
|
-- 运动组件更新方向响应函数
|
||||||
|
local cur_animation
|
||||||
|
if(InDirection.Y >= 0) then
|
||||||
|
cur_animation = "front/move"
|
||||||
|
else
|
||||||
|
cur_animation = "back/move"
|
||||||
|
end
|
||||||
|
if cur_animation ~= self.last_animation then
|
||||||
|
self["SpineAnimationComponent"]:SetSkin(cur_animation)
|
||||||
|
self["SpineAnimationComponent"]:SetSlotsToSetupPose()
|
||||||
|
self.last_animation = cur_animation
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function LevelRabbitRole:OnDetachCamera()
|
||||||
|
print(self, "LevelRabbitRole.OnDetachCamera")
|
||||||
|
|
||||||
|
-- 禁用弹簧臂的附着
|
||||||
|
self["SpringArmComponent"].bEnableCameraRotationLag = true
|
||||||
|
self["SpringArmComponent"].CameraRotationLagSpeed = 0
|
||||||
|
-- 保持当前位置,停止跟随
|
||||||
|
self["SpringArmComponent"].bInheritPitch = true
|
||||||
|
self["SpringArmComponent"].bInheritYaw = true
|
||||||
|
self["SpringArmComponent"].bInheritRoll = true
|
||||||
|
|
||||||
|
-- (Pitch=0.000000,Yaw=-90.000000,Roll=0.000000)
|
||||||
|
end
|
||||||
|
|
||||||
|
function LevelRabbitRole:OnReattachCamera()
|
||||||
|
print(self, "LevelRabbitRole.OnReattachCamera")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function LevelRabbitRole:OnMoveCamera(direction)
|
||||||
|
print(self, "LevelRabbitRole.OnMoveCamera", direction.X, direction.Y)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return Class(nil, nil, LevelRabbitRole)
|
||||||
4
Content/Lua/Level/Actor/Static/Campsite.lua
Normal file
4
Content/Lua/Level/Actor/Static/Campsite.lua
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
local Campsite = {}
|
||||||
|
|
||||||
|
|
||||||
|
return Class(nil, nil, Campsite)
|
||||||
@ -1,13 +1,36 @@
|
|||||||
|
local Vector = import("Vector")
|
||||||
|
local GameplayStatics = import("GameplayStatics")
|
||||||
|
local BusyGameplayLibrary = import("BusyGameplayLibrary")
|
||||||
|
|
||||||
|
--- 保留到以后做联机内容时拓展
|
||||||
|
--- @class LevelGameMode
|
||||||
|
--- @field GameMapActorClass table
|
||||||
local LevelGameMode = {}
|
local LevelGameMode = {}
|
||||||
|
|
||||||
function LevelGameMode:K2_PostLogin(new_player_controller)
|
function LevelGameMode:ctor()
|
||||||
|
self.map_actor = nil
|
||||||
local new_player_state = new_player_controller.PlayerState
|
|
||||||
|
|
||||||
local role = new_player_state:CreateRoleRoster(new_player_controller)
|
|
||||||
|
|
||||||
new_player_controller:Possess(role)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function LevelGameMode:ReceiveBeginPlay()
|
||||||
|
print("LevelGameMode:ReceiveBeginPlay", self.GameMapActorClass)
|
||||||
|
local world = BusyGameplayLibrary.K2_GetWorld(self)
|
||||||
|
local game_state = GameplayStatics.GetGameState(self) --- @type LevelGameState
|
||||||
|
|
||||||
|
if self.GameMapActorClass then
|
||||||
|
local map_actor = world:SpawnActor(self.GameMapActorClass, Vector(), nil, nil)
|
||||||
|
game_state:SetGameMapActor(map_actor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- function LevelGameMode:K2_PostLogin(new_player_controller)
|
||||||
|
-- local new_player_state = new_player_controller.PlayerState
|
||||||
|
-- local role = new_player_state:CreateRoleRoster(new_player_controller)
|
||||||
|
-- local new_pos = FVector()
|
||||||
|
-- new_pos.X = 500
|
||||||
|
-- new_pos.Y = 500
|
||||||
|
-- new_pos.Z = 50
|
||||||
|
-- role:K2_SetActorLocation(new_pos, true, nil, false)
|
||||||
|
-- new_player_controller:Possess(role)
|
||||||
|
-- end
|
||||||
|
|
||||||
return Class(nil, nil, LevelGameMode)
|
return Class(nil, nil, LevelGameMode)
|
||||||
9
Content/Lua/Level/LevelGameState.lua
Normal file
9
Content/Lua/Level/LevelGameState.lua
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
--- @class LevelGameState
|
||||||
|
local LevelGameState = {}
|
||||||
|
|
||||||
|
function LevelGameState:SetGameMapActor(game_map_actor)
|
||||||
|
self.GameMapActor = game_map_actor
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return Class(nil, nil, LevelGameState)
|
||||||
12
Content/Lua/Level/LevelPlayerState.lua
Normal file
12
Content/Lua/Level/LevelPlayerState.lua
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
local GameplayStatics = import("GameplayStatics")
|
||||||
|
|
||||||
|
local LevelPlayerState = {}
|
||||||
|
|
||||||
|
function LevelPlayerState:ReceiveBeginPlay()
|
||||||
|
local pc = GameplayStatics.GetPlayerController(self, 0)
|
||||||
|
local role = self:CreateRoleRoster(pc)
|
||||||
|
print("LevelPlayerState:ReceiveBeginPlay", role, self:HasAuthority())
|
||||||
|
pc:Possess(role)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Class(nil, nil, LevelPlayerState)
|
||||||
BIN
Content/Resource/Spine/PlacedItems/Fire/Fire.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Fire/Fire.uasset
Normal file
Binary file not shown.
BIN
Content/Resource/Spine/PlacedItems/Fire/FireData.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Fire/FireData.uasset
Normal file
Binary file not shown.
BIN
Content/Resource/Spine/PlacedItems/Fire/Textures/Fire.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Fire/Textures/Fire.uasset
Normal file
Binary file not shown.
BIN
Content/Resource/Spine/PlacedItems/Tree/Textures/Tree.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Tree/Textures/Tree.uasset
Normal file
Binary file not shown.
BIN
Content/Resource/Spine/PlacedItems/Tree/Tree.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Tree/Tree.uasset
Normal file
Binary file not shown.
BIN
Content/Resource/Spine/PlacedItems/Tree/TreeData.uasset
Normal file
BIN
Content/Resource/Spine/PlacedItems/Tree/TreeData.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,7 +16,6 @@ void UBusyActorManagerSubSystem::OnWorldBeginPlay(UWorld& InWorld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UBusyActorManagerSubSystem::Deinitialize(){
|
void UBusyActorManagerSubSystem::Deinitialize(){
|
||||||
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Luaʵ<61>ֵĺ<D6B5><C4BA><EFBFBD><EFBFBD>ܲ<EFBFBD><DCB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><C8B2>ṩ<EFBFBD><E1B9A9><EFBFBD>ٵ<EFBFBD>lua<75>ӿڰ<D3BF>
|
|
||||||
Super::Deinitialize();
|
Super::Deinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ FString UBusyActorManagerSubSystem::GetLuaFilePath_Implementation() const{
|
|||||||
|
|
||||||
bool UBusyActorManagerSubSystem::GetLevelBaseConfig(FBusyLevelBaseConfig& config){
|
bool UBusyActorManagerSubSystem::GetLevelBaseConfig(FBusyLevelBaseConfig& config){
|
||||||
FBusyLevelBaseConfig* Config;
|
FBusyLevelBaseConfig* Config;
|
||||||
UDataTable *DataTable = UBusyGamePlayLibrary::GetGameDataTable("LevelBaseConfig");
|
UDataTable *DataTable = UBusyGameplayLibrary::GetGameDataTable("LevelBaseConfig");
|
||||||
if (!DataTable) return false;
|
if (!DataTable) return false;
|
||||||
|
|
||||||
Config = DataTable->FindRow<FBusyLevelBaseConfig>(
|
Config = DataTable->FindRow<FBusyLevelBaseConfig>(
|
||||||
|
|||||||
@ -11,7 +11,7 @@ static inline const UBusyDataAsset* GetGameAsset() {
|
|||||||
|
|
||||||
template<typename RowStruct>
|
template<typename RowStruct>
|
||||||
static bool GetTableConfig(const FString& TableName, const FName& RowName, RowStruct& RowData) {
|
static bool GetTableConfig(const FString& TableName, const FName& RowName, RowStruct& RowData) {
|
||||||
UDataTable* Table = UBusyGamePlayLibrary::GetGameDataTable(TableName);
|
UDataTable* Table = UBusyGameplayLibrary::GetGameDataTable(TableName);
|
||||||
RowStruct* Config = Table->FindRow<RowStruct>(
|
RowStruct* Config = Table->FindRow<RowStruct>(
|
||||||
RowName,
|
RowName,
|
||||||
*FString::Printf(TEXT("GetTableConfig, %s"), *RowName.ToString()),
|
*FString::Printf(TEXT("GetTableConfig, %s"), *RowName.ToString()),
|
||||||
@ -26,79 +26,59 @@ static bool GetTableConfig(const FString& TableName, const FName& RowName, RowSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UDataTable* UBusyGamePlayLibrary::GetGameDataTable(const FString& TableName){
|
UDataTable* UBusyGameplayLibrary::GetGameDataTable(const FString& TableName){
|
||||||
const UBusyDataAsset* GameAsset = GetGameAsset();
|
const UBusyDataAsset* GameAsset = GetGameAsset();
|
||||||
if (!GameAsset) return nullptr;
|
if (!GameAsset) return nullptr;
|
||||||
auto Table = (GameAsset->DataTableMapping.Find(TableName));
|
auto Table = (GameAsset->DataTableMapping.Find(TableName));
|
||||||
return Table ? Table->Get() : nullptr;
|
return Table ? Table->Get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UClass* UBusyGamePlayLibrary::GetGameClass(const FString& ClassName){
|
UClass* UBusyGameplayLibrary::GetGameClass(const FString& ClassName){
|
||||||
const UBusyDataAsset* GameAsset = GetGameAsset();
|
const UBusyDataAsset* GameAsset = GetGameAsset();
|
||||||
if (!GameAsset) return nullptr;
|
if (!GameAsset) return nullptr;
|
||||||
auto Class = (GameAsset->ClassPathMapping.Find(ClassName));
|
auto Class = (GameAsset->ClassPathMapping.Find(ClassName));
|
||||||
return Class ? Class->Get() : nullptr;
|
return Class ? Class->Get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UClass* UBusyGamePlayLibrary::GetGameUIClass(const FString& ClassName){
|
UClass* UBusyGameplayLibrary::GetGameUIClass(const FString& ClassName){
|
||||||
const UBusyDataAsset* GameAsset = GetGameAsset();
|
const UBusyDataAsset* GameAsset = GetGameAsset();
|
||||||
if (!GameAsset) return nullptr;
|
if (!GameAsset) return nullptr;
|
||||||
auto Class = (GameAsset->UIPathMapping.Find(ClassName));
|
auto Class = (GameAsset->UIPathMapping.Find(ClassName));
|
||||||
return Class ? Class->Get() : nullptr;
|
return Class ? Class->Get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UWorld* UBusyGamePlayLibrary::K2_GetWorld(const UObject* obj){
|
UWorld* UBusyGameplayLibrary::K2_GetWorld(const UObject* UObj){
|
||||||
return obj->GetWorld();
|
return UObj->GetWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetLevelBaseConfig(const FName& RowName, FBusyLevelBaseConfig& RowData){
|
bool UBusyGameplayLibrary::GetLevelBaseConfig(const FName& RowName, FBusyLevelBaseConfig& RowData){
|
||||||
return GetTableConfig<FBusyLevelBaseConfig>(TEXT("LevelBaseConfig"), RowName, RowData);
|
return GetTableConfig<FBusyLevelBaseConfig>(TEXT("LevelBaseConfig"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetLevelItemConfig(const FName& RowName, FBusyLevelItemConfig& RowData){
|
bool UBusyGameplayLibrary::GetLevelItemConfig(const FName& RowName, FBusyLevelItemConfig& RowData){
|
||||||
return GetTableConfig<FBusyLevelItemConfig>(TEXT("LevelItems"), RowName, RowData);
|
return GetTableConfig<FBusyLevelItemConfig>(TEXT("LevelItems"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetRoleConfig(const FName& RowName, FBusyRoleConfig& RowData){
|
bool UBusyGameplayLibrary::GetRoleConfig(const FName& RowName, FBusyRoleConfig& RowData){
|
||||||
return GetTableConfig<FBusyRoleConfig>(TEXT("RoleConfig"), RowName, RowData);
|
return GetTableConfig<FBusyRoleConfig>(TEXT("RoleConfig"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetItemResourceConfig(const FName& RowName, FBusyLevelItemResourceConfig& RowData){
|
bool UBusyGameplayLibrary::GetItemResourceConfig(const FName& RowName, FBusyLevelItemResourceConfig& RowData){
|
||||||
return GetTableConfig<FBusyLevelItemResourceConfig>(TEXT("LevelItemResource"), RowName, RowData);
|
return GetTableConfig<FBusyLevelItemResourceConfig>(TEXT("LevelItemResource"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetLevelItemDescription(const FName& RowName, FBusyLevelItemDescription& RowData){
|
bool UBusyGameplayLibrary::GetLevelItemDescription(const FName& RowName, FBusyLevelItemDescription& RowData){
|
||||||
return GetTableConfig<FBusyLevelItemDescription>(TEXT("LevelItemDesc"), RowName, RowData);
|
return GetTableConfig<FBusyLevelItemDescription>(TEXT("LevelItemDesc"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetHomelandItemDescription(const FName& RowName, FBusyHomelandItemDescription& RowData){
|
bool UBusyGameplayLibrary::GetHomelandItemDescription(const FName& RowName, FBusyHomelandItemDescription& RowData){
|
||||||
return GetTableConfig<FBusyHomelandItemDescription>(TEXT("HomelandItemDesc"), RowName, RowData);
|
return GetTableConfig<FBusyHomelandItemDescription>(TEXT("HomelandItemDesc"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetItemDescription(const FName& RowName, FBusyItemDescription& RowData){
|
bool UBusyGameplayLibrary::GetItemDescription(const FName& RowName, FBusyItemDescription& RowData){
|
||||||
return GetTableConfig<FBusyItemDescription>(TEXT("ItemDesc"), RowName, RowData);
|
return GetTableConfig<FBusyItemDescription>(TEXT("ItemDesc"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UBusyGamePlayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData){
|
bool UBusyGameplayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData){
|
||||||
return GetTableConfig<FBusyCookMaterialStateConfig>(TEXT("CookMaterialStateConfig"), RowName, RowData);
|
return GetTableConfig<FBusyCookMaterialStateConfig>(TEXT("CookMaterialStateConfig"), RowName, RowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLuaBPVar UBusyGamePlayLibrary::CreateTextureBuffer(UObject* WorldContextObject){
|
|
||||||
auto DataTexture = UTexture2D::CreateTransient(512, 1, PF_R32_FLOAT);
|
|
||||||
DataTexture->Filter = TF_Trilinear;
|
|
||||||
DataTexture->AddressX = TA_Clamp;
|
|
||||||
DataTexture->AddressY = TA_Clamp;
|
|
||||||
DataTexture->UpdateResource();
|
|
||||||
return ULuaBlueprintLibrary::CreateVarFromObject(WorldContextObject, DataTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UBusyGamePlayLibrary::UpdateTextureBuffer(UTexture2D *DataTexture, TArray<float> FloatData){
|
|
||||||
DataTexture->GetPlatformData()->Mips[0];
|
|
||||||
FTexture2DMipMap& Mip = DataTexture->GetPlatformData()->Mips[0];
|
|
||||||
void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
|
|
||||||
|
|
||||||
FMemory::Memcpy(Data, FloatData.GetData(), FloatData.Num() * sizeof(float));
|
|
||||||
|
|
||||||
Mip.BulkData.Unlock();
|
|
||||||
DataTexture->UpdateResource();
|
|
||||||
}
|
|
||||||
|
|||||||
@ -14,30 +14,21 @@ ABusyPawnBase::ABusyPawnBase()
|
|||||||
SpineRenderComponent = CreateDefaultSubobject<USpineSkeletonRendererComponent>(TEXT("SpineRenderComponent"));
|
SpineRenderComponent = CreateDefaultSubobject<USpineSkeletonRendererComponent>(TEXT("SpineRenderComponent"));
|
||||||
SpineAnimationComponent = CreateDefaultSubobject<USpineSkeletonAnimationComponent>(TEXT("SpineAnimationComponent"));
|
SpineAnimationComponent = CreateDefaultSubobject<USpineSkeletonAnimationComponent>(TEXT("SpineAnimationComponent"));
|
||||||
AbilitySystemComponent = CreateDefaultSubobject<UBusyAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
|
AbilitySystemComponent = CreateDefaultSubobject<UBusyAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
|
||||||
|
|
||||||
MovementComponent = CreateDefaultSubobject<UBusyPawnMovement>(TEXT("MovementComponent"));
|
MovementComponent = CreateDefaultSubobject<UBusyPawnMovement>(TEXT("MovementComponent"));
|
||||||
|
|
||||||
|
|
||||||
RootComponent = RootScene;
|
RootComponent = RootScene;
|
||||||
SpineRoot->SetupAttachment(RootScene);
|
SpineRoot->SetupAttachment(RootScene);
|
||||||
SphereComponent->SetupAttachment(SpineRoot);
|
SphereComponent->SetupAttachment(SpineRoot);
|
||||||
SpineRenderComponent->SetupAttachment(SpineRoot);
|
SpineRenderComponent->SetupAttachment(SpineRoot);
|
||||||
|
|
||||||
SpineRoot->SetRelativeRotation(FRotator(0, 0, -90));
|
SpineRoot->SetRelativeRotation(FRotator(0, 0, -90));
|
||||||
|
|
||||||
|
|
||||||
bReplicates = true;
|
|
||||||
SetReplicatingMovement(true);
|
|
||||||
NetUpdateFrequency = 60.0f;
|
|
||||||
MovementComponent->SetIsReplicated(true);
|
|
||||||
AbilitySystemComponent->SetIsReplicated(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ABusyPawnBase::BeginPlay()
|
void ABusyPawnBase::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
SpineAnimationComponent->SetSkin(DefaultSkinName);
|
// SpineAnimationComponent->SetSkin(DefaultSkinName);
|
||||||
SpineAnimationComponent->SetAnimation(0, DefaultAnimationName, true);
|
// SpineAnimationComponent->SetAnimation(0, DefaultAnimationName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ABusyPawnBase::UpdateMoveDirection_Implementation(const FVector2D& InDirection)
|
void ABusyPawnBase::UpdateMoveDirection_Implementation(const FVector2D& InDirection)
|
||||||
|
|||||||
24
Source/BusyRabbit/Private/Level/Actor/BusyStaticResource.cpp
Normal file
24
Source/BusyRabbit/Private/Level/Actor/BusyStaticResource.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "Level/Actor/BusyStaticResource.h"
|
||||||
|
#include "SpineSkeletonRendererComponent.h"
|
||||||
|
#include "SpineSkeletonAnimationComponent.h"
|
||||||
|
|
||||||
|
ABusyStaticResource::ABusyStaticResource()
|
||||||
|
{
|
||||||
|
RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
|
||||||
|
SpineRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SpineRoot"));
|
||||||
|
|
||||||
|
SpineRenderComponent = CreateDefaultSubobject<USpineSkeletonRendererComponent>("SpineRenderComponent");
|
||||||
|
SpineAnimationComponent = CreateDefaultSubobject<USpineSkeletonAnimationComponent>("SpineAnimationComponent");
|
||||||
|
|
||||||
|
SetRootComponent(RootScene);
|
||||||
|
SpineRoot->SetupAttachment(RootScene);
|
||||||
|
SpineRenderComponent->SetupAttachment(SpineRoot);
|
||||||
|
SpineRoot->SetRelativeRotation(FRotator(0, 0, -90));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ABusyStaticResource::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
SpineAnimationComponent->SetSkin("default");
|
||||||
|
SpineAnimationComponent->SetAnimation(0, "idle", true);
|
||||||
|
}
|
||||||
@ -30,14 +30,11 @@ FVector2D UBusyPawnMovement::GetMoveDirection()const
|
|||||||
return FVector2D();
|
return FVector2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("",off)
|
|
||||||
void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType,
|
void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType,
|
||||||
FActorComponentTickFunction* ThisTickFunction)
|
FActorComponentTickFunction* ThisTickFunction)
|
||||||
{
|
{
|
||||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||||
|
|
||||||
if (!GetOwner()->HasAuthority()) return;
|
|
||||||
|
|
||||||
AActor* Owner = GetOwner();
|
AActor* Owner = GetOwner();
|
||||||
const IBusyMovable* Movable = Cast<IBusyMovable>(Owner);
|
const IBusyMovable* Movable = Cast<IBusyMovable>(Owner);
|
||||||
if (!Owner || !Movable) return;
|
if (!Owner || !Movable) return;
|
||||||
@ -66,11 +63,7 @@ void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType,
|
|||||||
if (!NewLocation.Equals(CurrentLocation))
|
if (!NewLocation.Equals(CurrentLocation))
|
||||||
{
|
{
|
||||||
Owner->SetActorLocation(NewLocation, true);
|
Owner->SetActorLocation(NewLocation, true);
|
||||||
Owner->ForceNetUpdate();
|
|
||||||
}
|
}
|
||||||
|
Movable->Execute_UpdateMoveDirection(Owner, GetMoveDirection());
|
||||||
|
|
||||||
// Movable->Execute_UpdateMoveDirection(Owner, GetMoveDirection());
|
|
||||||
}
|
}
|
||||||
#pragma optimize("",on)
|
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ void ABusyLevelItem::OnConstruction(const FTransform& Transform){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ABusyLevelItem::BeginPlay(){
|
void ABusyLevelItem::BeginPlay(){
|
||||||
UClass* cls = UBusyGamePlayLibrary::GetGameUIClass("PickBar");
|
UClass* cls = UBusyGameplayLibrary::GetGameUIClass("PickBar");
|
||||||
if (cls != nullptr) {
|
if (cls != nullptr) {
|
||||||
PickBar->SetWidgetClass(cls);
|
PickBar->SetWidgetClass(cls);
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ void ABusyLevelItem::InitPickBar(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ABusyLevelItem::SetItemDisplay(const FName& ItemID){
|
void ABusyLevelItem::SetItemDisplay(const FName& ItemID){
|
||||||
UDataTable* Resource = UBusyGamePlayLibrary::GetGameDataTable(TEXT("LevelItemResource"));
|
UDataTable* Resource = UBusyGameplayLibrary::GetGameDataTable(TEXT("LevelItemResource"));
|
||||||
|
|
||||||
// 查物品信息
|
// 查物品信息
|
||||||
FBusyLevelItemResourceConfig* ResourceConfig = Resource->FindRow<FBusyLevelItemResourceConfig>(
|
FBusyLevelItemResourceConfig* ResourceConfig = Resource->FindRow<FBusyLevelItemResourceConfig>(
|
||||||
@ -97,7 +97,7 @@ void ABusyLevelItem::SetItemDisplay(const FName& ItemID){
|
|||||||
|
|
||||||
void ABusyLevelItem::SetLevelItemID(const FName& ItemID){
|
void ABusyLevelItem::SetLevelItemID(const FName& ItemID){
|
||||||
// 取物品资源表
|
// 取物品资源表
|
||||||
UDataTable* ConfigTable = UBusyGamePlayLibrary::GetGameDataTable(TEXT("LevelItems"));
|
UDataTable* ConfigTable = UBusyGameplayLibrary::GetGameDataTable(TEXT("LevelItems"));
|
||||||
// 查物品信息
|
// 查物品信息
|
||||||
FBusyLevelItemConfig* ItemConfig = ConfigTable->FindRow<FBusyLevelItemConfig>(
|
FBusyLevelItemConfig* ItemConfig = ConfigTable->FindRow<FBusyLevelItemConfig>(
|
||||||
ItemID, TEXT("ABusyLevelItem::SetLevelItemID"), true
|
ItemID, TEXT("ABusyLevelItem::SetLevelItemID"), true
|
||||||
|
|||||||
@ -26,7 +26,7 @@ void ALevelItemReward::SetRewardID(const FName& CurrentRewardID){
|
|||||||
bool bIsFind = false;
|
bool bIsFind = false;
|
||||||
FBusyLevelItemDescription Desc;
|
FBusyLevelItemDescription Desc;
|
||||||
if (CurrentRewardID.IsNone()) return;
|
if (CurrentRewardID.IsNone()) return;
|
||||||
bIsFind = UBusyGamePlayLibrary::GetLevelItemDescription(CurrentRewardID, Desc);
|
bIsFind = UBusyGameplayLibrary::GetLevelItemDescription(CurrentRewardID, Desc);
|
||||||
if (!bIsFind) return;
|
if (!bIsFind) return;
|
||||||
this->RewardID = CurrentRewardID;
|
this->RewardID = CurrentRewardID;
|
||||||
this->Sprite->SetFlipbook(Desc.LevelResource.LoadSynchronous());
|
this->Sprite->SetFlipbook(Desc.LevelResource.LoadSynchronous());
|
||||||
|
|||||||
@ -2,10 +2,18 @@
|
|||||||
#include "Level/Actor/BusyPlayerRole.h"
|
#include "Level/Actor/BusyPlayerRole.h"
|
||||||
#include "EnhancedInput/Public/EnhancedInputSubsystems.h"
|
#include "EnhancedInput/Public/EnhancedInputSubsystems.h"
|
||||||
#include "Level/LevelPlayerState.h"
|
#include "Level/LevelPlayerState.h"
|
||||||
#include "EnhancedInput/Public/EnhancedInputSubsystems.h"
|
|
||||||
#include "EnhancedInput/Public/EnhancedInputComponent.h"
|
#include "EnhancedInput/Public/EnhancedInputComponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
inline static void BindEnhancedInputAction(UEnhancedInputComponent* EnhancedInput, const UInputAction* Action, UObject* Target, const FName& Callback)
|
||||||
|
{
|
||||||
|
if (Action)
|
||||||
|
{
|
||||||
|
EnhancedInput->BindAction(Action, ETriggerEvent::Triggered, Target, Callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ALevelPlayerController::ALevelPlayerController()
|
ALevelPlayerController::ALevelPlayerController()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -19,34 +27,74 @@ void ALevelPlayerController::BeginPlay()
|
|||||||
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
||||||
SetInputMode(InputMode);
|
SetInputMode(InputMode);
|
||||||
|
|
||||||
// 注册输入
|
if (RoamingCameraClass)
|
||||||
if (!HasAuthority())
|
|
||||||
{
|
{
|
||||||
const auto Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
RoamingCameraActor = GetWorld()->SpawnActor<AActor>(RoamingCameraClass);
|
||||||
if (InputMapping && Subsystem)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALevelPlayerController::SetupInputComponent()
|
||||||
|
{
|
||||||
|
Super::SetupInputComponent();
|
||||||
|
// 注册输入
|
||||||
|
if (!InputMapping || !InputComponent) return;
|
||||||
|
|
||||||
|
if (const auto Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||||
{
|
{
|
||||||
Subsystem->AddMappingContext(InputMapping, 0);
|
Subsystem->AddMappingContext(InputMapping, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UEnhancedInputComponent* EnhancedInput = CastChecked<UEnhancedInputComponent>(InputComponent);
|
||||||
|
if (!EnhancedInput) return;
|
||||||
|
|
||||||
if (UEnhancedInputComponent* EnhancedInput = CastChecked<UEnhancedInputComponent>(InputComponent)) {
|
BindEnhancedInputAction(EnhancedInput, MoveAction, this, "OnMove");
|
||||||
EnhancedInput->BindAction(TouchAction, ETriggerEvent::Triggered, this, FName("OnTouch"));
|
BindEnhancedInputAction(EnhancedInput, CameraDetachAction, this, "OnCameraDetach");
|
||||||
}
|
BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill");
|
||||||
}
|
BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALevelPlayerController::SetRoleMoveTo_Implementation(const FVector2D& Location)
|
void ALevelPlayerController::Tick(float DeltaTime)
|
||||||
{
|
{
|
||||||
ABusyPlayerRole* ControlledRole = GetControlledRole();
|
Super::Tick(DeltaTime);
|
||||||
if (!ControlledRole) return;
|
|
||||||
ControlledRole->MovementComponent->MoveTo(Location);
|
if (!bCameraDetached || !RoamingCameraActor) return;
|
||||||
|
|
||||||
|
AActor *ControlledRole = GetControlledRole();
|
||||||
|
const IBusyMovable *Movable = Cast<IBusyMovable>(GetControlledRole());
|
||||||
|
if (!Movable) return;
|
||||||
|
|
||||||
|
if (float CursorX, CursorY; GetMousePosition(CursorX, CursorY))
|
||||||
|
{
|
||||||
|
|
||||||
|
// 获取视口大小
|
||||||
|
int32 ViewportSizeX, ViewportSizeY;
|
||||||
|
GetViewportSize(ViewportSizeX, ViewportSizeY);
|
||||||
|
|
||||||
|
// 计算屏幕中心
|
||||||
|
const FVector2D ScreenCenter(ViewportSizeX / 2.0f, ViewportSizeY / 2.0f);
|
||||||
|
|
||||||
|
// 获取漫游相机位置
|
||||||
|
const FVector CurrentLocation = RoamingCameraActor->GetActorLocation();
|
||||||
|
|
||||||
|
// 计算方向向量
|
||||||
|
FVector Direction(CursorX - ScreenCenter.X, CursorY - ScreenCenter.Y, 0);
|
||||||
|
|
||||||
|
// 归一化
|
||||||
|
Direction.Normalize();
|
||||||
|
|
||||||
|
const float MoveSpeed = Movable->Execute_GetSpeed(ControlledRole);
|
||||||
|
const FVector MoveDistance = Direction * DeltaTime * MoveSpeed * RoamingSpeedFactor;
|
||||||
|
|
||||||
|
// 更新漫游相机位置
|
||||||
|
RoamingCameraActor->SetActorLocation(CurrentLocation + MoveDistance);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ALevelPlayerController::GetCursorPosition(FVector2D& Position) const
|
bool ALevelPlayerController::GetCursorPosition(FVector2D& Position) const
|
||||||
{
|
{
|
||||||
float CursorX = 0.f, CursorY = 0.f;
|
if (float CursorX, CursorY; GetMousePosition(CursorX, CursorY))
|
||||||
if (GetMousePosition(CursorX, CursorY))
|
|
||||||
{
|
{
|
||||||
FVector WorldLocation, WorldDirection;
|
FVector WorldLocation, WorldDirection;
|
||||||
if (DeprojectMousePositionToWorld(WorldLocation, WorldDirection))
|
if (DeprojectMousePositionToWorld(WorldLocation, WorldDirection))
|
||||||
@ -73,14 +121,50 @@ ABusyPlayerRole* ALevelPlayerController::GetControlledRole() const
|
|||||||
|
|
||||||
void ALevelPlayerController::SwitchControlledRole(ABusyPlayerRole* Target)
|
void ALevelPlayerController::SwitchControlledRole(ABusyPlayerRole* Target)
|
||||||
{
|
{
|
||||||
this->SetViewTarget(Target);
|
this->Possess(Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALevelPlayerController::OnTouch(const FInputActionValue& Value)
|
void ALevelPlayerController::OnMove(const FInputActionValue& Value) const
|
||||||
{
|
{
|
||||||
FVector2D Position;
|
AActor* ControlledRole = GetControlledRole();
|
||||||
if (GetCursorPosition(Position))
|
if (!ControlledRole) return;
|
||||||
|
|
||||||
|
IBusyControllable *Controllable = Cast<IBusyControllable>(ControlledRole);
|
||||||
|
if (!Controllable) return;
|
||||||
|
|
||||||
|
if (FVector2D Position; GetCursorPosition(Position))
|
||||||
{
|
{
|
||||||
SetRoleMoveTo(Position);
|
Controllable->Execute_OnMove(ControlledRole, Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALevelPlayerController::OnPrimarySkill(const FInputActionValue& Value) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALevelPlayerController::OnUltimateSkill(const FInputActionValue& Value) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALevelPlayerController::OnCameraDetach(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
if (!RoamingCameraActor) return;
|
||||||
|
|
||||||
|
AActor* ControlledRole = GetControlledRole();
|
||||||
|
if (!ControlledRole) return;
|
||||||
|
|
||||||
|
const FVector RoleLocation = ControlledRole->GetActorLocation();
|
||||||
|
RoamingCameraActor->SetActorLocation(RoleLocation);
|
||||||
|
|
||||||
|
|
||||||
|
if (Value.GetMagnitude() > 0)
|
||||||
|
{
|
||||||
|
bCameraDetached = true;
|
||||||
|
SetViewTarget(RoamingCameraActor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bCameraDetached = false;
|
||||||
|
SetViewTarget(ControlledRole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "Level/LevelPlayerState.h"
|
#include "Level/LevelPlayerState.h"
|
||||||
#include "Net/UnrealNetwork.h"
|
// #include "Net/UnrealNetwork.h"
|
||||||
#include "Level/Actor/BusyPlayerRole.h"
|
#include "Level/Actor/BusyPlayerRole.h"
|
||||||
|
|
||||||
|
|
||||||
@ -11,24 +11,19 @@ void ALevelPlayerState::BeginPlay()
|
|||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
void ALevelPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
// void ALevelPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
{
|
// {
|
||||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
// Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
//
|
||||||
DOREPLIFETIME(ALevelPlayerState, RoleRoster);
|
// DOREPLIFETIME(ALevelPlayerState, RoleRoster);
|
||||||
DOREPLIFETIME(ALevelPlayerState, ControlledRoleIndex);
|
// DOREPLIFETIME(ALevelPlayerState, ControlledRoleIndex);
|
||||||
}
|
// }
|
||||||
|
|
||||||
AActor* ALevelPlayerState::CreateRoleRoster(class APlayerController* PlayerController)
|
AActor* ALevelPlayerState::CreateRoleRoster(class APlayerController* PlayerController)
|
||||||
{
|
{
|
||||||
if (!HasAuthority())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
UWorld* World = PlayerController->GetWorld();
|
UWorld* World = PlayerController->GetWorld();
|
||||||
if (!World)
|
if (!World || !PlayerController)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -76,11 +71,3 @@ FVector2D ALevelPlayerState::GetSpawnLocation()const
|
|||||||
{
|
{
|
||||||
return FVector2D::ZeroVector;
|
return FVector2D::ZeroVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALevelPlayerState::SetRoleRoster(const TArray<ABusyPlayerRole*>& Roster)
|
|
||||||
{
|
|
||||||
if (HasAuthority())
|
|
||||||
{
|
|
||||||
RoleRoster = Roster;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,220 +0,0 @@
|
|||||||
#include "Level/TerrainGenerator.h"
|
|
||||||
#include "Math/UnrealMathUtility.h"
|
|
||||||
#include "Math/RandomStream.h"
|
|
||||||
|
|
||||||
UTerrainGenerator::UTerrainGenerator()
|
|
||||||
{
|
|
||||||
NextHandle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool UTerrainGenerator::GenerateWithNodes(TArray<FGameplayTag>& Map, int32 Width, int32 Height, const TArray<int32>& ValidLeafNodes)
|
|
||||||
{
|
|
||||||
// 使用区域生长算法生成基础地图
|
|
||||||
RegionGrowing(Map, Width, Height, ValidLeafNodes);
|
|
||||||
|
|
||||||
// 应用柏林噪声进行平滑处理
|
|
||||||
ApplyPerlinNoiseSmoothing(Map, Width, Height);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UTerrainGenerator::RegionGrowing(TArray<FGameplayTag>& Map, int32 Width, int32 Height,
|
|
||||||
const TArray<int32>& ValidLeafNodes) const
|
|
||||||
{
|
|
||||||
if (ValidLeafNodes.Num() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FRandomStream RandomStream(FMath::Rand());
|
|
||||||
|
|
||||||
// 计算总权重
|
|
||||||
float TotalWeight = 0.0f;
|
|
||||||
for (int32 Handle : ValidLeafNodes)
|
|
||||||
{
|
|
||||||
if (const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
|
|
||||||
{
|
|
||||||
TotalWeight += Node->Weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TotalWeight <= 0.0f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建权重分布
|
|
||||||
TArray<float> WeightDistribution;
|
|
||||||
TArray<int32> HandleDistribution;
|
|
||||||
float CurrentWeight = 0.0f;
|
|
||||||
|
|
||||||
for (int32 Handle : ValidLeafNodes)
|
|
||||||
{
|
|
||||||
if (const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
|
|
||||||
{
|
|
||||||
CurrentWeight += Node->Weight / TotalWeight;
|
|
||||||
WeightDistribution.Add(CurrentWeight);
|
|
||||||
HandleDistribution.Add(Handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区域生长算法
|
|
||||||
TArray<int32> RegionSizes;
|
|
||||||
RegionSizes.SetNum(ValidLeafNodes.Num());
|
|
||||||
|
|
||||||
int32 TotalCells = Width * Height;
|
|
||||||
for (int32 i = 0; i < ValidLeafNodes.Num(); i++)
|
|
||||||
{
|
|
||||||
float Ratio = 0.0f;
|
|
||||||
if (const FTerrainNodeInfo* Node = TerrainNodes.Find(ValidLeafNodes[i]))
|
|
||||||
{
|
|
||||||
Ratio = Node->Weight / TotalWeight;
|
|
||||||
}
|
|
||||||
RegionSizes[i] = FMath::CeilToInt(TotalCells * Ratio);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化地图为无效标签
|
|
||||||
FGameplayTag InvalidTag;
|
|
||||||
for (int32 i = 0; i < Map.Num(); i++)
|
|
||||||
{
|
|
||||||
Map[i] = InvalidTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从随机点开始生长
|
|
||||||
for (int32 RegionIndex = 0; RegionIndex < ValidLeafNodes.Num(); RegionIndex++)
|
|
||||||
{
|
|
||||||
int32 Handle = ValidLeafNodes[RegionIndex];
|
|
||||||
FGameplayTag TerrainTag = GetFinalTerrainTag(Handle);
|
|
||||||
int32 TargetSize = RegionSizes[RegionIndex];
|
|
||||||
int32 CurrentSize = 0;
|
|
||||||
|
|
||||||
// 寻找起始点
|
|
||||||
int32 StartX, StartY;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
StartX = RandomStream.RandRange(0, Width - 1);
|
|
||||||
StartY = RandomStream.RandRange(0, Height - 1);
|
|
||||||
} while (Map[StartY * Width + StartX].IsValid());
|
|
||||||
|
|
||||||
// 使用队列进行区域生长
|
|
||||||
TQueue<FIntPoint> Queue;
|
|
||||||
Queue.Enqueue(FIntPoint(StartX, StartY));
|
|
||||||
Map[StartY * Width + StartX] = TerrainTag;
|
|
||||||
CurrentSize++;
|
|
||||||
|
|
||||||
while (!Queue.IsEmpty() && CurrentSize < TargetSize)
|
|
||||||
{
|
|
||||||
FIntPoint CurrentPoint;
|
|
||||||
Queue.Dequeue(CurrentPoint);
|
|
||||||
|
|
||||||
// 检查四个方向
|
|
||||||
TArray<FIntPoint> Directions = {
|
|
||||||
FIntPoint(1, 0), FIntPoint(-1, 0),
|
|
||||||
FIntPoint(0, 1), FIntPoint(0, -1)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const FIntPoint& Dir : Directions)
|
|
||||||
{
|
|
||||||
FIntPoint Neighbor = CurrentPoint + Dir;
|
|
||||||
|
|
||||||
if (Neighbor.X >= 0 && Neighbor.X < Width &&
|
|
||||||
Neighbor.Y >= 0 && Neighbor.Y < Height)
|
|
||||||
{
|
|
||||||
int32 Index = Neighbor.Y * Width + Neighbor.X;
|
|
||||||
|
|
||||||
if (!Map[Index].IsValid())
|
|
||||||
{
|
|
||||||
Map[Index] = TerrainTag;
|
|
||||||
Queue.Enqueue(Neighbor);
|
|
||||||
CurrentSize++;
|
|
||||||
|
|
||||||
if (CurrentSize >= TargetSize)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 填充剩余的空格
|
|
||||||
for (int32 i = 0; i < Map.Num(); i++)
|
|
||||||
{
|
|
||||||
if (!Map[i].IsValid())
|
|
||||||
{
|
|
||||||
float RandValue = RandomStream.FRand();
|
|
||||||
for (int32 j = 0; j < WeightDistribution.Num(); j++)
|
|
||||||
{
|
|
||||||
if (RandValue <= WeightDistribution[j])
|
|
||||||
{
|
|
||||||
Map[i] = GetFinalTerrainTag(HandleDistribution[j]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UTerrainGenerator::ApplyPerlinNoiseSmoothing(TArray<FGameplayTag>& Map, int32 Width, int32 Height) const
|
|
||||||
{
|
|
||||||
FRandomStream RandomStream(FMath::Rand());
|
|
||||||
float NoiseScale = 0.1f;
|
|
||||||
|
|
||||||
for (int32 Y = 0; Y < Height; Y++)
|
|
||||||
{
|
|
||||||
for (int32 X = 0; X < Width; X++)
|
|
||||||
{
|
|
||||||
int32 Index = Y * Width + X;
|
|
||||||
|
|
||||||
// 计算柏林噪声值
|
|
||||||
float NoiseValue = FMath::PerlinNoise2D(FVector2D(X * NoiseScale, Y * NoiseScale));
|
|
||||||
NoiseValue = (NoiseValue + 1.0f) / 2.0f; // 映射到 0-1
|
|
||||||
|
|
||||||
// 50%概率根据噪声调整地形
|
|
||||||
if (RandomStream.FRand() < 0.5f && NoiseValue > 0.7f)
|
|
||||||
{
|
|
||||||
// 查找周围最多的地形
|
|
||||||
TMap<FGameplayTag, int32> NeighborCount;
|
|
||||||
|
|
||||||
for (int32 dy = -1; dy <= 1; dy++)
|
|
||||||
{
|
|
||||||
for (int32 dx = -1; dx <= 1; dx++)
|
|
||||||
{
|
|
||||||
if (dx == 0 && dy == 0) continue;
|
|
||||||
|
|
||||||
int32 NX = X + dx;
|
|
||||||
int32 NY = Y + dy;
|
|
||||||
|
|
||||||
if (NX >= 0 && NX < Width && NY >= 0 && NY < Height)
|
|
||||||
{
|
|
||||||
FGameplayTag NeighborTag = Map[NY * Width + NX];
|
|
||||||
NeighborCount.FindOrAdd(NeighborTag)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 找到最多的邻居地形
|
|
||||||
FGameplayTag MostCommonTag;
|
|
||||||
int32 MaxCount = 0;
|
|
||||||
|
|
||||||
for (const auto& Pair : NeighborCount)
|
|
||||||
{
|
|
||||||
if (Pair.Value > MaxCount)
|
|
||||||
{
|
|
||||||
MaxCount = Pair.Value;
|
|
||||||
MostCommonTag = Pair.Key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MaxCount > 0)
|
|
||||||
{
|
|
||||||
Map[Index] = MostCommonTag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
#include "Level/TerrainGeneratorBlueprintLibrary.h"
|
|
||||||
#include "Level/TerrainGenerator.h"
|
|
||||||
#include "GameplayTagsManager.h"
|
|
||||||
#include "Engine/Engine.h"
|
|
||||||
|
|
||||||
UTerrainGenerator* UTerrainGeneratorBlueprintLibrary::CreateTerrainGenerator()
|
|
||||||
{
|
|
||||||
return NewObject<UTerrainGenerator>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UTerrainGeneratorBlueprintLibrary::SetupExampleTerrainConfig(UTerrainGeneratorBase* Generator)
|
|
||||||
{
|
|
||||||
if (!Generator)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定义地形标签
|
|
||||||
FGameplayTag ForestTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Forest"));
|
|
||||||
FGameplayTag GrasslandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Grassland"));
|
|
||||||
FGameplayTag WaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water"));
|
|
||||||
FGameplayTag SwampTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp"));
|
|
||||||
FGameplayTag LandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Land"));
|
|
||||||
|
|
||||||
FGameplayTag SwampLandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp.Land"));
|
|
||||||
FGameplayTag SwampWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp.Water"));
|
|
||||||
FGameplayTag ShallowWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water.Shallow"));
|
|
||||||
FGameplayTag DeepWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water.Deep"));
|
|
||||||
|
|
||||||
// 添加父地形
|
|
||||||
int32 ForestHandle = Generator->AddTerrain(ForestTag);
|
|
||||||
int32 GrasslandHandle = Generator->AddTerrain(GrasslandTag);
|
|
||||||
int32 WaterHandle = Generator->AddTerrain(WaterTag);
|
|
||||||
int32 SwampHandle = Generator->AddTerrain(SwampTag);
|
|
||||||
int32 LandHandle = Generator->AddTerrain(LandTag);
|
|
||||||
|
|
||||||
// 添加子地形
|
|
||||||
int32 SwampLandHandle = Generator->AddTerrain(SwampLandTag);
|
|
||||||
int32 SwampWaterHandle = Generator->AddTerrain(SwampWaterTag);
|
|
||||||
int32 ShallowWaterHandle = Generator->AddTerrain(ShallowWaterTag);
|
|
||||||
int32 DeepWaterHandle = Generator->AddTerrain(DeepWaterTag);
|
|
||||||
|
|
||||||
// 绑定父子关系
|
|
||||||
Generator->BindChildTerrain(SwampHandle, {SwampLandHandle, SwampWaterHandle});
|
|
||||||
Generator->BindChildTerrain(WaterHandle, {ShallowWaterHandle, DeepWaterHandle});
|
|
||||||
|
|
||||||
// 设置概率
|
|
||||||
Generator->SetProbability(ForestHandle, 0.8f); // 森林出现概率80%
|
|
||||||
Generator->SetProbability(GrasslandHandle, 0.9f); // 草地出现概率90%
|
|
||||||
Generator->SetProbability(WaterHandle, 0.7f); // 水体出现概率70%
|
|
||||||
Generator->SetProbability(SwampHandle, 0.6f); // 沼泽出现概率60%
|
|
||||||
Generator->SetProbability(LandHandle, 1.0f); // 土地总是出现
|
|
||||||
|
|
||||||
// 设置权重
|
|
||||||
Generator->SetWeight(ForestHandle, 9.0f); // 森林权重9
|
|
||||||
Generator->SetWeight(GrasslandHandle, 5.0f); // 草地权重5
|
|
||||||
Generator->SetWeight(LandHandle, 3.0f); // 土地权重3
|
|
||||||
|
|
||||||
Generator->SetWeight(SwampLandHandle, 1.0f); // 沼泽陆地权重1
|
|
||||||
Generator->SetWeight(SwampWaterHandle, 2.0f); // 沼泽水域权重2
|
|
||||||
|
|
||||||
Generator->SetWeight(ShallowWaterHandle, 3.0f); // 浅水权重3
|
|
||||||
Generator->SetWeight(DeepWaterHandle, 1.0f); // 深水权重1
|
|
||||||
|
|
||||||
// 设置互斥关系
|
|
||||||
Generator->SetExclusive({ForestHandle, SwampWaterHandle}); // 森林和沼泽水域互斥
|
|
||||||
}
|
|
||||||
|
|
||||||
TArray<FGameplayTag> UTerrainGeneratorBlueprintLibrary::GenerateMap(
|
|
||||||
UTerrainGenerator* Generator,
|
|
||||||
int32 Width,
|
|
||||||
int32 Height)
|
|
||||||
{
|
|
||||||
TArray<FGameplayTag> Result;
|
|
||||||
|
|
||||||
if (!Generator)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接返回一维地图数据
|
|
||||||
return Generator->GenerateMap(Width, Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UTerrainGeneratorBlueprintLibrary::GetMapDimensions(
|
|
||||||
UTerrainGenerator* Generator,
|
|
||||||
int32& Width,
|
|
||||||
int32& Height)
|
|
||||||
{
|
|
||||||
Width = 256;
|
|
||||||
Height = 256;
|
|
||||||
|
|
||||||
if (Generator)
|
|
||||||
{
|
|
||||||
// 这里可以根据需要从生成器获取实际的尺寸信息
|
|
||||||
// 目前返回默认值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FString UTerrainGeneratorBlueprintLibrary::GetTerrainDisplayName(const FGameplayTag& TerrainTag)
|
|
||||||
{
|
|
||||||
if (!TerrainTag.IsValid())
|
|
||||||
{
|
|
||||||
return TEXT("无效地形");
|
|
||||||
}
|
|
||||||
|
|
||||||
FString TagName = TerrainTag.ToString();
|
|
||||||
|
|
||||||
// 从标签中提取显示名称
|
|
||||||
if (TagName.StartsWith(TEXT("Terrain.")))
|
|
||||||
{
|
|
||||||
TagName.RemoveFromStart(TEXT("Terrain."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 替换下划线为空格
|
|
||||||
TagName.ReplaceCharInline(TEXT('.'), TEXT(' '));
|
|
||||||
TagName.ReplaceCharInline(TEXT('_'), TEXT(' '));
|
|
||||||
|
|
||||||
// 首字母大写
|
|
||||||
if (TagName.Len() > 0)
|
|
||||||
{
|
|
||||||
TagName[0] = FChar::ToUpper(TagName[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TagName;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UTerrainGeneratorBlueprintLibrary::IsValidTerrainTag(const FGameplayTag& TerrainTag)
|
|
||||||
{
|
|
||||||
return TerrainTag.IsValid();
|
|
||||||
}
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
#include "Level/TerrainGenerator.h"
|
|
||||||
#include "GameplayTagsManager.h"
|
|
||||||
#include "Engine/Engine.h"
|
|
||||||
|
|
||||||
// 测试地形生成器功能
|
|
||||||
void TestTerrainGenerator()
|
|
||||||
{
|
|
||||||
// 创建地形生成器实例
|
|
||||||
UTerrainGenerator* Generator = NewObject<UTerrainGenerator>();
|
|
||||||
|
|
||||||
// 定义地形标签
|
|
||||||
FGameplayTag ForestTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Forest"));
|
|
||||||
FGameplayTag GrasslandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Grassland"));
|
|
||||||
FGameplayTag WaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water"));
|
|
||||||
FGameplayTag SwampTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp"));
|
|
||||||
FGameplayTag LandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Land"));
|
|
||||||
|
|
||||||
FGameplayTag SwampLandTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp.Land"));
|
|
||||||
FGameplayTag SwampWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Swamp.Water"));
|
|
||||||
FGameplayTag ShallowWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water.Shallow"));
|
|
||||||
FGameplayTag DeepWaterTag = FGameplayTag::RequestGameplayTag(TEXT("Terrain.Water.Deep"));
|
|
||||||
|
|
||||||
// 添加父地形
|
|
||||||
int32 ForestHandle = Generator->AddTerrain(ForestTag);
|
|
||||||
int32 GrasslandHandle = Generator->AddTerrain(GrasslandTag);
|
|
||||||
int32 WaterHandle = Generator->AddTerrain(WaterTag);
|
|
||||||
int32 SwampHandle = Generator->AddTerrain(SwampTag);
|
|
||||||
int32 LandHandle = Generator->AddTerrain(LandTag);
|
|
||||||
|
|
||||||
// 添加子地形
|
|
||||||
int32 SwampLandHandle = Generator->AddTerrain(SwampLandTag);
|
|
||||||
int32 SwampWaterHandle = Generator->AddTerrain(SwampWaterTag);
|
|
||||||
int32 ShallowWaterHandle = Generator->AddTerrain(ShallowWaterTag);
|
|
||||||
int32 DeepWaterHandle = Generator->AddTerrain(DeepWaterTag);
|
|
||||||
|
|
||||||
// 绑定父子关系
|
|
||||||
Generator->BindChildTerrain(SwampHandle, {SwampLandHandle, SwampWaterHandle});
|
|
||||||
Generator->BindChildTerrain(WaterHandle, {ShallowWaterHandle, DeepWaterHandle});
|
|
||||||
|
|
||||||
// 设置概率
|
|
||||||
Generator->SetProbability(ForestHandle, 1.0f);
|
|
||||||
Generator->SetProbability(GrasslandHandle, 0.9f);
|
|
||||||
Generator->SetProbability(WaterHandle, 0.7f);
|
|
||||||
Generator->SetProbability(SwampHandle, 1.0f); // 设置为1.0确保沼泽总是出现
|
|
||||||
Generator->SetProbability(LandHandle, 1.0f);
|
|
||||||
|
|
||||||
// 设置权重
|
|
||||||
Generator->SetWeight(ForestHandle, 9.0f);
|
|
||||||
Generator->SetWeight(GrasslandHandle, 5.0f);
|
|
||||||
Generator->SetWeight(LandHandle, 3.0f);
|
|
||||||
Generator->SetWeight(SwampHandle, 2.0f); // 为沼泽父节点设置权重
|
|
||||||
|
|
||||||
Generator->SetWeight(SwampLandHandle, 1.0f);
|
|
||||||
Generator->SetWeight(SwampWaterHandle, 2.0f);
|
|
||||||
|
|
||||||
Generator->SetWeight(ShallowWaterHandle, 3.0f);
|
|
||||||
Generator->SetWeight(DeepWaterHandle, 1.0f);
|
|
||||||
|
|
||||||
// 设置互斥关系
|
|
||||||
Generator->SetExclusive({ForestHandle, SwampWaterHandle});
|
|
||||||
|
|
||||||
// 生成地图
|
|
||||||
TArray<FGameplayTag> Map = Generator->GenerateMap(64, 64);
|
|
||||||
|
|
||||||
// 统计地形分布
|
|
||||||
TMap<FGameplayTag, int32> TerrainCount;
|
|
||||||
for (const FGameplayTag& Tag : Map)
|
|
||||||
{
|
|
||||||
TerrainCount.FindOrAdd(Tag)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 输出统计结果
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("=== 地形生成统计 ==="));
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("地图大小: %dx%d"), 64, 64);
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("总格子数: %d"), Map.Num());
|
|
||||||
|
|
||||||
for (const auto& Pair : TerrainCount)
|
|
||||||
{
|
|
||||||
float Percentage = (float)Pair.Value / Map.Num() * 100.0f;
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("%s: %d (%.1f%%)"),
|
|
||||||
*Pair.Key.ToString(), Pair.Value, Percentage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证互斥关系
|
|
||||||
bool HasForest = TerrainCount.Contains(ForestTag);
|
|
||||||
bool HasSwampWater = TerrainCount.Contains(SwampWaterTag);
|
|
||||||
|
|
||||||
if (HasForest && HasSwampWater)
|
|
||||||
{
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("警告: 森林和沼泽水域同时出现,互斥关系可能未正确工作"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("互斥关系验证: 通过"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证父子关系
|
|
||||||
bool HasSwamp = TerrainCount.Contains(SwampTag);
|
|
||||||
bool HasSwampChildren = TerrainCount.Contains(SwampLandTag) || TerrainCount.Contains(SwampWaterTag);
|
|
||||||
|
|
||||||
if (HasSwamp && !HasSwampChildren)
|
|
||||||
{
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("警告: 沼泽出现但没有子地形"));
|
|
||||||
}
|
|
||||||
else if (!HasSwamp && HasSwampChildren)
|
|
||||||
{
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("警告: 沼泽子地形出现但沼泽未出现"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("父子关系验证: 通过"));
|
|
||||||
}
|
|
||||||
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("=== 测试完成 ==="));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 控制台命令用于测试
|
|
||||||
static FAutoConsoleCommand TestTerrainGeneratorCommand(
|
|
||||||
TEXT("TestTerrainGenerator"),
|
|
||||||
TEXT("测试地形生成器功能"),
|
|
||||||
FConsoleCommandDelegate::CreateStatic(TestTerrainGenerator)
|
|
||||||
);
|
|
||||||
@ -59,7 +59,7 @@ void ABusyRole::Tick(float InDeltaSeconds){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ABusyRole::SetRole(const FName& Name){
|
void ABusyRole::SetRole(const FName& Name){
|
||||||
UDataTable* Table = UBusyGamePlayLibrary::GetGameDataTable("RoleConfig");
|
UDataTable* Table = UBusyGameplayLibrary::GetGameDataTable("RoleConfig");
|
||||||
if (Table == nullptr) {
|
if (Table == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,15 +62,13 @@ void URoleAnimation::PlayPickAnimation(const FName& ItemName, ERoleMoveDirection
|
|||||||
|
|
||||||
|
|
||||||
bool URoleAnimation::GetOwnerRoleInfo(UPaperFlipbookComponent*& Sprite, FBusyRoleAnimationData*& AnimationData){
|
bool URoleAnimation::GetOwnerRoleInfo(UPaperFlipbookComponent*& Sprite, FBusyRoleAnimationData*& AnimationData){
|
||||||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>owner
|
|
||||||
ABusyRole* Role = Cast<ABusyRole>(this->GetOwner());
|
ABusyRole* Role = Cast<ABusyRole>(this->GetOwner());
|
||||||
if (Role == nullptr) {
|
if (Role == nullptr) {
|
||||||
UE_LOG(LogRoleAnimation, Error, TEXT("URoleAnimation::GetPaperFilpBookComponent, Can't get Role"));
|
UE_LOG(LogRoleAnimation, Error, TEXT("URoleAnimation::GetPaperFilpBookComponent, Can't get Role"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <20><><EFBFBD><EFBFBD>owner<65><72><EFBFBD><EFBFBD>
|
UDataTable* DataTable = UBusyGameplayLibrary::GetGameDataTable("RoleAnimation");
|
||||||
UDataTable* DataTable = UBusyGamePlayLibrary::GetGameDataTable("RoleAnimation");
|
|
||||||
if (DataTable == nullptr) {
|
if (DataTable == nullptr) {
|
||||||
UE_LOG(LogRoleAnimation, Error, TEXT("URoleAnimation::GetOwnerRoleInfo, Can't get Animation DataTable"))
|
UE_LOG(LogRoleAnimation, Error, TEXT("URoleAnimation::GetOwnerRoleInfo, Can't get Animation DataTable"))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class BUSYRABBIT_API UBusyGamePlayLibrary : public UBlueprintFunctionLibrary
|
class BUSYRABBIT_API UBusyGameplayLibrary : public UBlueprintFunctionLibrary
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
static UClass* GetGameUIClass(const FString& ClassName);
|
static UClass* GetGameUIClass(const FString& ClassName);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure)
|
UFUNCTION(BlueprintPure)
|
||||||
static UWorld* K2_GetWorld(const UObject* obj);
|
static UWorld* K2_GetWorld(const UObject* UObj);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure)
|
UFUNCTION(BlueprintPure)
|
||||||
static bool GetLevelBaseConfig(const FName& RowName, FBusyLevelBaseConfig& RowData);
|
static bool GetLevelBaseConfig(const FName& RowName, FBusyLevelBaseConfig& RowData);
|
||||||
@ -59,11 +59,4 @@ public:
|
|||||||
UFUNCTION(BlueprintPure)
|
UFUNCTION(BlueprintPure)
|
||||||
static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData);
|
static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure)
|
|
||||||
static FLuaBPVar CreateTextureBuffer(UObject* WorldContextObject);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable)
|
|
||||||
static void UpdateTextureBuffer(UTexture2D* DataTexture, TArray<float> FloatData);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "BusyPawnBase.h"
|
#include "BusyPawnBase.h"
|
||||||
|
#include "Level/LevelPlayerController.h"
|
||||||
#include "BusyPlayerRole.generated.h"
|
#include "BusyPlayerRole.generated.h"
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class ABusyPlayerRole : public ABusyPawnBase
|
class ABusyPlayerRole : public ABusyPawnBase, public IBusyControllable
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
public:
|
public:
|
||||||
@ -12,21 +13,9 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*--------------------相机相关--------------------------*/
|
/*--------------------相机相关--------------------------*/
|
||||||
|
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||||
TObjectPtr<class USpringArmComponent> SpringArmComponent;
|
TObjectPtr<class USpringArmComponent> SpringArmComponent;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||||
TObjectPtr<class UCameraComponent> CameraComponent;
|
TObjectPtr<class UCameraComponent> CameraComponent;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
|
||||||
TObjectPtr<class UBusyRoleMovement> Movement; // 移动组件
|
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
|
||||||
TObjectPtr<class UPW_AbilitySystemComponent> RoleAbility; // 技能组件
|
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite)
|
|
||||||
TObjectPtr<class URoleAnimation> RoleAnimation;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
33
Source/BusyRabbit/Public/Level/Actor/BusyStaticResource.h
Normal file
33
Source/BusyRabbit/Public/Level/Actor/BusyStaticResource.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "LuaActor.h"
|
||||||
|
#include "BusyStaticResource.generated.h"
|
||||||
|
|
||||||
|
class USpineSkeletonRendererComponent;
|
||||||
|
class USpineSkeletonAnimationComponent;
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(Blueprintable, BlueprintType)
|
||||||
|
class ABusyStaticResource:public ALuaActor
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
public:
|
||||||
|
ABusyStaticResource();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(EditAnywhere)
|
||||||
|
TObjectPtr<USceneComponent> RootScene; //场景根组件
|
||||||
|
|
||||||
|
/*----------------------------spine相关组件----------------------------*/
|
||||||
|
UPROPERTY(EditDefaultsOnly)
|
||||||
|
TObjectPtr<USceneComponent> SpineRoot;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly)
|
||||||
|
TObjectPtr<USpineSkeletonRendererComponent> SpineRenderComponent;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||||
|
TObjectPtr<USpineSkeletonAnimationComponent> SpineAnimationComponent;
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
};
|
||||||
@ -3,6 +3,33 @@
|
|||||||
#include "LuaPlayerController.h"
|
#include "LuaPlayerController.h"
|
||||||
#include "LevelPlayerController.generated.h"
|
#include "LevelPlayerController.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
UINTERFACE(MinimalAPI, Blueprintable)
|
||||||
|
class UBusyControllable: public UInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IBusyControllable
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
public:
|
||||||
|
// 角色移动
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||||
|
void OnMove(const FVector2D& Location);
|
||||||
|
|
||||||
|
// 角色普通技能
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||||
|
void OnPrimarySkill();
|
||||||
|
|
||||||
|
// 角色大招
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||||
|
void OnUltimateSkill();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FInputActionValue;
|
||||||
class ABusyPlayerRole;
|
class ABusyPlayerRole;
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
@ -14,37 +41,69 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
virtual void SetupInputComponent() override;
|
||||||
|
virtual void Tick(float DeltaTime) override;
|
||||||
public: // RPC相关
|
|
||||||
UFUNCTION(Server, Reliable)
|
|
||||||
void SetRoleMoveTo(const FVector2D& Location);
|
|
||||||
void SetRoleMoveTo_Implementation(const FVector2D& Location);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UFUNCTION(BlueprintCallable, Category = "Controller")
|
UFUNCTION(BlueprintCallable, Category = "Controller")
|
||||||
bool GetCursorPosition(FVector2D& Position) const;
|
bool GetCursorPosition(FVector2D& Position) const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Controller")
|
UFUNCTION(BlueprintCallable, Category = "Controller")
|
||||||
void GetCursorHitResult(TArray<AActor*>& Results) const;
|
ABusyPlayerRole* GetControlledRole() const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Controller")
|
UFUNCTION(BlueprintCallable, Category = "Controller")
|
||||||
ABusyPlayerRole* GetControlledRole() const;
|
void GetCursorHitResult(TArray<AActor*>& Results) const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Controller")
|
UFUNCTION(BlueprintCallable, Category = "Controller")
|
||||||
void SwitchControlledRole(ABusyPlayerRole* Target);
|
void SwitchControlledRole(ABusyPlayerRole* Target);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Roaming Camera")
|
||||||
|
TSubclassOf<AActor> RoamingCameraClass;
|
||||||
|
|
||||||
|
// 漫游相机移动速度为角色移动速度 * 漫游速度系数
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="漫游速度系数", Category = "Roaming Camera")
|
||||||
|
float RoamingSpeedFactor = 3.0;
|
||||||
|
|
||||||
public: // 输入相关
|
public: // 输入相关
|
||||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
TObjectPtr<class UInputMappingContext> InputMapping;
|
TObjectPtr<class UInputMappingContext> InputMapping;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
TObjectPtr<class UInputAction> TouchAction;
|
TObjectPtr<class UInputAction> MoveAction; // 鼠标右键移动
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
|
TObjectPtr<class UInputAction> SelectAction; // 鼠标左键选择
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
|
TObjectPtr<class UInputAction> PrimarySkillAction; // 基础技能
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
|
TObjectPtr<class UInputAction> UltimateSkillAction; // 大招
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||||
|
TObjectPtr<class UInputAction> CameraDetachAction; // 相机脱离
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION()
|
||||||
|
void OnMove(const FInputActionValue& Value)const;
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnTouch(const FInputActionValue& Value);
|
void OnPrimarySkill(const FInputActionValue& Value)const;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnUltimateSkill(const FInputActionValue& Value)const;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnCameraDetach(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY()
|
||||||
|
AActor* RoamingCameraActor = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bCameraDetached = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class ALevelPlayerState : public ALuaPlayerState
|
|||||||
public:
|
public:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
// virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
public: // 给蓝图初始化的接口
|
public: // 给蓝图初始化的接口
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
@ -27,19 +27,6 @@ public: // 给蓝图的Get接口
|
|||||||
ABusyPlayerRole* GetControlledRole() const;
|
ABusyPlayerRole* GetControlledRole() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public: // 给蓝图的Set接口
|
|
||||||
UFUNCTION(BlueprintCallable)
|
|
||||||
void SetRoleRoster(const TArray<ABusyPlayerRole*>& Roster);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual FVector2D GetSpawnLocation()const;
|
virtual FVector2D GetSpawnLocation()const;
|
||||||
|
|
||||||
@ -48,11 +35,10 @@ public:
|
|||||||
TArray<TSubclassOf<ABusyPlayerRole>> RoleClasses;
|
TArray<TSubclassOf<ABusyPlayerRole>> RoleClasses;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UPROPERTY(Replicated, BlueprintReadOnly)
|
UPROPERTY(BlueprintReadOnly)
|
||||||
int ControlledRoleIndex = -1;
|
int ControlledRoleIndex = -1;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
UPROPERTY(Replicated, BlueprintReadOnly)
|
|
||||||
TArray<ABusyPlayerRole*> RoleRoster;
|
TArray<ABusyPlayerRole*> RoleRoster;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "GameplayTagContainer.h"
|
|
||||||
#include "Generator/TerrainGeneratorBase.h"
|
|
||||||
#include "TerrainGenerator.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UCLASS(BlueprintType, Blueprintable)
|
|
||||||
class BUSYRABBIT_API UTerrainGenerator : public UTerrainGeneratorBase
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UTerrainGenerator();
|
|
||||||
|
|
||||||
virtual bool GenerateWithNodes(
|
|
||||||
TArray<FGameplayTag>& Map, int32 Width, int32 Height,
|
|
||||||
const TArray<int32>& ValidLeafNodes
|
|
||||||
)override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RegionGrowing(TArray<FGameplayTag>& Map, int32 Width, int32 Height,
|
|
||||||
const TArray<int32>& ValidLeafNodes) const;
|
|
||||||
|
|
||||||
void ApplyPerlinNoiseSmoothing(TArray<FGameplayTag>& Map, int32 Width, int32 Height) const;
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
|
||||||
#include "GameplayTagContainer.h"
|
|
||||||
#include "TerrainGeneratorBlueprintLibrary.generated.h"
|
|
||||||
|
|
||||||
// 蓝图函数库,方便在蓝图中使用地形生成<E7949F>?
|
|
||||||
UCLASS()
|
|
||||||
class BUSYRABBIT_API UTerrainGeneratorBlueprintLibrary : public UBlueprintFunctionLibrary
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
// 创建地形生成器实<E599A8>?
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static class UTerrainGenerator* CreateTerrainGenerator();
|
|
||||||
|
|
||||||
// 快速设置示例地形配<E5BDA2>?
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static void SetupExampleTerrainConfig(class UTerrainGeneratorBase* UTerrainGenerator);
|
|
||||||
|
|
||||||
// 生成地图并返回一维数组(蓝图不支持嵌套TArray<61>?
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static TArray<FGameplayTag> GenerateMap(
|
|
||||||
class UTerrainGenerator* Generator,
|
|
||||||
int32 Width = 256,
|
|
||||||
int32 Height = 256
|
|
||||||
);
|
|
||||||
|
|
||||||
// 获取地图尺寸信息(用于在蓝图中解析一维数组)
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static void GetMapDimensions(
|
|
||||||
class UTerrainGenerator* Generator,
|
|
||||||
int32& Width,
|
|
||||||
int32& Height
|
|
||||||
);
|
|
||||||
|
|
||||||
// 获取地形标签的显示名<E7A4BA>?
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static FString GetTerrainDisplayName(const FGameplayTag& TerrainTag);
|
|
||||||
|
|
||||||
// 检查地形标签是否有<E590A6>?
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Terrain Generator")
|
|
||||||
static bool IsValidTerrainTag(const FGameplayTag& TerrainTag);
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user