狐狸接入
This commit is contained in:
		| @ -31,10 +31,6 @@ void ABusyPawnBase::BeginPlay() | ||||
| 	// SpineAnimationComponent->SetAnimation(0, DefaultAnimationName, true); | ||||
| } | ||||
|  | ||||
| void ABusyPawnBase::UpdateMoveDirection_Implementation(const FVector2D& InDirection) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| float ABusyPawnBase::GetSpeed_Implementation()const | ||||
| { | ||||
|  | ||||
| @ -30,8 +30,13 @@ FVector2D UBusyPawnMovement::GetMoveDirection()const | ||||
| 	return FVector2D(); | ||||
| } | ||||
|  | ||||
| FVector2D UBusyPawnMovement::GetForwardDirection() const | ||||
| { | ||||
| 	return ForwardDirection; | ||||
| } | ||||
|  | ||||
| void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType, | ||||
| 							FActorComponentTickFunction* ThisTickFunction) | ||||
|                                       FActorComponentTickFunction* ThisTickFunction) | ||||
| { | ||||
| 	Super::TickComponent(DeltaTime, TickType, ThisTickFunction); | ||||
|  | ||||
| @ -64,6 +69,17 @@ void UBusyPawnMovement::TickComponent(float DeltaTime, ELevelTick TickType, | ||||
| 	{ | ||||
| 		Owner->SetActorLocation(NewLocation, true); | ||||
| 	} | ||||
| 	Movable->Execute_UpdateMoveDirection(Owner, GetMoveDirection()); | ||||
| 	 | ||||
| 	FVector2D &&NewDirection=GetMoveDirection(); | ||||
| 	if (!NewDirection.Equals(FVector2D::Zero(), 0.01)) | ||||
| 	{ | ||||
| 		ForwardDirection = NewDirection; | ||||
| 	} | ||||
| 	if (!NewDirection.Equals(LastMoveDirection)) | ||||
| 	{ | ||||
| 		Movable->Execute_OnMoveDirectionChanged(Owner, NewDirection); | ||||
| 		LastMoveDirection = NewDirection; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -51,6 +51,7 @@ void ALevelPlayerController::SetupInputComponent() | ||||
| 	BindEnhancedInputAction(EnhancedInput, CameraDetachAction, this, "OnCameraDetach"); | ||||
| 	BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill"); | ||||
| 	BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill"); | ||||
| 	BindEnhancedInputAction(EnhancedInput, SwitchRoleAction, this, "OnSwitchRole"); | ||||
| } | ||||
|  | ||||
| void ALevelPlayerController::Tick(float DeltaTime) | ||||
| @ -168,3 +169,13 @@ void ALevelPlayerController::OnCameraDetach(const FInputActionValue& Value) | ||||
| 		SetViewTarget(ControlledRole); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value) | ||||
| { | ||||
| 	const int32 Index = static_cast<int32>(Value.GetMagnitude() - 1); | ||||
| 	if (ALevelPlayerState* PS = GetPlayerState<ALevelPlayerState>()) | ||||
| 	{ | ||||
| 		ABusyPlayerRole* ControlledRole = PS->SwitchControlledRole(Index); | ||||
| 		SwitchControlledRole(ControlledRole); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -67,6 +67,19 @@ ABusyPlayerRole* ALevelPlayerState::GetControlledRole() const | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ABusyPlayerRole* ALevelPlayerState::SwitchControlledRole(int32 Index) | ||||
| { | ||||
| 	if (RoleRoster.IsValidIndex(Index)) | ||||
| 	{ | ||||
| 		ControlledRoleIndex = Index; | ||||
| 		return RoleRoster[ControlledRoleIndex]; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| FVector2D ALevelPlayerState::GetSpawnLocation()const | ||||
| { | ||||
| 	return FVector2D::ZeroVector; | ||||
|  | ||||
| @ -54,9 +54,16 @@ inline static IGameMapInterface * GetMapActor(const UActorComponent* Component) | ||||
| void UStaticResourceLayerComponent::GenerateResources() | ||||
| { | ||||
| 	TArray<FVector2D> ResourcePoints; | ||||
|  | ||||
| 	// 生成资源点 | ||||
| 	GenerateResourcePoints(ResourcePoints); | ||||
| 	 | ||||
| 	// 生成必定生成的资源 | ||||
| 	GenerateAlwaysPresentInfo(ResourcePoints); | ||||
|  | ||||
| 	// 利用剩下的资源点,根据权重生成资源 | ||||
| 	GenerateResourceByWeight(ResourcePoints); | ||||
|  | ||||
| 	AActor *Owner = GetOwner(); | ||||
| 	UWorld* World =	GetWorld(); | ||||
| 	 | ||||
| @ -115,6 +122,34 @@ void UStaticResourceLayerComponent::GetAlwaysPresentResourceList(TMap<FName, int | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #pragma optimize("",off) | ||||
| bool UStaticResourceLayerComponent::GetCanGenerateResourcesWeight(const FVector2D& Position, | ||||
| 	TArray<TTuple<FName, int>>& OutResourcesWeight) const | ||||
| { | ||||
| 	using FTuple = TTuple<FName, int>; | ||||
|  | ||||
| 	AActor *Owner; | ||||
| 	IGameMapInterface * MapInterface; | ||||
| 	OutResourcesWeight.Empty(); | ||||
| 	 | ||||
| 	if (!GetOwnerInfo(Owner, MapInterface)) return false; | ||||
| 	if (!GenerateConfig) return false; | ||||
|  | ||||
| 	FGameplayTag &&Terrain = MapInterface->Execute_GetTerrainAt(Owner, Position.X, Position.Y); | ||||
| 	if (!Terrain.IsValid()) return false; | ||||
|  | ||||
| 	for (const auto& Pair : GenerateConfig->GetRowMap()) | ||||
| 	{ | ||||
| 		const FStaticResourceGenerateConfig* RowData = reinterpret_cast<FStaticResourceGenerateConfig*>(Pair.Value); | ||||
| 		if (!RowData->TerrainTypes.HasTag(Terrain)) continue; | ||||
| 		const float *TerrainWeightFindResult = RowData->TerrainWeights.Find(Terrain); | ||||
| 		float TotalWeight = RowData->GenerateWeight * (TerrainWeightFindResult ? *TerrainWeightFindResult : 1.0); | ||||
| 		OutResourcesWeight.Add(FTuple(Pair.Key, TotalWeight)); | ||||
| 	} | ||||
| 	return !OutResourcesWeight.IsEmpty(); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>& ResourcePoints) | ||||
| { | ||||
| 	AActor *Owner = GetOwner(); | ||||
| @ -143,7 +178,8 @@ bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>& | ||||
|  | ||||
| 		if (Config->TerrainTypes.HasTag(CurrentTerrain))  // 资源的地形配置包含当前的地形,则添加进生成的列表 | ||||
| 		{ | ||||
| 			GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(CurrentSelected, FVector2D(ResourcePoints[i].X, ResourcePoints[i].Y))); | ||||
| 			TryPushGenerateResult(CurrentSelected, CurrentPoint); | ||||
| 			// GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(CurrentSelected, FVector2D(ResourcePoints[i].X, ResourcePoints[i].Y))); | ||||
| 			ConsumeOneOfAlwaysPresent(AlwaysPresentResource, CurrentSelected); | ||||
| 			ResourcePoints[i].X = ResourcePoints[i].Y = -1; | ||||
| 			UE_LOG(LogMapGenerate, Log, TEXT("UStaticResourceLayerComponent::GenerateAlwaysPresentInfo Create %s at (%d, %d)"), | ||||
| @ -164,3 +200,52 @@ bool UStaticResourceLayerComponent::GenerateAlwaysPresentInfo(TArray<FVector2D>& | ||||
| 	ResourcePoints.RemoveAll([](const FVector2D Element){ return Element.X < 0 && Element.Y < 0; }); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void UStaticResourceLayerComponent::GenerateResourceByWeight(TArray<FVector2D>& ResourcePoints) | ||||
| { | ||||
| 	using FTuple = TTuple<FName, int>; | ||||
| 	TArray<TTuple<FName, int>> ResourceWeightList; | ||||
| 	for (const FVector2D& Point : ResourcePoints) | ||||
| 	{ | ||||
| 		ResourceWeightList.Empty(); | ||||
| 		if (!GetCanGenerateResourcesWeight(Point, ResourceWeightList)) continue; | ||||
|  | ||||
| 		float Base = 0.f; | ||||
| 		const float RandNum = static_cast<float>(FMath::Rand()) / static_cast<float>(RAND_MAX); | ||||
|  | ||||
| 		const float TotalWeight = Algo::Accumulate(ResourceWeightList, 0.f, [](const float Sum, const FTuple& Element) | ||||
| 		{ | ||||
| 			return Sum + Element.Value; | ||||
| 		}); | ||||
|  | ||||
| 		for (FTuple& Element : ResourceWeightList) | ||||
| 		{ | ||||
| 			const float RandomBolder = Base + Element.Value / TotalWeight; | ||||
| 			if (RandNum >= Base && RandNum < RandomBolder) | ||||
| 			{ | ||||
| 				TryPushGenerateResult(Element.Key, Point); | ||||
| 				break; | ||||
| 			} | ||||
| 			Base = RandomBolder; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #pragma optimize("",on) | ||||
|  | ||||
|  | ||||
| void UStaticResourceLayerComponent::TryPushGenerateResult(const FName& ResourceID, const FVector2D& Position) | ||||
| { | ||||
| 	GeneratedResourcePoints.Add(TTuple<FName, FVector2D>(ResourceID, Position)); | ||||
| } | ||||
|  | ||||
| bool UStaticResourceLayerComponent::GetOwnerInfo(AActor*& Owner, IGameMapInterface*& MapInterface) const | ||||
| { | ||||
| 	AActor *SelfOwner = GetOwner(); | ||||
| 	if (!SelfOwner) return false; | ||||
| 	IGameMapInterface * OwnerMapInterface = Cast<IGameMapInterface>(SelfOwner); | ||||
| 	if (!OwnerMapInterface) return false; | ||||
| 	Owner = SelfOwner; | ||||
| 	MapInterface = OwnerMapInterface; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @ -21,8 +21,6 @@ public: | ||||
|  | ||||
| 	virtual void BeginPlay()override; | ||||
|  | ||||
| 	virtual void UpdateMoveDirection_Implementation(const FVector2D& InDirection) override; | ||||
|  | ||||
| 	virtual float GetSpeed_Implementation()const override; | ||||
|  | ||||
| protected: | ||||
|  | ||||
| @ -15,9 +15,9 @@ public: | ||||
|  | ||||
| 	UFUNCTION(BlueprintNativeEvent) | ||||
| 	float GetSpeed() const; | ||||
| 	 | ||||
|  | ||||
| 	UFUNCTION(BlueprintNativeEvent, Category = "Movement") | ||||
| 	void UpdateMoveDirection(const FVector2D &InDirection); | ||||
| 	void OnMoveDirectionChanged(const FVector2D &InDirection); | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| @ -33,12 +33,30 @@ public: | ||||
| 	UFUNCTION(BlueprintCallable) | ||||
| 	void MoveTo(const FVector2D& Target); | ||||
|  | ||||
| 	/** | ||||
| 	 * 获取当前移动的方向 | ||||
| 	 * @return 返回朝向的单位向量,如果没动返回(0,0) | ||||
| 	 */ | ||||
| 	UFUNCTION(BlueprintCallable) | ||||
| 	FVector2D GetMoveDirection()const; | ||||
|  | ||||
| 	/** | ||||
| 	 * 获取当前朝向 | ||||
| 	 * @return  返回当前朝向的单位向量,如果没动,返回上一次运动时的朝向 | ||||
| 	 */ | ||||
| 	UFUNCTION(BlueprintCallable) | ||||
| 	FVector2D GetForwardDirection()const; | ||||
|  | ||||
| 	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)override; | ||||
|  | ||||
| protected: | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly) | ||||
| 	FVector2D MoveTargetLocation; | ||||
|  | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly) | ||||
| 	FVector2D LastMoveDirection; | ||||
|  | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly) | ||||
| 	FVector2D ForwardDirection; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| @ -85,6 +85,8 @@ public: // 输入相关 | ||||
| 	UPROPERTY(EditDefaultsOnly, Category = "Input") | ||||
| 	TObjectPtr<class UInputAction> CameraDetachAction;  // 相机脱离 | ||||
|  | ||||
| 	UPROPERTY(EditDefaultsOnly, Category = "Input") | ||||
| 	TObjectPtr<class UInputAction> SwitchRoleAction;  // 切换控制的角色 | ||||
|  | ||||
| public: | ||||
| 	UFUNCTION() | ||||
| @ -99,6 +101,9 @@ public: | ||||
| 	UFUNCTION() | ||||
| 	void OnCameraDetach(const FInputActionValue& Value); | ||||
|  | ||||
| 	UFUNCTION() | ||||
| 	void OnSwitchRole(const FInputActionValue& Value); | ||||
|  | ||||
|  | ||||
| protected: | ||||
| 	UPROPERTY() | ||||
|  | ||||
| @ -26,6 +26,9 @@ public: // 给蓝图的Get接口 | ||||
| 	UFUNCTION(BlueprintCallable) | ||||
| 	ABusyPlayerRole* GetControlledRole() const; | ||||
|  | ||||
| public: | ||||
| 	UFUNCTION(BlueprintCallable) | ||||
| 	ABusyPlayerRole* SwitchControlledRole(int32 Index); | ||||
|  | ||||
| protected: | ||||
| 	virtual FVector2D GetSpawnLocation()const; | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include "StaticResourceLayerComponent.generated.h" | ||||
|  | ||||
|  | ||||
| class IGameMapInterface; | ||||
|  | ||||
| USTRUCT(BlueprintType, Blueprintable) | ||||
| struct FStaticResourceGenerateConfig: public FTableRowBase | ||||
| @ -17,11 +18,15 @@ struct FStaticResourceGenerateConfig: public FTableRowBase | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成的最少数量") | ||||
| 	int MinGenerateCount = 0; | ||||
|  | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="可以在哪些地形生成") | ||||
| 	FGameplayTagContainer TerrainTypes; | ||||
|  | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成权重") | ||||
| 	int GenerateWeight = 1; | ||||
|  | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="可以在哪些地形生成") | ||||
| 	FGameplayTagContainer TerrainTypes; | ||||
| 	// 在这种地形上,最终的权重为 [生成权重]*[地形权重系数],若地形权重系数没有配置,默认为1.0 | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="地形权重系数", meta = (ClampMin = "0.0")) | ||||
| 	TMap<FGameplayTag, float> TerrainWeights; | ||||
|  | ||||
| 	// 用于该资源生成时应该与某些资源保持多远的距离 | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName="生成距离规则") | ||||
| @ -39,14 +44,27 @@ class UStaticResourceLayerComponent :public UActorComponent | ||||
| public: | ||||
| 	void GenerateResources(); | ||||
|  | ||||
| protected: // get | ||||
| 	void GetAlwaysPresentResourceList(TMap<FName, int32>& OutAlwaysPresentResource)const; | ||||
|  | ||||
| 	/**  | ||||
| 	 * 获取某个点所有能生成的资源权重列表 | ||||
| 	 * @param Position 给定点的位置 | ||||
| 	 * @param[out] OutResourcesWeight 给定点所处的地形能够生成的所有资源列表,包含资源ID和权重 | ||||
| 	 */ | ||||
| 	bool GetCanGenerateResourcesWeight(const FVector2D& Position, TArray<TTuple<FName, int>>& OutResourcesWeight)const; | ||||
| 	 | ||||
|  | ||||
|  | ||||
| protected: | ||||
| 	virtual void GenerateResourcePoints(TArray<FVector2D>& OutResourcePoint); | ||||
|  | ||||
| 	void GetAlwaysPresentResourceList(TMap<FName, int32>& OutAlwaysPresentResource)const; | ||||
|  | ||||
| 	bool GenerateAlwaysPresentInfo(TArray<FVector2D>& ResourcePoints); | ||||
|  | ||||
| 	void GenerateResourceByWeight(TArray<FVector2D>& ResourcePoints); | ||||
|  | ||||
| 	void TryPushGenerateResult(const FName& ResourceID, const FVector2D& Position); | ||||
| 	 | ||||
|  | ||||
| public: | ||||
| @ -58,6 +76,7 @@ public: | ||||
|  | ||||
| 	TArray<TTuple<FName, FVector2D>> GeneratedResourcePoints; | ||||
|  | ||||
| protected: | ||||
| private: | ||||
| 	bool GetOwnerInfo(AActor* &Owner, IGameMapInterface* &MapInterface) const; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user