惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
博客园_首页
宝玉的分享
宝玉的分享
S
SegmentFault 最新的问题
Jina AI
Jina AI
Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
美团技术团队
IT之家
IT之家
罗磊的独立博客
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
博客园 - 叶小钗
M
MIT News - Artificial intelligence
B
Blog RSS Feed
有赞技术团队
有赞技术团队
Y
Y Combinator Blog

博客园 - ParamousGIS

VS中CMakePresets的Path环境变量设置 VTK 类结构图 VSCode的C++项目缓存目录 VMWare Workstation 17.6安装Windows7 awesome-cpp 矢量切片工具--SparkVectorTileTool dll生成lib 自动布局 C++第三方库 QT + CMake环境配置 应用clang-format对c++代码时进行格式化 UE5--022--2D Blend Spaces UE5--025--SuperSideScrollerGame--004--AnimBP--AnimMontage UE5--024--SuperSideScrollerGame--003--AIController UE5--023--SuperSideScrollerGame--002 UE5--021--Animation Montage UE5--020--Material Instances UE5--019--LayeredBlendPerBone UE5--018--BlendSpace--AnimGraph
UE5--022--SuperSideScrollerGame--001
ParamousGIS · 2025-04-12 · via 博客园 - ParamousGIS

1. ASuperSideScrollerGameMode

1.1 ASuperSideScrollerGameMode.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "SuperSideScrollerGameMode.generated.h"

UCLASS(minimalapi)
class ASuperSideScrollerGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    ASuperSideScrollerGameMode();
};

1.2 ASuperSideScrollerGameMode.cpp

#include "SuperSideScrollerGameMode.h"
#include "SuperSideScrollerCharacter.h"
#include "UObject/ConstructorHelpers.h"

ASuperSideScrollerGameMode::ASuperSideScrollerGameMode()
{
    // set default pawn class to our Blueprinted character
    static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter"));
    if (PlayerPawnBPClass.Class != NULL)
    {
        DefaultPawnClass = PlayerPawnBPClass.Class;
    }
}

3.3 BP_SuperSideScroller_GameMode

image

2. ASuperSideScrollerCharacter

2.1 ASuperSideScrollerCharacter.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Logging/LogMacros.h"
#include "SuperSideScrollerCharacter.generated.h"

class USpringArmComponent;
class UCameraComponent;
class UInputMappingContext;
class UInputAction;
struct FInputActionValue;

DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All);

UCLASS(config=Game)
class ASuperSideScrollerCharacter : public ACharacter
{
    GENERATED_BODY()

    /** Camera boom positioning the camera behind the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    USpringArmComponent* CameraBoom;

    /** Follow camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    UCameraComponent* FollowCamera;
    
    /** MappingContext */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
    UInputMappingContext* DefaultMappingContext;

    /** Jump Input Action */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
    UInputAction* JumpAction;

    /** Move Input Action */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
    UInputAction* MoveAction;

    /** Look Input Action */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
    UInputAction* LookAction;

public:
    ASuperSideScrollerCharacter();
    

protected:

    /** Called for movement input */
    void Move(const FInputActionValue& Value);

    /** Called for looking input */
    void Look(const FInputActionValue& Value);
            

protected:
    // APawn interface
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
    // To add mapping context
    virtual void BeginPlay();

public:
    /** Returns CameraBoom subobject **/
    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
    /** Returns FollowCamera subobject **/
    FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
};

2.2 ASuperSideScrollerCharacter.cpp

#include "SuperSideScrollerCharacter.h"
#include "Engine/LocalPlayer.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/Controller.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"

DEFINE_LOG_CATEGORY(LogTemplateCharacter);

//////////////////////////////////////////////////////////////////////////
// ASuperSideScrollerCharacter

ASuperSideScrollerCharacter::ASuperSideScrollerCharacter()
{
    // Set size for collision capsule
    GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
        
    // Don't rotate when the controller rotates. Let that just affect the camera.
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;

    // Configure character movement
    GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...    
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // ...at this rotation rate

    // Note: For faster iteration times these variables, and many more, can be tweaked in the Character Blueprint
    // instead of recompiling to adjust them
    GetCharacterMovement()->JumpZVelocity = 700.f;
    GetCharacterMovement()->AirControl = 0.35f;
    GetCharacterMovement()->MaxWalkSpeed = 500.f;
    GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
    GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
    GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f;

    // Create a camera boom (pulls in towards the player if there is a collision)
    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    CameraBoom->SetupAttachment(RootComponent);
    CameraBoom->TargetArmLength = 400.0f; // The camera follows at this distance behind the character    
    CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller

    // Create a follow camera
    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
    FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

    // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
    // are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
}

void ASuperSideScrollerCharacter::BeginPlay()
{
    // Call the base class  
    Super::BeginPlay();
}

//////////////////////////////////////////////////////////////////////////
// Input

void ASuperSideScrollerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    // Add Input Mapping Context
    if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
    {
        if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
        {
            Subsystem->AddMappingContext(DefaultMappingContext, 0);
        }
    }
    
    // Set up action bindings
    if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
        
        // Jumping
        EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
        EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);

        // Moving
        EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ASuperSideScrollerCharacter::Move);

        // Looking
        //EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASuperSideScrollerCharacter::Look);
    }
    else
    {
        UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
    }
}

void ASuperSideScrollerCharacter::Move(const FInputActionValue& Value)
{
    // input is a Vector2D
    FVector2D MovementVector = Value.Get<FVector2D>();

    if (Controller != nullptr)
    {
        // find out which way is forward
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);

        // get forward vector
        const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
    
        // get right vector 
        const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

        // add movement 
        AddMovementInput(ForwardDirection, MovementVector.Y);
        AddMovementInput(RightDirection, MovementVector.X);
    }
}

void ASuperSideScrollerCharacter::Look(const FInputActionValue& Value)
{
    // input is a Vector2D
    FVector2D LookAxisVector = Value.Get<FVector2D>();

    if (Controller != nullptr)
    {
        // add yaw and pitch input to controller
        AddControllerYawInput(LookAxisVector.X);
        AddControllerPitchInput(LookAxisVector.Y);
    }
}

3. ASuperSideScroller_Player

3.1 ASuperSideScroller_Player.h

#pragma once

#include "CoreMinimal.h"
#include "SuperSideScroller/SuperSideScrollerCharacter.h"
#include "SuperSideScroller_Player.generated.h"

/**
 *
 */
UCLASS()
class SUPERSIDESCROLLER_API ASuperSideScroller_Player : public ASuperSideScrollerCharacter
{
    GENERATED_BODY()

private:
    //Bool to control if we are sprinting. Failsafe.
    bool bIsSprinting;

    UPROPERTY(EditAnywhere)
    class UAnimMontage* ThrowMontage;

    UPROPERTY(EditAnywhere)
    TSubclassOf<class APlayerProjectile> PlayerProjectile;

    int32 NumberofCollectables;

    FTimerHandle PowerupHandle;

    bool bHasPowerupActive;


public:
    //Constructor
    ASuperSideScroller_Player();

    void SpawnProjectile();

    UFUNCTION(BlueprintPure)
    int32 GetCurrentNumberofCollectables() {
        return NumberofCollectables;
    };

    void IncrementNumberofCollectables(int32 Value);

    void IncreaseMovementPowerup();

    void EndPowerup();


protected:

    UPROPERTY(EditAnywhere, Category = "Input")
    class UInputMappingContext* IC_Character;

    UPROPERTY(EditAnywhere, Category = "Input")
    class UInputAction* IA_Sprint;

    UPROPERTY(EditAnywhere, Category = "Input")
    class UInputAction* IA_Throw;

    //Override base character class function to setup our player input component
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

    //Sprinting
    void Sprint();

    //StopSprinting
    void StopSprinting();

    //Throw Projectile
    void ThrowProjectile();

};

3.2 ASuperSideScroller_Player.cpp

#include "SuperSideScroller_Player.h"
#include "Components/InputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Animation/AnimInstance.h"
#include "PlayerProjectile.h"
#include "Engine/World.h"
#include "Components/SphereComponent.h"
#include "TimerManager.h"

ASuperSideScroller_Player::ASuperSideScroller_Player()
{
    //Set sprinting to false by default.
    bIsSprinting = false;
    //Set our max Walk Speed to 300.0f
    GetCharacterMovement()->MaxWalkSpeed = 300.0f;
}

void ASuperSideScroller_Player::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) {
    //Not always necessary, but good practice to call the function inthe base class with Super.
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    UEnhancedInputComponent* EnhancedPlayerInput = Cast<UEnhancedInputComponent>(PlayerInputComponent);
    if (EnhancedPlayerInput)
    {
        // 
        APlayerController* PlayerController = Cast<APlayerController>(GetController());
        UEnhancedInputLocalPlayerSubsystem* EnhancedSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
        if (EnhancedSubsystem)
        {
            EnhancedSubsystem->AddMappingContext(IC_Character, 1);
        }

        //Bind pressed action Sprint to your Sprint function
        EnhancedPlayerInput->BindAction(IA_Sprint, ETriggerEvent::Triggered, this, &ASuperSideScroller_Player::Sprint);
        //Bind released action Sprint to your StopSprinting function
        EnhancedPlayerInput->BindAction(IA_Sprint, ETriggerEvent::Completed, this, &ASuperSideScroller_Player::StopSprinting);
        //Bind the pressed action Throw to your ThrowProjectile function
        EnhancedPlayerInput->BindAction(IA_Throw, ETriggerEvent::Triggered, this, &ASuperSideScroller_Player::ThrowProjectile);
    }
}

void ASuperSideScroller_Player::Sprint()
{
    if (!bIsSprinting)
    {
        bIsSprinting = true;
        if (bHasPowerupActive)
        {
            GetCharacterMovement()->MaxWalkSpeed = 900.0f;
        }
        else
        {
            GetCharacterMovement()->MaxWalkSpeed = 500.0f;
        }
    }

}

void ASuperSideScroller_Player::StopSprinting()
{
    if (bIsSprinting)
    {
        bIsSprinting = false;
        GetCharacterMovement()->MaxWalkSpeed = 300.0f;
    }
}

void ASuperSideScroller_Player::ThrowProjectile() {

    UE_LOG(LogTemp, Warning, TEXT("THROW PROJECTILE"));
    if (ThrowMontage)
    {
        const bool bIsMontagePlaying = GetMesh()->GetAnimInstance()->Montage_IsPlaying(ThrowMontage);
        if (!bIsMontagePlaying)
        {
            GetMesh()->GetAnimInstance()->Montage_Play(ThrowMontage, 1.0f);
        }
    }
}

void ASuperSideScroller_Player::SpawnProjectile()
{
    if (PlayerProjectile)
    {
        UWorld* World = GetWorld();
        if (World)
        {
            FActorSpawnParameters SpawnParams;
            SpawnParams.Owner = this;
            //
            const FVector SpawnLocation = this->GetMesh() -> GetSocketLocation(FName("ProjectileSocket"));
            const FRotator Rotation = GetActorForwardVector().Rotation();
            //
            APlayerProjectile* Projectile = World -> SpawnActor<APlayerProjectile>(PlayerProjectile, SpawnLocation, Rotation, SpawnParams);
        }
    }
}

void ASuperSideScroller_Player::IncrementNumberofCollectables(int32 Value)
{
    if (Value == 0)
    {
        return;
    }
    else
    {
        NumberofCollectables += Value;
    }
    UE_LOG(LogTemp, Warning, TEXT("Number of Coins: %d"), NumberofCollectables);
}


void ASuperSideScroller_Player::IncreaseMovementPowerup()
{
    bHasPowerupActive = true;
    GetCharacterMovement()->MaxWalkSpeed = 500.0f;
    GetCharacterMovement()->JumpZVelocity = 1500.0f;
    UWorld* World = GetWorld();
    if (World)
    {
        World->GetTimerManager().SetTimer(PowerupHandle, this, &ASuperSideScroller_Player::EndPowerup, 8.0f, false);

    }

}

void ASuperSideScroller_Player::EndPowerup()
{
    bHasPowerupActive = false;
    GetCharacterMovement()->MaxWalkSpeed = 300.0f;
    GetCharacterMovement()->JumpZVelocity = 1000.0f;
    UWorld* World = GetWorld();
    if (World)
    {
        World->GetTimerManager().ClearTimer(PowerupHandle);
    }
}

3.3 BP_SuperSideScroller_MainCharacter

image

4. ASuperSideScroller_Controller

4.1 ASuperSideScroller_Controller.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "SuperSideScroller_Controller.generated.h"

/**
 * 
 */
UCLASS()
class SUPERSIDESCROLLER_API ASuperSideScroller_Controller : public APlayerController
{
    GENERATED_BODY()
    
};

4.2 ASuperSideScroller_Controller.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "SuperSideScroller_Controller.h"

4.3 BP_SuperSideScroller_PC

image

5. APlayerProjectile

5.1 APlayerProjectile.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlayerProjectile.generated.h"

UCLASS()
class SUPERSIDESCROLLER_API APlayerProjectile : public AActor
{
    GENERATED_BODY()

public:
    // Sets default values for this actor's properties
    APlayerProjectile();

protected:
    // Called when the game starts or when spawned
    //virtual void BeginPlay() override;

public:
    // Called every frame
    //virtual void Tick(float DeltaTime) override;

    //Sphere collision component
    UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
    class USphereComponent* CollisionComp;

    UFUNCTION()
    void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

    void ExplodeProjectile();

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    class UParticleSystem* DestroyEffect;

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    class USoundBase* DestroySound;

private:
    // Projectile movement component
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = "true"))
    class UProjectileMovementComponent* ProjectileMovement;

    //Static mesh component
    UPROPERTY(EditAnywhere, Category = Projectile)
    class UStaticMeshComponent* MeshComp;

    UPROPERTY(VisibleDefaultsOnly, Category = Sound)
    class UAudioComponent* ProjectileMovementSound;

    UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
    class UParticleSystemComponent* ProjectileEffect;
};

5.2 APlayerProjectile.cpp

#include "PlayerProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"
#include "EnemyBase.h"
#include "Components/AudioComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
APlayerProjectile::APlayerProjectile()
{
     // 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;

    CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
    CollisionComp->InitSphereRadius(15.0f);
    CollisionComp->BodyInstance.SetCollisionProfileName("BlockAll");
    CollisionComp->OnComponentHit.AddDynamic(this, &APlayerProjectile::OnHit);
    // Set as root component
    RootComponent = CollisionComp;

    // Use a ProjectileMovementComponent to govern this projectile's movement
    ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
    ProjectileMovement->UpdatedComponent = CollisionComp;
    ProjectileMovement->ProjectileGravityScale = 0.0f;
    ProjectileMovement->InitialSpeed = 800.0f;
    ProjectileMovement->MaxSpeed = 800.0f;

    MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
    MeshComp->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);

    InitialLifeSpan = 3.0f;

    //
    ProjectileMovementSound = CreateDefaultSubobject<UAudioComponent>(TEXT("ProjectileMovementSound"));
    ProjectileMovementSound->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);

    ProjectileEffect = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("ProjectileEffect"));
    ProjectileEffect->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);


}

// Called when the game starts or when spawned
//void APlayerProjectile::BeginPlay()
//{
//    Super::BeginPlay();
//    
//}

// Called every frame
//void APlayerProjectile::Tick(float DeltaTime)
//{
//    Super::Tick(DeltaTime);
//
//}

void APlayerProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
    UE_LOG(LogTemp, Warning, TEXT("HIT"));
    AEnemyBase* Enemy = Cast<AEnemyBase>(OtherActor);
    if (Enemy)
    {
        Enemy->DestroyEnemy();
    }
    ExplodeProjectile();
}

void APlayerProjectile::ExplodeProjectile()
{
    UWorld* World = GetWorld();
    if (World)
    {
        if (DestroyEffect)
        {
            UGameplayStatics::SpawnEmitterAtLocation(World, DestroyEffect, GetActorTransform());
        }
        if (DestroySound)
        {
            UGameplayStatics::SpawnSoundAtLocation(World, DestroySound, GetActorLocation());
        }
    }

    Destroy();
}

5.3 BP_PlayerProjectile

image